<?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=Philosopher</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=Philosopher"/>
	<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/Special:Contributions/Philosopher"/>
	<updated>2026-05-19T13:21:12Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Conditions&amp;diff=84774</id>
		<title>Conditions</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Conditions&amp;diff=84774"/>
		<updated>2015-05-21T04:22:18Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: yes you can use strings too. Note that it does not guarantee type conversion: if the left one is a string, there will be no numeric comparison&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
'''Conditions''' (or '''SGConditions''') in the SimGear library are a property-based representation of custom conditions based on comparing property values. They can be evaluated from both C++ and Nasal (see simgear/props/condition.hxx and [[$FG_ROOT]]/Nasal/props.nas). Comparison of string-typed properties involves lexicographic ordering, as specified by the C++ operators &amp;lt;tt&amp;gt;&amp;amp;lt;&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;&amp;amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
Conditions are supported in&lt;br /&gt;
* All [[bindings]], all [[animations]]&lt;br /&gt;
* State machines&lt;br /&gt;
* Various parts of [[HUD]]s, 2D panels&lt;br /&gt;
And several other places.&lt;br /&gt;
&lt;br /&gt;
== Sample Expressions ==&lt;br /&gt;
This is a sample expression for checking if the throttle on the first engine is above half:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;condition&amp;gt;&lt;br /&gt;
  &amp;lt;greater-than&amp;gt;&lt;br /&gt;
    &amp;lt;property&amp;gt;/controls/engines/engine[0]/throttle&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;value type=&amp;quot;double&amp;quot;&amp;gt;0.5&amp;lt;/value&amp;gt;&lt;br /&gt;
  &amp;lt;/greater-than&amp;gt;&lt;br /&gt;
&amp;lt;/condition&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Supported elements ==&lt;br /&gt;
Each comparison (like less-than or greater-than-equals) requires either two &amp;lt;tt&amp;gt;&amp;amp;lt;property&amp;amp;gt;&amp;lt;/tt&amp;gt; elements (the first with index=0 and the second with index=1) or a &amp;lt;tt&amp;gt;&amp;amp;lt;property&amp;amp;gt;&amp;lt;/tt&amp;gt; (considered first) and &amp;lt;tt&amp;gt;&amp;amp;lt;value&amp;amp;gt;&amp;lt;/tt&amp;gt; (considered second); booleans compare each of their child conditions. A &amp;lt;tt&amp;gt;&amp;amp;lt;condition&amp;amp;gt;&amp;lt;/tt&amp;gt; element itself functions as an &amp;lt;tt&amp;gt;&amp;amp;lt;and&amp;amp;gt;&amp;lt;/tt&amp;gt; element; that is, it can have several children, all of which must be true to make the whole condition true.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;and&amp;gt;&lt;br /&gt;
&amp;lt;or&amp;gt;&lt;br /&gt;
&amp;lt;not&amp;gt; &amp;lt;!-- acts like logical inverse of &amp;lt;and&amp;gt;, i.e. accepts child conditions --&amp;gt;&lt;br /&gt;
&amp;lt;equals&amp;gt;&lt;br /&gt;
&amp;lt;not-equals&amp;gt;&lt;br /&gt;
&amp;lt;less-than&amp;gt;&lt;br /&gt;
&amp;lt;greater-than&amp;gt;&lt;br /&gt;
&amp;lt;less-than-equals&amp;gt;&lt;br /&gt;
&amp;lt;greater-than-equals&amp;gt;&lt;br /&gt;
&amp;lt;property&amp;gt; &amp;lt;!-- evaluates boolean value of specified property --&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
=== Readme file ===&lt;br /&gt;
* {{readme file|conditions}}&lt;br /&gt;
&lt;br /&gt;
=== Source code ===&lt;br /&gt;
* {{repo link&lt;br /&gt;
| site   = sf&lt;br /&gt;
| proj   = flightgear/simgear&lt;br /&gt;
| path   = next/tree/simgear/props/condition.hxx&lt;br /&gt;
| text   = simgear/props/condition.hxx&lt;br /&gt;
}}&lt;br /&gt;
* {{repo link&lt;br /&gt;
| site   = sf&lt;br /&gt;
| proj   = flightgear/simgear&lt;br /&gt;
| path   = next/tree/simgear/props/condition.cxx&lt;br /&gt;
| text   = simgear/props/condition.cxx&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear]]&lt;br /&gt;
[[Category:XML]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Conditions&amp;diff=84773</id>
		<title>Conditions</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Conditions&amp;diff=84773"/>
		<updated>2015-05-21T04:17:06Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Supported elements */ rephrase/grammar/code-language mix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
'''Conditions''' (or '''SGConditions''') in the SimGear library are a property-based representation of custom conditions based on comparing property values. They can be evaluated from both C++ and Nasal (see simgear/props/condition.hxx and [[$FG_ROOT]]/Nasal/props.nas).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
Conditions are supported in&lt;br /&gt;
* All [[bindings]], all [[animations]]&lt;br /&gt;
* State machines&lt;br /&gt;
* Various parts of [[HUD]]s, 2D panels&lt;br /&gt;
And several other places.&lt;br /&gt;
&lt;br /&gt;
== Sample Expressions ==&lt;br /&gt;
This is a sample expression for checking if the throttle on the first engine is above half:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;condition&amp;gt;&lt;br /&gt;
  &amp;lt;greater-than&amp;gt;&lt;br /&gt;
    &amp;lt;property&amp;gt;/controls/engines/engine[0]/throttle&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;lt;value type=&amp;quot;double&amp;quot;&amp;gt;0.5&amp;lt;/value&amp;gt;&lt;br /&gt;
  &amp;lt;/greater-than&amp;gt;&lt;br /&gt;
&amp;lt;/condition&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Supported elements ==&lt;br /&gt;
Each comparison (like less-than or greater-than-equals) requires either two &amp;lt;tt&amp;gt;&amp;amp;lt;property&amp;amp;gt;&amp;lt;/tt&amp;gt; elements (the first with index=0 and the second with index=1) or a &amp;lt;tt&amp;gt;&amp;amp;lt;property&amp;amp;gt;&amp;lt;/tt&amp;gt; (considered first) and &amp;lt;tt&amp;gt;&amp;amp;lt;value&amp;amp;gt;&amp;lt;/tt&amp;gt; (considered second); booleans compare each of their child conditions. A &amp;lt;tt&amp;gt;&amp;amp;lt;condition&amp;amp;gt;&amp;lt;/tt&amp;gt; element itself functions as an &amp;lt;tt&amp;gt;&amp;amp;lt;and&amp;amp;gt;&amp;lt;/tt&amp;gt; element; that is, it can have several children, all of which must be true to make the whole condition true.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;and&amp;gt;&lt;br /&gt;
&amp;lt;or&amp;gt;&lt;br /&gt;
&amp;lt;not&amp;gt; &amp;lt;!-- acts like logical inverse of &amp;lt;and&amp;gt;, i.e. accepts child conditions --&amp;gt;&lt;br /&gt;
&amp;lt;equals&amp;gt;&lt;br /&gt;
&amp;lt;not-equals&amp;gt;&lt;br /&gt;
&amp;lt;less-than&amp;gt;&lt;br /&gt;
&amp;lt;greater-than&amp;gt;&lt;br /&gt;
&amp;lt;less-than-equals&amp;gt;&lt;br /&gt;
&amp;lt;greater-than-equals&amp;gt;&lt;br /&gt;
&amp;lt;property&amp;gt; &amp;lt;!-- evaluates boolean value of specified property --&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
=== Readme file ===&lt;br /&gt;
* {{readme file|conditions}}&lt;br /&gt;
&lt;br /&gt;
=== Source code ===&lt;br /&gt;
* {{repo link&lt;br /&gt;
| site   = sf&lt;br /&gt;
| proj   = flightgear/simgear&lt;br /&gt;
| path   = next/tree/simgear/props/condition.hxx&lt;br /&gt;
| text   = simgear/props/condition.hxx&lt;br /&gt;
}}&lt;br /&gt;
* {{repo link&lt;br /&gt;
| site   = sf&lt;br /&gt;
| proj   = flightgear/simgear&lt;br /&gt;
| path   = next/tree/simgear/props/condition.cxx&lt;br /&gt;
| text   = simgear/props/condition.cxx&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear]]&lt;br /&gt;
[[Category:XML]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Use_vectors_and_foreach_loops_to_write_shorter_code&amp;diff=78954</id>
		<title>Howto:Use vectors and foreach loops to write shorter code</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Use_vectors_and_foreach_loops_to_write_shorter_code&amp;diff=78954"/>
		<updated>2015-01-07T15:19:50Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: use separate arguments to setprop() instead of concatenation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
* Last updated: 02/2012&lt;br /&gt;
* Contributors: Omega95, Hooray&lt;br /&gt;
&lt;br /&gt;
Objective: Demonstrate how the use of [[Nasal]] vectors and foreach loops may help to create shorter and less redundant Nasal code. &lt;br /&gt;
&lt;br /&gt;
Consider the following snippet of code, taken from [[Howto: Implement a Flight Management Computer in Nasal]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l1-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l2-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l3-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l4-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l5-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l6-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/l7-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, this is a fairly repetitive piece of code, which could be easily generalized, so that only a single setprop() call is used in a loop (foreach). It could be rewritten like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
 var lines = [&amp;quot;l1-type&amp;quot;, &amp;quot;l2-type&amp;quot;, &amp;quot;l3-type&amp;quot;, &amp;quot;l4-type&amp;quot;, &amp;quot;l5-type&amp;quot;, &amp;quot;l6-type&amp;quot;, &amp;quot;l7-type&amp;quot;];&lt;br /&gt;
 foreach(var line; lines) {&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu&amp;quot;, cdu, line, &amp;quot;click&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you could also use a small helper function (method):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
 var init_lines= func {&lt;br /&gt;
  var lines = [&amp;quot;l1-type&amp;quot;, &amp;quot;l2-type&amp;quot;, &amp;quot;l3-type&amp;quot;, &amp;quot;l4-type&amp;quot;, &amp;quot;l5-type&amp;quot;, &amp;quot;l6-type&amp;quot;, &amp;quot;l7-type&amp;quot;];&lt;br /&gt;
  foreach(var line; lines) {&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu&amp;quot;, cdu, line, &amp;quot;click&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The nice thing is, that we get less code, which is more general - i.e. it will be much easier to change things later on, so that support for more CDU/FMC lines could be added easily for example.&lt;br /&gt;
&lt;br /&gt;
Now, when looking through the code in [[Howto: Implement a Flight Management Computer in Nasal]], we can find more code, which looks fairly similar:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r1-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r2-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r3-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r4-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r5-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r6-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/r7-type&amp;quot;, &amp;quot;click&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only thing different here is that we have &amp;quot;r1..r7-type&amp;quot; rather than &amp;quot;l1..l7&amp;quot;. So, we could just take our previous function and generalize it some more:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
 var init_cdu_types= func(what) {&lt;br /&gt;
 foreach(var w; what) {&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu&amp;quot;, cdu, w, &amp;quot;click&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This could now be easily called during initialization to set up the properties like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
  var lines = [&amp;quot;l1-type&amp;quot;, &amp;quot;l2-type&amp;quot;, &amp;quot;l3-type&amp;quot;, &amp;quot;l4-type&amp;quot;, &amp;quot;l5-type&amp;quot;, &amp;quot;l6-type&amp;quot;, &amp;quot;l7-type&amp;quot;];&lt;br /&gt;
  init_cdu_types(lines);&lt;br /&gt;
&lt;br /&gt;
  var lines = [&amp;quot;r1-type&amp;quot;, &amp;quot;r2-type&amp;quot;, &amp;quot;r3-type&amp;quot;, &amp;quot;r4-type&amp;quot;, &amp;quot;r5-type&amp;quot;, &amp;quot;r6-type&amp;quot;, &amp;quot;r7-type&amp;quot;];&lt;br /&gt;
  init_cdu_types(lines);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, looking further through the code, there are more opportunities to generalize our little helper function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
  ## Field Values&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l1-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l2-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l3-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l4-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l5-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l6-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/l7-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r1-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r2-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r3-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r4-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r5-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r6-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu[&amp;quot; ~ cdu ~ &amp;quot;]/display/r7-label&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only thing that's different here, is the final setprop argument - which is empty in this case, so we could just change our function to support an additional argument:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
 var init_cdu_types= func(what,value=&amp;quot;click&amp;quot;) {&lt;br /&gt;
 foreach(var w; what) {&lt;br /&gt;
   setprop(&amp;quot;/controls/cdu&amp;quot;, cdu, w, value);&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that we have provided a default value here (which is &amp;quot;click&amp;quot;), so that the previous function calls don't need to be changed.&lt;br /&gt;
&lt;br /&gt;
With the changes in place, our init code could be made even shorter:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
  var lines = [&amp;quot;l1-type&amp;quot;, &amp;quot;l2-type&amp;quot;, &amp;quot;l3-type&amp;quot;, &amp;quot;l4-type&amp;quot;, &amp;quot;l5-type&amp;quot;, &amp;quot;l6-type&amp;quot;, &amp;quot;l7-type&amp;quot;];&lt;br /&gt;
  init_cdu_types(lines);&lt;br /&gt;
&lt;br /&gt;
  var lines = [&amp;quot;r1-type&amp;quot;, &amp;quot;r2-type&amp;quot;, &amp;quot;r3-type&amp;quot;, &amp;quot;r4-type&amp;quot;, &amp;quot;r5-type&amp;quot;, &amp;quot;r6-type&amp;quot;, &amp;quot;r7-type&amp;quot;];&lt;br /&gt;
  init_cdu_types(lines);&lt;br /&gt;
&lt;br /&gt;
  var lines = [&amp;quot;/display/l1-label&amp;quot;, &amp;quot;/display/l2-label&amp;quot;, &amp;quot;/display/l3-label&amp;quot;, &amp;quot;/display/l4-label&amp;quot;, &amp;quot;/display/l5-label&amp;quot;,&amp;quot;/display/l6-label&amp;quot;, &amp;quot;/display/l7-label&amp;quot;,&amp;quot;/display/r1-label&amp;quot;, &amp;quot;/display/r2-label&amp;quot;, &amp;quot;/display/r3-label&amp;quot;, &amp;quot;/display/r4-label&amp;quot;, &amp;quot;/display/r5-label&amp;quot;,&amp;quot;/display/r6-label&amp;quot;, &amp;quot;/display/r7-label&amp;quot;];&lt;br /&gt;
  init_cdu_types(lines,&amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, there are some more opportunities - such as automatically creating these vectors, too. Which is also trivial to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
 var create_with_suffix = func(prefix,start,end,suffix) {&lt;br /&gt;
 var result = [];&lt;br /&gt;
  for (var i=start;i&amp;lt;=end;i+=1) {&lt;br /&gt;
    var s= prefix ~ i ~ suffix;&lt;br /&gt;
    append(result,s);&lt;br /&gt;
  }&lt;br /&gt;
  return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, now we have a helper function, which automatically creates these vectors. Which can be used like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
 var left = create_with_suffix('l',1,7,'-type');&lt;br /&gt;
 var right = create_with_suffix('r',1,7,'-type');&lt;br /&gt;
&lt;br /&gt;
 var display_right = create_with_suffix('display/l',1,7,'-label');&lt;br /&gt;
 var display_left = create_with_suffix('display/r',1,7,'-label');&lt;br /&gt;
&lt;br /&gt;
 init_cdu_types(left);&lt;br /&gt;
 init_cdu_types(right);&lt;br /&gt;
 init_cdu_types(display_right);&lt;br /&gt;
 init_cdu_types(display_left);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal howto]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=76270</id>
		<title>Canvas snippets</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=76270"/>
		<updated>2014-09-14T20:15:40Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Canvas Input Dialog */ great idea!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{Stub}}&lt;br /&gt;
{{WIP}}&lt;br /&gt;
&lt;br /&gt;
{{Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Creating a Canvas GUI Window ==&lt;br /&gt;
{{Note|This example uses so called method chaining, if you're not familiar with the concept, please see: [[Object_Oriented_Programming_with_Nasal#More_on_methods:_Chaining|Method Chaining]].}}&lt;br /&gt;
&lt;br /&gt;
[[File:Snippets-canvas-dialog.png|thumb|This is what the [[Nasal]]/[[Canvas]] snippet will look like once you pasted it into the [[Nasal Console]] and click &amp;quot;Execute&amp;quot;.]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
# create a new window, dimensions are 320 x 160, using the dialog decoration (i.e. titlebar)&lt;br /&gt;
var window = canvas.Window.new([320,160],&amp;quot;dialog&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# adding a canvas to the new window and setting up background colors/transparency&lt;br /&gt;
var myCanvas = window.createCanvas().setColorBackground(1,1,1,1);&lt;br /&gt;
&lt;br /&gt;
# creating the top-level/root group which will contain all other elements/group&lt;br /&gt;
var root = myCanvas.createGroup();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Canvas Input Dialog ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
# create a new InputDialog with a title, label, and a callback&lt;br /&gt;
canvas.InputDialog.getText(&amp;quot;Input Dialog Title&amp;quot;, &amp;quot;Please enter some text&amp;quot;, func(btn,value) {&lt;br /&gt;
    if (value) gui.popupTip(&amp;quot;You entered: &amp;quot;~value);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=PLIB&amp;diff=75753</id>
		<title>PLIB</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=PLIB&amp;diff=75753"/>
		<updated>2014-08-31T12:42:34Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: Library GPL -&amp;gt; Lesser GPL ;-), note on Canvas' eventual replacement (soon!) of PUI&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''PLIB''' (Portable Game Library) is a set of software libraries for writing games written by Steve J. Baker. [[FlightGear]] has used PLIB for most of its development. It is also used by the FlightGear related program [[Atlas]]. PLIB is open source and released under Lesser GNU Public License (LGPL). &lt;br /&gt;
&lt;br /&gt;
[[FlightGear 1.0.0]] (released in 2007) was the last public release to use PLIB for the 3d scene graph, before the the transition to OpenSceneGraph ([[OSG]]). FlightGear still uses PLIB for various tasks, for example reading joystick inputs and showing a graphical user interface (GUI). In the latter usage, the PUI component of PLIB will be replaced in FlightGear with [[Canvas|Canvas 2D rendering subsystem]] and [[Nasal|Nasal scripting]] to improve the GUI beyond what PUI offers.&lt;br /&gt;
&lt;br /&gt;
PLIB is needed when building [[FlightGear]]. &lt;br /&gt;
&lt;br /&gt;
== PLIB libraries ==&lt;br /&gt;
* Picoscopic User Interface Library (PUI) 	&lt;br /&gt;
* Sound Library (SL) 	&lt;br /&gt;
* Standard Geometry Library(SG) 	&lt;br /&gt;
* Simple Scene Graph Library (SSG) 	&lt;br /&gt;
* PUI Auxiliary Library (PUAUX) 	&lt;br /&gt;
* SSG Auxiliary Library (SSGA) 	&lt;br /&gt;
* Joystick wrappers (JS) 	&lt;br /&gt;
* Fonts'n'Text Library (FNT) 	&lt;br /&gt;
* Utility Library (UL) 	&lt;br /&gt;
* Pegasus Network Library (NET) 	&lt;br /&gt;
* PLIB Scripting Language (PSL) 	&lt;br /&gt;
* PLIB Windowing Library (PW) 	&lt;br /&gt;
&lt;br /&gt;
== Recommended version ==&lt;br /&gt;
Even if version 1.8.5, shipped with most of the GNU/Linux distributions, does work for FlightGear and related software, it is [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg20793.html recommended] to use the latest source from its SVN repo:&lt;br /&gt;
 svn co https://plib.svn.sourceforge.net/svnroot/plib/trunk plib&lt;br /&gt;
 cd plib&lt;br /&gt;
 sed s/PLIB_TINY_VERSION\ \ 5/PLIB_TINY_VERSION\ \ 6/ -i src/util/ul.h&lt;br /&gt;
&lt;br /&gt;
== Link ==&lt;br /&gt;
* http://plib.sourceforge.net/index.html&lt;br /&gt;
&lt;br /&gt;
[[pt:PLIB]]&lt;br /&gt;
[[Category:Software]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=$FG_ROOT&amp;diff=75683</id>
		<title>$FG ROOT</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=$FG_ROOT&amp;diff=75683"/>
		<updated>2014-08-28T16:34:24Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''$FG_ROOT''' is refered to as the main directory of [[FlightGear]], containing the so called ''base package'' (default [[aircraft]] and [[scenery]], [[Menubar|GUI]] files etc). When running FlightGear from a [[command line]], you can set $FG_ROOT via &amp;lt;tt&amp;gt;--fg-root=path/to/root&amp;lt;/tt&amp;gt;. In [[FGRun]], it is set on the paths page, previous to the aircraft selection page.&lt;br /&gt;
&lt;br /&gt;
As of FlightGear 2.4, it is advised to install additional scenery and aircraft in [[$FG_SCENERY]] and [[$FG_AIRCRAFT]] directories outside $FG_ROOT. This allow for maintaining the additional stuff when installing a new version of FlightGear.&lt;br /&gt;
&lt;br /&gt;
=== Common paths ===&lt;br /&gt;
* '''Mac OS X:''' &amp;lt;tt&amp;gt;Applications/FlightGear.app/Contents/Resources/data/&amp;lt;/tt&amp;gt; (right-click on FlightGear.app and select &amp;quot;Show Package Contents&amp;quot; to see the Contents folder)&lt;br /&gt;
: $FG_ROOT is not installed automatically. See [[New to FlightGear#Installing on Mac OS X|New to FlightGear]] for an installation manual.&lt;br /&gt;
* '''Ubuntu:''' &amp;lt;tt&amp;gt;/usr/share/games/flightgear/&amp;lt;/tt&amp;gt;&lt;br /&gt;
* '''Windows:''' &amp;lt;tt&amp;gt;Program Files\FlightGear\data\&amp;lt;/tt&amp;gt; (default, '''see note!''')&lt;br /&gt;
: Newer Windows versions are very, very protective about the &amp;lt;tt&amp;gt;Program Files&amp;lt;/tt&amp;gt; folder and installing FlightGear into this folder makes it prone to any problems relating to file read/write permissions. Hence, installing FlightGear into &amp;lt;tt&amp;gt;Program Files&amp;lt;/tt&amp;gt; on Windows Vista and later is not recommended.&lt;br /&gt;
&lt;br /&gt;
[[Category:Special directories|ROOT]]&lt;br /&gt;
&lt;br /&gt;
[[de:$FG ROOT]]&lt;br /&gt;
[[fr:$FG ROOT]]&lt;br /&gt;
[[nl:$FG_ROOT]]&lt;br /&gt;
[[es:$FG_ROOT]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Install_scenery&amp;diff=75682</id>
		<title>Howto:Install scenery</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Install_scenery&amp;diff=75682"/>
		<updated>2014-08-28T16:29:40Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Technical */ +commandline option, formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{installing}}&lt;br /&gt;
&lt;br /&gt;
[[Image:High_textures_transitions3.png|thumb|High detail France scenery]]&lt;br /&gt;
[[Image:High_textures_transitions4_1.png|thumb|High detail France scenery]]&lt;br /&gt;
[[Image:High_textures_transitions6_2.png|thumb|High detail France scenery]]&lt;br /&gt;
&lt;br /&gt;
FlightGear comes with a limited set of [[scenery]]. Apart from the Bay Area around San Francisco (including the default airport [[KSFO]]), additional scenery can be installed by the user. If you locate yourself at an airport and see nothing but water, you probably did not install that scenery area (correctly).&lt;br /&gt;
&lt;br /&gt;
== Obtaining scenery ==&lt;br /&gt;
You can download the official [[World Scenery]] terrain from the [http://www.flightgear.org/Downloads/scenery FlightGear website]. Alternatively, custom scenery is available for certain specific areas. They are distributed separately due to their license, or because their level of detail is not suitable for low-end machines. See [[Suggested Airports/Scenery]] for a list of custom scenery projects.&lt;br /&gt;
&lt;br /&gt;
There is also a 4 DVD set available for download via [http://www.torrentbox.com/download/59050/FlightGear_4_DVD_Disk-set.torrent BitTorrent], which can be a higher performance option for those wanting to download the entire world. And, last but not least, it can be purchased as 3 DVD set from the [http://www.flightgear.org/dvd/ official FlightGear website].&lt;br /&gt;
&lt;br /&gt;
=== TerraSync ===&lt;br /&gt;
[[TerraSync]] is a very useful utility that automatically downloads and installs needed FlightGear scenery and keeps it up to date while the simulator is running. &lt;br /&gt;
&lt;br /&gt;
=== TerraMaster ===&lt;br /&gt;
[[File:TerraMaster r32 - Global view.png|thumb|TerraSync scenery in TerraMaster]]&lt;br /&gt;
[[TerraMaster]] is a scenery manager that basically is a frontend for TerraSync but that also makes it easier to maintain and get a good overview of downloaded TerraSync scenery. It is a crossplatform graphical application written in Java.&lt;br /&gt;
&lt;br /&gt;
TerraMaster allows the FlightGear user to manage scenery tiles easily, selecting which tiles to add (by download), delete, and view the downloaded/not yet downloaded tiles at a glance. TerraMaster is highly recommended not only for managing scenery tiles easily especially if you are downloading and managing scenery from a computer that does not have FlightGear installed. The downloaded tiles are put into a folder which can then be copied into the FlightGear directory later on to complete the scenery.&lt;br /&gt;
&lt;br /&gt;
Learn more about the [[TerraMaster]] tool.&lt;br /&gt;
&lt;br /&gt;
=== Downloading from mirrors ===&lt;br /&gt;
A list of mirrors can be found [http://www.flightgear.org/mirrors.html#ftp here].&lt;br /&gt;
&lt;br /&gt;
On most of the mirrors, the latest scenery can be found under &amp;lt;tt&amp;gt;Scenery-2.0.0/&amp;lt;/tt&amp;gt;. Downloading from mirrors is often better than the official site, because mirrors are sometimes faster and have more user capacity. Use the [http://www.flightgear.org/Downloads/scenery graphical interface] to find the appropriate chunk. Be careful about confusing N with S, and E with W!!&lt;br /&gt;
Here is how to find an airport's co-ordinates:&lt;br /&gt;
&lt;br /&gt;
# Go to the Wikipedia page for the airport in question (for example, PHNL for Honolulu)&lt;br /&gt;
# Find the co-ordinates (often at the top or right and side, marked with a small globe)&lt;br /&gt;
#* e.g. PHNL is in 21 N 157 W. If it's in the western hemisphere, you should round it up... so you should find the block with W160N20 If the co-ords were 21 N 157 E, you would round it '''down'''.. meaning that this location would be E150N20.&lt;br /&gt;
&lt;br /&gt;
=== Downloading with BitTorrent ===&lt;br /&gt;
There is a torrent file hosted on http://www.terasaur.org which you can [http://terasaur.org/torrent/download/ae22ec86209fb14cb143a968be5ba8d3bebd7d6f/Scenery-v2.10.torrent find here]. There is also an alternative torrent (only added a new announcement URL) with a strong seed [http://flightgear.mxchange.org:23456/file?info_hash=%AE%22%EC%86%20%9F%B1L%B1C%A9h%BE%5B%A8%D3%BE%BD%7Do available].&lt;br /&gt;
&lt;br /&gt;
Please note that these downloads are currently for version 2.10 and that you should download the matching launcher, too.&lt;br /&gt;
&lt;br /&gt;
== Installing scenery ==&lt;br /&gt;
You can optionally use a GUI installer, called [[FlightGear Admin Wizard|FGAdmin]], to (un)install scenery.&lt;br /&gt;
&lt;br /&gt;
=== GNU/Linux ===&lt;br /&gt;
If you are under a Linux operation system and you are not using a graphical interface to extract the tar archive, you can use one of the two following set of commands in a shell terminal.&lt;br /&gt;
&lt;br /&gt;
 cd SceneryDirectory&lt;br /&gt;
 tar -xvzf input_file.tgz&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
 tar -xvzf 'input_file.tgz' -C SceneryDirectory&lt;br /&gt;
&lt;br /&gt;
In the above two examples, it is supposed that &amp;lt;tt&amp;gt;SceneryDirectory&amp;lt;/tt&amp;gt; is set to a directory, outside &amp;lt;tt&amp;gt;[[$FG_ROOT]]&amp;lt;/tt&amp;gt; (see [[#Technical]] for the reasoning behind this). Additionally, &amp;lt;tt&amp;gt;input_file.tgz&amp;lt;/tt&amp;gt; should be substituted with the filename of the archive to be extracted (the filename should be completed with the full pathname or any other valid method so that the shell could find the correct archive).&lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
Simply unpack the downloaded scenery into a directory of choice, outside the &amp;lt;tt&amp;gt;[[$FG_ROOT]]&amp;lt;/tt&amp;gt; directory (see [[#Technical]] for the reasoning behind this), using software like [http://www.winzip.com/ Winzip] or [http://www.7-zip.org 7-zip]. Once done, append this directory to [[$FG_SCENERY]]. When using the [[FlightGear Wizard]], you can do so on the first page (previous from aircraft selection). Do not forget to press the &amp;quot;Refresh&amp;quot; button on the airport selection page, when using the wizard.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' More recent Windows versions (e.g. XP, Vista, Win7) tinkering a lot with user rights on access level. Therefore it is a bad idea to install and run FlightGear (scenery) to and from &amp;lt;tt&amp;gt;C:\Program Files&amp;lt;/tt&amp;gt;. Find another drive/folder where you, as logged in user, have all neccesary right to read, write and execute the files you installed. Additionally there's a space / blank in folder's name which could cause weird behaviour. Using &amp;lt;tt&amp;gt;C:\FlightGear&amp;lt;/tt&amp;gt; is a nice option.&lt;br /&gt;
&lt;br /&gt;
=== Macintosh ===&lt;br /&gt;
Unpack the tgz file either by double-clicking it and moving the resulting wXXXnXXX folder to the Scenery folder described in the next line, or on the command line:&lt;br /&gt;
 tar -xvzf 'input_file.tgz' -C /Applications/FlightGear.app/Contents/Resources/data/Scenery&lt;br /&gt;
&lt;br /&gt;
== Technical ==&lt;br /&gt;
Scenery for FlightGear is determined by looking at the environment variable [[$FG SCENERY]]. Should the paths in $FG_SCENERY not be valid, FlightGear falls back to &amp;lt;tt&amp;gt;[[$FG ROOT]]/Scenery&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Mixing scenery types is almost universally a bad idea, and is unsupported. In this connection you should note that the scenery packaged with the base package/windows installer may not be the latest scenery.&lt;br /&gt;
&lt;br /&gt;
For this reason it's probably better to extract scenery files you've downloaded into a new folder, which we'll call, for the sake of this exercise, &amp;lt;tt&amp;gt;$FOOBAR/Scenery&amp;lt;/tt&amp;gt;.&lt;br /&gt;
In this directory, create two subdirectories: /Objects and /Terrain. You should untar individual files into the /Terrain folder.&lt;br /&gt;
&lt;br /&gt;
Then you should set up $FG_SCENERY to use the new path:&lt;br /&gt;
* On POSIX Clients&lt;br /&gt;
*: &amp;lt;tt&amp;gt;set FG_SCENERY=&amp;quot;$FOOBAR/Scenery&amp;quot; + FG_SCENERY&amp;lt;/tt&amp;gt;&lt;br /&gt;
* On Windows (FGRun)&lt;br /&gt;
*: Go back to the first page of fgrun, and add the &amp;lt;tt&amp;gt;$FOOBAR/Scenery&amp;lt;/tt&amp;gt; folder to the list.&lt;br /&gt;
* Via a commandline option&lt;br /&gt;
*: &amp;lt;tt&amp;gt;--fg-scenery=&amp;quot;$FOOBAR/Scenery&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Terrain ===&lt;br /&gt;
The Scenery directory will show the following (scenery is shown for completeness and for easy reference to above):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
* Scenery/&lt;br /&gt;
** Terrain/&lt;br /&gt;
*** w130n30/&lt;br /&gt;
** Objects/&lt;br /&gt;
*** w130n30/&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you download a scenery module called w90n40.tgz from [http://flightgear.org/Downloads/scenery-1.0.1.html flightgear.org] and extract it in Scenery, the result will resemble something like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
* Scenery/&lt;br /&gt;
** Terrain/&lt;br /&gt;
*** w09n40/&lt;br /&gt;
*** w130n30/&lt;br /&gt;
** Objects/&lt;br /&gt;
*** w09n40/&lt;br /&gt;
*** w130n30/&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the directory structure is already present in the tar archive, starting from the Scenery directory. Note that you have to extract the tar archive in the Scenery directory, not in the FG_ROOT directory, because the Scenery directory is not present in the archive.&lt;br /&gt;
&lt;br /&gt;
=== Objects ===&lt;br /&gt;
Objects and models can be found at the [http://scenemodels.flightgear.org/ FlightGear Scenery Objects Database].&lt;br /&gt;
&lt;br /&gt;
These objects are included in each scenery release, but as the object database is more frequently updated than the terrain, one may want to occasionally update the Object subdirectory from the FlightGear Scenery Objects Database between scenery releases.&lt;br /&gt;
Another option is to download or update the scenery on-demand by using the terrasync program described below.&lt;br /&gt;
&lt;br /&gt;
Objects are really part of the scenery and can be found in the Scenery directory under [[$FG ROOT]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
* Scenery/&lt;br /&gt;
** Objects/&lt;br /&gt;
*** w130n30/&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any objects should be installed under the &amp;lt;tt&amp;gt;Scenery/Objects&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
=== Models ===&lt;br /&gt;
Replaces the former &amp;lt;tt&amp;gt;[[$FG_ROOT]]/Models&amp;lt;/tt&amp;gt;; stores all the shared objects.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
* Scenery/&lt;br /&gt;
** Models/&lt;br /&gt;
*** Airport/&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Airports ===&lt;br /&gt;
{{Main article|About Scenery/Airports}}&lt;br /&gt;
As of FlightGear 2.4.0, this directory is used to extract airport data (like runway usage and parking spots) from.&lt;br /&gt;
&lt;br /&gt;
The directory tree might look somewhat overwhelming, but it simply follows the &amp;lt;tt&amp;gt;Airports/[I]/[C]/[A]/&amp;lt;/tt&amp;gt; code (see [[ICAO-code]]).&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
* Scenery/&lt;br /&gt;
** Airports/&lt;br /&gt;
*** K/&lt;br /&gt;
**** S/&lt;br /&gt;
***** F/&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
* [[Scenery FAQ]]&lt;br /&gt;
&lt;br /&gt;
[[de:Howto:Install_scenery]]&lt;br /&gt;
[[es:Instalación de escenarios]]&lt;br /&gt;
[[fr:Installer une scène]]&lt;br /&gt;
[[Nl:Scenery installeren]]&lt;br /&gt;
[[PL:Instalowanie scenerii]]&lt;br /&gt;
[[pt:Instalando Cenário]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Scenery]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FGx&amp;diff=74800</id>
		<title>FGx</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FGx&amp;diff=74800"/>
		<updated>2014-08-07T14:22:50Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: Redirected page to FGX&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[FGX]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Mac_OS_X_Launcher&amp;diff=74799</id>
		<title>FlightGear Mac OS X Launcher</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Mac_OS_X_Launcher&amp;diff=74799"/>
		<updated>2014-08-07T14:22:11Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: +issue 1521; thanks for the help Johan!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}&lt;br /&gt;
&lt;br /&gt;
{{caution|This launcher is unmaintained and may not work properly. It is anticipated to no longer work at all in OS X version 10.10 &amp;quot;Yosemite&amp;quot; and beyond (see {{issue|1521}}). For an alternative, see [[FGo!]] or [[FGx]], among others.&lt;br /&gt;
&lt;br /&gt;
FlightGear can also be launched via the command line (Terminal.app) from the same binary distribution, e.g.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /Applications/FlightGear.app/Contents/Resources&lt;br /&gt;
./fgfs.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
[[File:FlightGear Mac OS X Screenshot.png|right]]&lt;br /&gt;
&lt;br /&gt;
'''FlightGear Mac OS X Launcher''' is a graphical front end for [[FlightGear]], included in official Mac binaries of [[FlightGear 0.9.10]], [[FlightGear 1.0|1.0.0]], [[Flightgear 1.9.0|1.9.0]], and [[FlightGear 2.0.0|2.0.0]] through [[Flightgear 3.2.0|3.2.0]] releases. The launcher allows one to choose options more easily than with the command line.&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear front ends]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Mac_OS_X_Launcher&amp;diff=74781</id>
		<title>FlightGear Mac OS X Launcher</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Mac_OS_X_Launcher&amp;diff=74781"/>
		<updated>2014-08-07T04:31:40Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: this page needs an update... poor launcher&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}&lt;br /&gt;
&lt;br /&gt;
{{Note|This launcher is unmaintained and may not work properly. It is anticipated to no longer work at all in OS X version 10.10 &amp;quot;Yosemite&amp;quot; and beyond. For an alternative, see [[FGo!]] or [[FGx]], among others. It can also be launched via the commandline (Terminal.app) from the same binary distribution, e.g.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd /Applications/FlightGear.app/Contents/Resources&lt;br /&gt;
./fgfs.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''FlightGear Mac OS X Launcher''' is a graphical front end for [[FlightGear]], included in official Mac binaries of [[FlightGear 0.9.10]], [[FlightGear 1.0|1.0.0]], [[Flightgear 1.9.0|1.9.0]], and [[FlightGear 2.0.0|2.0.0]] through [[Flightgear 3.2.0|3.2.0]] releases. The launcher allows one to choose options more easily than with the command line.&lt;br /&gt;
&lt;br /&gt;
[[File:FlightGear Mac OS X Screenshot.png|right]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Talk:Failure_Manager&amp;diff=74780</id>
		<title>Talk:Failure Manager</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Talk:Failure_Manager&amp;diff=74780"/>
		<updated>2014-08-07T03:10:09Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Backwards compatibilty ==&lt;br /&gt;
&lt;br /&gt;
Things to consider:&lt;br /&gt;
&lt;br /&gt;
- aircraft that depend on what is in the dialog today, and how it writes to serviceable properties and makes some properties read-only.&lt;br /&gt;
&lt;br /&gt;
If we just remove all default failures, these aircraft, which might not be actively maintained, all of a sudden will lose all failure management, unless it is custom coded.&lt;br /&gt;
&lt;br /&gt;
Maybe planes using the new system could set a property such as: &amp;lt;failure-system&amp;gt;&amp;lt;version&amp;gt;2&amp;lt;/version&amp;gt;&amp;lt;/failure-system&amp;gt;&lt;br /&gt;
That would give the new system, with no predefined failures, and not specifying anything will give the old, with its predefined failures. [[User:Necolatis|Necolatis]] ([[User talk:Necolatis|talk]]) 22:18, 6 February 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: You've hit the nail on the head with this one. Can we please have the old way as default, with the new way as an option? along with correct behaviour of &amp;lt;nasal&amp;gt;&amp;lt;FailureManager&amp;gt;false&amp;lt;/FailureManager&amp;gt;&amp;lt;/nasal&amp;gt; in autosave.xml . ??? Thanks for nothing btw.&lt;br /&gt;
::No, I don't want to use your super duper mega fancy failure manager, and I set it to off and I expect to have the normal, old behaviour, so my simple failure manager works as expected, but no, if I set it to off everything's broken, because someone thought it might be fancy to have it that way...&lt;br /&gt;
&amp;lt;!-- :: Hooray, one more time, _Please_ _Stop_ _This_ _Madness_ ..... !!!! --&amp;gt;&lt;br /&gt;
:: [[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 17:10, 4 August 2014 (UTC)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
::: @i4dnf: you may want to check your &amp;quot;facts&amp;quot; before you start your name calling, or you may find -once again- that you are only making yourself ridiculous. --[[User:Hooray|Hooray]] ([[User talk:Hooray|talk]]) 17:23, 4 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:::: @Hooray I've got my facts very right. You are the one pushing for everything in nasal every other 5 words, every other post, and yeah, that's why I call on you to stop this madness.... &lt;br /&gt;
:::: Enough's enough....&lt;br /&gt;
:::: [[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 17:29, 4 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: Nope, far from it - besides, there's no causality here at all when it comes to an -apparent- lack of backward compatibility versus the choice of implementation language (i.e. the whole C++ vs. Nasal debate). In general, backward compatibility is not a language feature, but a matter of explicit design (with very few exceptions like Erlang, where backward compatibility is an explicit language feature, which still needs to be used though!) &lt;br /&gt;
:: Assuming that you also have some kind of background in computing, I would expect you to understand that ? And FlightGear itself is particularly bad at backward compatibility. The failure management framework makes a conscious attempt at keeping backward compatibility in mind though.&lt;br /&gt;
:: &lt;br /&gt;
:: Unfortunately, your whole &amp;quot;bug report&amp;quot; is as uninformative as it can be, which is disappointing, but also goes to show that you're obviously not interested in contributing to a solution, but just to a huge misunderstanding? &lt;br /&gt;
:: However, assuming that you are referring to your own aircraft -that is no longer part of the base package- it may help to point out that several aircraft were patched when the failure management framework got committed. &lt;br /&gt;
:: Apart from that, I have very little to offer, and would refer you to galvedro who can surely point out what needs to be done to make your own use-case work again, or to implement your &amp;quot;feature request&amp;quot;.  &lt;br /&gt;
:: &lt;br /&gt;
:: However, if you're right, I'd just ask you to please keep in mind that this may very well be a simple case of a new contributor/committer having missed one or two things - given that fellow contributors like Thorsten, and others, have also pointed out issues in your own contributions/code, I would have expected you to more be a little more forgiving here ? &lt;br /&gt;
:: Honestly, collaboration and feedback is key here - when the patch/feature got committed, this was announced and people were invited to provide feedback - as is common. &lt;br /&gt;
:: So there's really no need to turn into a drama queen just because you may have missed something due to your own lack of feedback. We really don't need people to act like drama queens whenever something in master/next doesn't quite work as expected, no matter the underlying reason - especially not fellow contributors (current AND former ones!). There's really no need to constantly poison the atmosphere and just show up to point out issues and tell off others.&lt;br /&gt;
:: But yeah, it is kinda funny how apparently smart people can make very uninformed, and even stupid, points just because they have some kind of history with fellow contributors ... I guess we've all been there once - so it may help to put things into perspective, and maybe just try to understand that this is not a Nasal issues, and that I wasn't even involved in writing the code - which is much cleaner than most Nasal code we get to see, including mine and yours.  --[[User:Hooray|Hooray]] ([[User talk:Hooray|talk]]) 17:50, 4 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
::: Right, in case I'm blind(as I can't see any) please point to the announcement, and the so called updated aircraft. And no, it wasn't a bug report, was just a confirmation of Necolatis' worries.&lt;br /&gt;
::: My aircraft or not, this is irrelevant. What is relevant is that a certain subsystem was turned on its head without proper notice or backward compatibility. And, yeah, in case you didn't notice, there's roughly 500 aircraft in fgdata, and any one of those might rely on the &amp;quot;old&amp;quot; system and be broken now, and for those 500 aircraft the sim is holding on to ancient tech in places where updated stuff would bring far more improvements and benefits...&lt;br /&gt;
::: And since we're on the subject of name calling, you might want to check who you're calling poisonous, since you are the single most toxic element in this community. And that's quite an achievement for someone that, so far as I know, has not committed one line of code to this sim. And I do call on you when I see your trigger happy cronies committing stuff without testing, and breaking stuff, driven by your misguided, poisonous (since you like that word) 'mentorship'&lt;br /&gt;
:::Thanks for nothing, again&lt;br /&gt;
:::P.S. If unable to summarize your answer in 5 phrases don't bother, I seldom read past that in any of your postings&lt;br /&gt;
:::[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 18:22, 4 August 2014 (UTC)&lt;br /&gt;
:: Don't worry: I won't bother - I really couldn't care less about explaining myself to you (and yeah, it would take me more than 5 lines, including links to patches committed over a decade ago ...). At least you've proven that I was right, that this is in fact not about Nasal or myself and that you never bothered to check your facts. Thanks for proving once again, that you're really just interested in flaming. BTW: nick names are cheap, and I've had more than one in over 10 yrs of varying involvement, including paid contract work that involved ripping out Nasal back then *g* ... PLONK --[[User:Hooray|Hooray]] ([[User talk:Hooray|talk]]) 18:39, 4 August 2014 (UTC)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:::@i4dnf: It should be possible to disable the module using standard mechanisms, and while enabled, the module should be fully backwards compatible. I wrote this part explicitly for handling backwards compatibility: [https://gitorious.org/fg/fgdata/source/509f210cd0c6a544c62be2986a10ace23f485784:Aircraft/Generic/Systems/compat_failure_modes.nas Aircraft/Generic/Systems/compat_failure_modes.nas]. I have opened a discussion in your talk page so we can work out what is missing. --[[User:Galvedro|Galvedro]] ([[User talk:Galvedro|talk]]) 12:13, 6 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:::: There are two big issues, besides the fundamental one of making a 'complex' piece of code mandatory for simple stuff (but that's another talk).&lt;br /&gt;
:::: 1: Failure to set sane defaults and provide for normal operation with the module disabled -&amp;gt; disabling the module leaves all 'serviceable' properties in the failed state, instead of the sane/failsafe default of true.&lt;br /&gt;
:::: 2: Moving properties around, changing ui items and their effect on the property tree, without proper notification/announcement (and no, i don't mean 3rd word 157th line of some obscure forum post), e.g. moving the /gear/serviceable flag to its new location. I get it that stuff is/was in disarray, but such a move should not be done overnight/pre-release and without even telling (I had to dig into the git history to see what's going on there). Given the 'age' of the original property location it is likely that aircraft might depend on it (the location of their repository is irrelevant), and such a change would break them. There are numerous examples of how this change should be handled on the devel ML. &lt;br /&gt;
:::: Thanks for considering these. ''Hopefully you'll also consider the possibility that not everybody wants/needs to use your code, and in many cases it's overkill.''&lt;br /&gt;
:::: Also keep in mind that there are many aircraft maintained outside of fgdata, and in the future it's very likely there will be no aircraft maintained in fgdata anymore (except ufo and c172p)&lt;br /&gt;
::::[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 00:49, 7 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
::::::: &amp;quot;''Also keep in mind that there are many aircraft maintained outside of fgdata, and in the future it's very likely there will be no aircraft maintained in fgdata anymore (except ufo and c172p)''&amp;quot;&lt;br /&gt;
:::::: While this might be literally true, it really isn't – I'm 100% sure there will always be a &amp;quot;main FG&amp;quot; repository of aircraft which have nowhere else to go, while certain actively-maintained aircraft could go to their respective hangars (i.e. stay there). There is a point to centrality (i.e. knowing where to find things and easy access to those) that I'm sure won't be neglected, even in the event of a potential FGData split or similar.&lt;br /&gt;
:::::: [[User:Philosopher|—Philosopher]] ([[User talk:Philosopher|talk]]) 03:10, 7 August 2014 (UTC)&lt;br /&gt;
:::::: P.S. How is 2 months &amp;quot;''overnight/pre-release''&amp;quot;? That's a whole third of the release cycle, plus as previously stated, it was intended to be backwards compatible – I checked the c172p and Seneca II (IIRC) myself – and it's also in the [[Changelog 3.2]], so quit your griping.&lt;br /&gt;
&lt;br /&gt;
::My plan for handling backwards compatibility, as can be seen in the roadmap section, is to load the compat script explicitly from every aircraft at some point. This will provide them with the same set of failure modes that they currently have. Unmaintained planes will remain that way, and those being actively maintained will be able to replace the compat script and start tailoring failure mode support to what the aircraft can actually handle. --[[User:Galvedro|Galvedro]] ([[User talk:Galvedro|talk]]) 12:13, 6 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
== GUI instruments ==&lt;br /&gt;
&lt;br /&gt;
The GUI contains instruments, such as radio, transponder, GPS, map etc.&lt;br /&gt;
&lt;br /&gt;
Should these have a failure mode, or maybe an option inside the dialog to include them as failures? (not sure if any of them currently depend on any serviceable/read-only properties. [[User:Necolatis|Necolatis]] ([[User talk:Necolatis|talk]]) 22:18, 6 February 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Prototype dialog ==&lt;br /&gt;
&lt;br /&gt;
I can make a prototype dialog, to show how I imagine the dialog to look, and then we can discuss it from there?&lt;br /&gt;
&lt;br /&gt;
In my opinion there should only be 1 dialog, which includes failures, and setting random failures, instead of 3 dialogs, like today. That could be done with tabs. [[User:Necolatis|Necolatis]] ([[User talk:Necolatis|talk]]) 22:18, 6 February 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Failing ground equipment ==&lt;br /&gt;
&lt;br /&gt;
I have just skimmed through the code to have an idea of what's involved.&lt;br /&gt;
&lt;br /&gt;
The problem I see right away is that there are different animals covered under the SGSubsystem umbrella. At the very least, there are a) core sim modules, like ephemeris and sound, and b) cockpit instruments and systems. The SGSubsystem interface is in my opinion, a bit overkill for the b) category in some aspects (the initialization stuff, for example), and it falls short in others (i.e. connectivity). This is something I wanted to investigate and see if it would be beneficial (and acceptable) to separate SGSubsystem into more explicit interfaces.&lt;br /&gt;
&lt;br /&gt;
Regarding failure management there is another problem in the code. The current standard IO interface for built-in instruments and systems is the property tree. Those that implement failure modes, do so via a &amp;quot;serviceable&amp;quot; property. That means that they don't care about C++ interfaces, rather, they rely on conventions. Adding an interface derived from Subsystem would not improve the the situation in this case.&lt;br /&gt;
&lt;br /&gt;
Additionally, navaids and such are not accessible as Subsystem objects by themselves, but as pieces of information gathered from the navaid cache (if I followed the code correctly). If we forced a FailableSubsystem interface, the interface would apply to the entire navdb, which means that the interface will not be as simple as:&lt;br /&gt;
&lt;br /&gt;
FailableSubsystem::set_failure_level(int level);&lt;br /&gt;
&lt;br /&gt;
It would have to be more complex, also in order to allow non trivial subsystems to implement more than one failure mode.&lt;br /&gt;
&lt;br /&gt;
Given this, as a first step, what I would do in order to support navaid failure would be to expose a simplified NavDataCache interface to Nasal and either&lt;br /&gt;
&lt;br /&gt;
a) implement a &amp;quot;failure_actuator&amp;quot;, as I call them in the current prototype, that sets the navaid range down to zero on failure, or&lt;br /&gt;
b) implement a NavDataCache::fail_navaid(id) that would be exposed to Nasal, possibly together with a few other calls, now we are at it.&lt;br /&gt;
&lt;br /&gt;
The easy way to do it I guess it would be to create a NavDataCache Facade class with a reduced interface suitable for Nasal, and then use cppbind to expose the class to scripting interface. Somethig like that..&lt;br /&gt;
&lt;br /&gt;
[[User:Galvedro|Galvedro]] ([[User talk:Galvedro|talk]]) Thu Feb 06, 2014 8:31 pm&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User_talk:Hvengel&amp;diff=74079</id>
		<title>User talk:Hvengel</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User_talk:Hvengel&amp;diff=74079"/>
		<updated>2014-07-14T13:55:03Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Spinner animation */ Nasal&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Spinner animation ==&lt;br /&gt;
&lt;br /&gt;
Hi. I've duplicated the spinner for each of the stages of the propeller animation (blades, blurred blades, disk ), as each of these spins at a different rate. It's the cheapest way to solve the issue, and it avoids having extra bits of code laying around (I generally avoid having nasal involved if there's a viable solution without it). Some will argue it's a quick job in 5 lines of nasal, well 5 lines of nasal add up, and can become quite the issue as the extra-500 bears witness (it is unflyable here and elsewhere due to the low fps, as everything is waiting on the nasal scripts).&lt;br /&gt;
&lt;br /&gt;
[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 09:09, 11 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Like you I avoid Nasal if there is an XML way to handle things.  With a JSBSim FDM you can do a lot of things in XML that require Nasal in a YASim aircraft and, at least for a JSBSim FDM, you should almost never need Nasal for animations unless they are VERY complex or are not FDM specific (IE. intended for use in any aircraft regardless of FDM).  The K-14A gun sight reticle animations are an example of something complex enough to be beyond doing it with XML only but it is also intended to be FDM independent as well so using JSBSim to drive the animations was not an option.   &lt;br /&gt;
&lt;br /&gt;
Also in JSBSim you can setup XML functions specifically to drive animations.  For example, I do this to throttle the gun animations as frame rates fall below certain thresholds.  But I don't use any JSBSim stuff for the prop animation. When you use XML you are relegating things to either the FDM or to FG itself which will generally be more efficient and &amp;quot;safer&amp;quot; than rolling your own Nasal and much of this will actually happen in C++ space.  Also if you do this using FDM XML you take this out of the main loop which is generally a good thing.&lt;br /&gt;
&lt;br /&gt;
Yesterday evening I pulled the prop disk and a second copy of the spinner into a separate model and did some cleanup on the models (the blades and the disk were not running true so I fixed that issue).  Looks OK. &lt;br /&gt;
&lt;br /&gt;
Right now I only have two stages to the prop animation and I am trying (unsuccessfully) to use a transparency animation on the blades to simulate the blurred blades phase.  In fact I have been unable to get the transparency animation working in a number of contexts with recent versions of FG and I am not sure what the issue really is (probably something I am doing).  I can get things to have a fixed transparency by setting the material to a certain gamma and using a texture with a gamma but I have been unable to change the transparency at run time using the transparency or blend animation.&lt;br /&gt;
&lt;br /&gt;
The other issue here is that in the blurred blade phase the blades should be darker/less transparent closer to the hub/spinner because they are traveling way slower than at the tips of the blades.  A blurred blade phase specific model and texture would probably make this possible.   &lt;br /&gt;
&lt;br /&gt;
At this point I have more important stuff to tackle than the blurred blase phase stuff so it will have to wait until later as the prop animations are &amp;quot;good enough&amp;quot; for now.&lt;br /&gt;
&lt;br /&gt;
[[User:Hvengel|Hvengel]] ([[User talk:Hvengel|talk]]) 16:16, 12 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:: &amp;quot;When you use XML you are relegating things to either the FDM or to FG itself which will generally be more efficient and &amp;quot;safer&amp;quot; than rolling your own Nasal and much of this will actually happen in C++ space.  Also if you do this using FDM XML you take this out of the main loop which is generally a good thing.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
: This is not true – FDM is still inside the main loop (anything that accesses the property tree is inside the main loop). In fact it would be less efficient (theoretically) to put animation code into the FDM because it's updated unnecessarily – animations are only evaluated each frame. (Direct output of surface position is fine, but processing it doesn't have to be in the FDM.) It's not like adding a small Nasal operation for an animation would have any performance penalty at all – even on the most outdated hardware imaginable. But then again, it'll just be a small difference normally – hardly even 1/10th of a ms.&lt;br /&gt;
&lt;br /&gt;
: Emilian: while I agree that the Extra-500 is really slow for me as well, how well it performs is not relevant to this discussion. The Nasal used there is more comparable to &amp;quot;500+600+700+... lines of Nasal code adding up&amp;quot; than &amp;quot;5+5+5+... lines of Nasal code adding up&amp;quot; – because 5 lines of Nasal code takes up no time at all (unless it calls expensive functions and/or uses recursion and/or loops, which the Extra-500 certainly uses some of). The Extra-500 is really complex (as far as I understand it) and is subject to different issues, issues which don't affect small scripts (i.e. 5-liners). Some of the lack of efficiency is not even Nasal code, it's hard coded (e.g. the props.Node interface, which doesn't use cppbind and thus can create unnecessary temporary GC-able objects if used incorrectly). Some of it is the lack of efficiency in the Extra-500's code versus what being accomplished – i.e. it could be much simpler in places (and actually use MapStructure). Some of it is the positioned queries – those are not microscopic yet, but probably will be soon. Et cetera. There's different ways we could prove it's inefficient code. Nasal itself, however, is very efficient from what I've seen and simple animations are not time-wasters at all. Even 100 lines of simple Nasal animations should execute in under ~2-4ms, I would guess, on reasonably modern hardware if it doesn't use certain constructs (e.g. props.globals.getNode(&amp;quot;&amp;quot;).setValue/getValue, where the node isn't cached, see [http://forum.flightgear.org/viewtopic.php?f=30&amp;amp;t=22155#p201370], or other GC nightmares). Even GC'ing is extremely fast on my computer :-). [[User:Philosopher|—Philosopher]] ([[User talk:Philosopher|talk]]) 13:55, 14 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
== Ubershader Issues ==&lt;br /&gt;
&lt;br /&gt;
HI, I'm the author of the ubershader and accompanying effects. I noticed on the forums that you're having some issues with it.&lt;br /&gt;
&lt;br /&gt;
Could you please paste somewhere the effect file you use?&lt;br /&gt;
&lt;br /&gt;
Also could you check that the respective objects are not parented to some other object (or an empty) from where they could possibly inherit effects/materials?&lt;br /&gt;
&lt;br /&gt;
The flipped normal behaviour is really weird (and would suggest you have inadvertently enabled the &amp;lt;normalmap-dds&amp;gt; flag)&lt;br /&gt;
&lt;br /&gt;
Also, for the uberhsader the relevant documentation is in $FG_DATA/Docs/model-combined.eff/&lt;br /&gt;
&lt;br /&gt;
(If you're gonna ask why it's not on the wiki, you have already hit the main reason, bitrot, and having to duplicate maintenance efforts. And no, I don't think the wiki should be the authoritative source for documentation)&lt;br /&gt;
&lt;br /&gt;
HTH&lt;br /&gt;
&lt;br /&gt;
[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 18:11, 3 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:Hello Hvengel&lt;br /&gt;
&lt;br /&gt;
:I have/had the same problem with the EC135P2 and the Dornier 328 model slow WIP. So far I can remember one thing seems to be is the uvmapping. When two face are overlapped in the :UVmapped it seems to produce this issue. At least it is not a issue with the shader itself. More the way the model is uvmapped.&lt;br /&gt;
:Can you send a in-sim screenshot of the faulty part and a image of the the matching uvmapping?&lt;br /&gt;
&lt;br /&gt;
:Btw: the main culprit is not the vertice numbers- but the objects numbers. So a, let's say 7.000.000 vertice aircraft divided into 1000 objects has a much bigger impact &lt;br /&gt;
: as a model with twice number of vertices but divided in only 50 objects. Means: combine all meshes into one object in Blender as long you don't need to animate in any way = &lt;br /&gt;
: One object + those objects which has to be animated (aileron, flap,...)!&lt;br /&gt;
&lt;br /&gt;
:Cheers&lt;br /&gt;
:--[[User:HHS|HHS]] ([[User talk:HHS|talk]]) 19:38, 3 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
::Yes, the UV coordinates direction needs to be consistent on the same mesh. You can have overlapping faces as long as they don't share an edge in the UV and/or they don't have one of the coordinates flipped. &amp;lt;s&amp;gt;(i would post some screenshots if not for the innane upload wizard :( )&amp;lt;/s&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::In the problematic example the middle face will be causing issues (it's U coordinates being flipped, and it shares the UV edge with the left face). In the problematic2 example the B1 (right) face will be causing issues, as it's V coordinates are flipped (mirrored)&lt;br /&gt;
::{{Gallery&lt;br /&gt;
|Ubershader_blender_uv_ok.png|UV OK1&lt;br /&gt;
|Ubershader_blender_uv_ok.png|UV OK2&lt;br /&gt;
|Ubershader_blender_uv_problem.png|UV Problem1&lt;br /&gt;
|Ubershader_blender_uv_problem1.png|UV Problem2&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
::[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 10:44, 4 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
I have very carefully gone over the three objects to make sure that the UV maps had no overlapping or 0 area faces in the UV map.  In the case of the cowl I actually removed parts of it that were not part of the main exterior surface.  These consisted of things like the cylindrical surfaces for the air intake holes, the edge and internal surfaces of the exhaust cutout, the internal air intake passages (behind the holes on the side of the cowl) and the front ring that is next to the spinner which are all now separate objects now.  The cowl in now much simpler (still a fairly complex shape in the chin scoop area) with no folded over edges or inside surfaces.    &lt;br /&gt;
&lt;br /&gt;
So here are some screen shots:&lt;br /&gt;
&lt;br /&gt;
[[File:Cowl UVMap.jpg|thumb|Cowl UVMap]]&lt;br /&gt;
[[File:Cowl In Sim Normals Normal.jpg|thumb|Cowl In Sim Normals Normal]]&lt;br /&gt;
[[File:Cowl In Sim Normals Flipped.jpg|thumb|Cowl In Sim Normals Flipped]]&lt;br /&gt;
&lt;br /&gt;
These are high res screen shots (about 4.5 mega pixels each) so you should be able to see all of the necessary details.  The background in the UV map screen shot is the actual texture being used.  The line and hole detail in the texture was used to create the normal map.&lt;br /&gt;
&lt;br /&gt;
[[User:Hvengel|Hvengel]] ([[User talk:Hvengel|talk]]) 18:08, 5 July 2014 (UTC) Hal&lt;br /&gt;
&lt;br /&gt;
:''Hi, I've moved your message here to have the discussion in one place.''&lt;br /&gt;
&lt;br /&gt;
:I took a look at the blender file. Sorry to say this but the mesh is a mess, and I suspect the somewhat flaky blender-2.6+ .ac export script is choking on it and spitting out garbage. &lt;br /&gt;
:For example on the '''cowl''' object there are 88 '''n-gons''' (faces with 5 or more vertices). This can cause issues with the winding order (which determines the respective face/normal orientation), even more so if the script tries to be smart and split those on its own. There is a blender script that's called '''MeshLint''' and can help with checking and fixing the meshes. You can find and enable it in the addons tab of the user-settings dialog. Try first manually splitting the n-gons into tris, recalculate normals and then re export the mesh from blender, see if that helps. &lt;br /&gt;
:I know working with booleans seems easier, but these are the ''hidden'' traps in that style of work, and you end up doing twice the work needed on the mesh to fix it up after the ''quick&amp;amp;dirty'' boolean operations.&lt;br /&gt;
:And that's a shame given the amount of work you obviously already put into it.&lt;br /&gt;
:HTH&lt;br /&gt;
:[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 19:01, 5 July 2014 (UTC) [[User:Hvengel|Hvengel]] ([[User talk:Hvengel|talk]]) 08:22, 6 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
:Got the MeshLint add in and went through the three meshes that are having issues and removed all n-gons.  Kind of time consuming but no too bad.   After all I only have to do one side then mirror it to get the other side. After removing all n-gons I then had Blender recalculate the normals and exported the model.  The issue is still there.&lt;br /&gt;
&lt;br /&gt;
As a side note the last objects I discovered that had this issue are the exhaust covers.  In these I cut the holes by hand since I couldn't get the boolean operation to work.  I also cut the exhaust cutouts in the cowl by hand and at one point these were nice clean looking cutouts.  But when i did the boolean operation to do the 32 1 inch holes for the filtered air intake Blender decided to mess with the exhaust cutouts.  But at that point I don't think there where any n-gons.  But the normals problem was still there even before I tried to clean things up.  I spent some time cleaning up the air intake holes and this is where the n-gons came from.&lt;br /&gt;
&lt;br /&gt;
I just had a close look at the exhaust covers and the one I looked at did have two n-gons.  I fixed those then flipped back to to normal and recalculated the normals and exported it.  Opening the .ac file in FG everything looked sort of OK except the inside of the mesh was bright and reflective.  This object has the normals of the front pointing outward and the normals of the back areas are pointing inward and these parts of the object are textured black.  But the back was acting like it's normals were flipped (IE. the back was black - showing the texture- on the outside when it should be showing this on the inside).  Turns out that this is acting just like the cowl and wing fairings.  So is unrelated to using a Boolean operation.&lt;br /&gt;
&lt;br /&gt;
Thinking things through a little it appears that all of the objects that are showing up black in the FGRUN 3D preview when the normals are the correct direction are objects where I did cutouts of some sort either by hand or using a Boolean operation in Blender.  For most of these I did NOT use a boolean operation. &lt;br /&gt;
&lt;br /&gt;
The export script definitely has issues but, at least with simpler models, works in most cases.  The way it behaves when something is not textured is very flawed in that it just fails with more or less hidden and very cryptic error messages.  I do UI work for a living and I would never let something that poorly designed out into the wild.  If it has such obvious UI issues who knows what kind of issues exist in the actually functionality.&lt;br /&gt;
&lt;br /&gt;
[[User:Hvengel|Hvengel]] ([[User talk:Hvengel|talk]]) 08:22, 6 July 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
===Most Likely Fix ===&lt;br /&gt;
:: Pfewww that was a hard one, and well hidden. The perils of transforming stuff in object mode in blender ;)&lt;br /&gt;
:: All these problem objects have negative scaling on at least one of the axes, and when the export script applies the transform, the normals get flipped. You'll notice it right away if you apply the transform first. Which you should do, to all objects, right away, to avoid this cropping up again. Fuselage isn't affected since it's not scaled. Examples below:&lt;br /&gt;
::{{Gallery&lt;br /&gt;
|Ubershader-isue-blender-cowl.jpg|Cowl&lt;br /&gt;
|Ubershader-isue-blender-exhaustcover.jpg|exhaustCoverLeft&lt;br /&gt;
|Ubershader-isue-blender-wingfillet.jpg|wingFilletLeft&lt;br /&gt;
|Ubershader-isue-blender-fuse.jpg|Fuse&lt;br /&gt;
}}&lt;br /&gt;
::Btw, a couple of issues that I noticed that '''will''' affect performance: all your meshes have '''double-sided''' faces in blender, make them '''single-sided'''; your textures have the '''alpha channel''' left in, this will affect performance with shaders disabled and will cause funny rendering bugs in Rembrandt. Remove the alpha channel for the textures that are applied to opaque objects.&lt;br /&gt;
::&lt;br /&gt;
::HTH, and cheers,&lt;br /&gt;
::[[User:I4dnf|I4dnf]] ([[User talk:I4dnf|talk]]) 16:06, 6 July 2014 (UTC)&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Create_custom_splash_screens&amp;diff=74009</id>
		<title>Howto:Create custom splash screens</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Create_custom_splash_screens&amp;diff=74009"/>
		<updated>2014-07-10T16:55:10Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Aircraft specific */ add information about full path to splash-texture nde&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A splash screen is an image that is displayed during the loading of [[FlightGear]]. They usually exist of a [[Howto: Make nice screenshots|screenshot]] of an [[aircraft]], together with the name/type of the aircraft and the name &amp;quot;FlightGear&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Creating custom splash screens''' is another thing that is very easy to do, just by looking at the documentation or by looking at existing aircraft, for example the default [[Cessna C172|C172P]].&lt;br /&gt;
&lt;br /&gt;
== Various kinds of splash screens ==&lt;br /&gt;
There are two kinds of splash screens:&lt;br /&gt;
* '''aircraft specific:''' packaged with an aircraft and only displayed when that specific aircraft is loaded.&lt;br /&gt;
* '''general:''' randomly picked and displayed when there is no custom splash screen for the aircraft that is loaded.&lt;br /&gt;
&lt;br /&gt;
=== Aircraft specific ===&lt;br /&gt;
The splash screen image is configured by the &amp;lt;tt&amp;gt;aircraft-set.xml&amp;lt;/tt&amp;gt;, where &amp;quot;aircraft&amp;quot; is the name of the aircraft. You can find these files in each aircraft's directory in &amp;lt;tt&amp;gt;[[$FG ROOT]]/Aircraft&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[File:C172p-folder-structure.png]]&lt;br /&gt;
&lt;br /&gt;
The set file supports a &amp;quot;splash-texture&amp;quot; tag in XML (just search for &amp;quot;splash-texture&amp;quot; using your text editor&amp;quot;), it should look like this and should be inside a &amp;amp;lt;sim&amp;amp;gt; tag and then a &amp;amp;lt;startup&amp;amp;gt; tag (so the path is /sim/startup/splash-texture):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;splash-texture&amp;gt;filename.png&amp;lt;/splash-texture&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note that for the time being, aircraft cannot have multiple custom splash screens.&lt;br /&gt;
&lt;br /&gt;
The filename is relative to the &amp;lt;tt&amp;gt;Aircraft/&amp;lt;/tt&amp;gt; directory and will differ among different aircraft, but often it just refers to &amp;quot;splash.png&amp;quot;. See for example the C172P:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;splash-texture&amp;gt;Aircraft/c172p/splash.png&amp;lt;/splash-texture&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, the image is located in &amp;lt;tt&amp;gt;[[$FG ROOT]]/Aircraft/c172p/splash.png&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
Aircraft that do not have a custom splash-texture specified, will be assigned a randomly chosen screen from the global &amp;lt;tt&amp;gt;[[$FG ROOT]]/Textures&amp;lt;/tt&amp;gt; directory. Editing and overwriting these screens (splash?.png) will affect all aircraft without aircraft specific screens.&lt;br /&gt;
&lt;br /&gt;
== Modifying/creating splash screens ==&lt;br /&gt;
The easiest thing for you to get started with, would be to simply load an existing splash screen image in an image editor (i.e. GIMP or Photoshop) and start modifying it. Once you are finished, you can save the file to the directory where your aircraft is located, using a filename such as &amp;quot;splash.png&amp;quot;, for an aircraft specific screen. In the aircraft-set.xml you will want to change the splash tag then, to refer to this image (case sensitive). &lt;br /&gt;
&lt;br /&gt;
You could also edit the general screens, the only difference here is that you overwrite one of the screens in the &amp;lt;tt&amp;gt;[[$FG ROOT]]/Textures&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
== Things to note ==&lt;br /&gt;
* '''Image dimensions &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; be powers of two''' (eg. 256x256 or 512x512 pixels), but as long as you really just edited existing splash screens, that should not be a problem.&lt;br /&gt;
* If you want to modify the splash screen of one particular aircraft, there is no reason to modify ANY splash screens outside your aircraft folder. Just add a splash screen to your aircraft folder (i.e. by copying a png or rgb file from another aircraft), add it to your aircraft-set.xml file and then modify the splash screen in your image editor.&lt;br /&gt;
&lt;br /&gt;
== Related content ==&lt;br /&gt;
* [[Howto: Make an aircraft]], specifically at the [[Howto: Make an aircraft#.3Csplash-texture.3E.3C.2Fsplash-texture.3E|splash texture section]].&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft enhancement|Create custom splash screens]]&lt;br /&gt;
[[Category:Howto|Create custom splash screens]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Initializing_Nasal_early&amp;diff=73954</id>
		<title>Initializing Nasal early</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Initializing_Nasal_early&amp;diff=73954"/>
		<updated>2014-07-09T22:00:36Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: move initial heading; don't use io.include&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Internals}}&lt;br /&gt;
&lt;br /&gt;
This is a summary of all discussions relating to:&lt;br /&gt;
* initializing the Nasal scripting interpreter earlier&lt;br /&gt;
* providing an integrated GUI front-end/launcher using [[Canvas]] and [[Nasal]]: [[Aircraft Center]]&lt;br /&gt;
* moving $FG_ROOT/Nasal initialization out of C++ into scripting space (aka &amp;quot;bootstrapping&amp;quot;) while introducing proper dependency resolution (inter- and intra-modular)&lt;br /&gt;
* decoupling FlightGear initialization such that certain subsystems can be optionally disabled right at the beginning&lt;br /&gt;
* making the initialization process/splash screen more responsive by using Nasal/Canvas instead of hard-coded GL code [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=22021] ({{Issue|1456}})&lt;br /&gt;
* allowing custom startup profiles/modes to be implemented via Nasal helper scripts, for example:&lt;br /&gt;
** [[FGCanvas]]&lt;br /&gt;
** [[FlightGear Benchmark]]&lt;br /&gt;
** [[FlightGear Headless]]&lt;br /&gt;
&lt;br /&gt;
== Objective ==&lt;br /&gt;
{{cquote|&lt;br /&gt;
The position init code is a little complex, to allow for starting on a carrier and some other cases, and ideally we would do it from script, but unfortunately there's some technical limitations on doing that. (Not insurmountable, but not quick either). Adding more cases to the position-init code is certainly doable - one suggestion I made some time ago, is when MP is active, to default to starting at a free parking position instead of on a runway. (When no startup position is provided at all). This would avoid people accidentally starting on the runway in MP events, which would be a big usability win.&lt;br /&gt;
&lt;br /&gt;
When no parking positions are defined, AI traffic defaults to the 'airport centre' location. Selection a taxiway parallel to the active runway is possible, but for complex airport layouts I can imagine many ways this logic could fail. Personally I think it would be more robust to stick to picking parking positions, and otherwise using the airport centre, because it would encourage people to add the parking position data :)&lt;br /&gt;
&lt;br /&gt;
I anyone wants to work on this, it would be a self-contained function in position-init code, just ask here for any questions. All the pieces certainly exist - the taxiways, parking locations and runways for the airport are all accessible.&amp;lt;ref&amp;gt;{{cite web |url=http://sourceforge.net/p/flightgear/mailman/attachment/F69E014E-F15A-4EAB-B512-36B87CA3B2C5%40mac.com/1/|title= Aircraft positioning on the runway|author=James Turner |date=2013-11-12 10:32:27}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |I would prefer to init Nasal earlier in startup, because I would like use [[Aircraft Center|Canvas-based UI for pieces such as aircraft-selection]] - but right now we have to load Nasal in postInit, which is seconds and seconds into startup. Most Nasal things that need FDM state already wait on fdm-initialized, so in ''theory'' the only fix required is to skip &amp;amp;lt;nasal&amp;amp;gt; evaluation in 'animation' XML files (apparently there is a long-standing assumption that such elements are skipped when loading an aircraft as the main one, i.e they are only run for AI / MP aircraft - this is a bad situation but changing it now could be a serious compatibility problem)&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=192734#p192734&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Modular Nasal &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;zakalawe&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sun Oct 27&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  | I am delighted to have this cleaned up, and a way to incrementally init bits of Nasal, but I would be much happier to see a patch of the C++ difs, the sooner the better, just in case you're doing something that is not going to work safely.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=192734#p192734&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Modular Nasal &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;zakalawe&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sun Oct 27&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |I really don't believe there should be an option to disable bootstrapping, it should just be an issue of matching FGData. Basically, if we have new-style scripts (i.e. using require() and deprecating &amp;quot;nasal-dir-initialized&amp;quot;), then we ''need'' a bootstrap script (because otherwise... we would have to reimplement the corresponding code in C++ space); else, we have old FGData (as I sometimes like to switch back to, to pursue other projects like the Nasal Browser) and we use the old C++ loading code.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=193231#p193231&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Modular Nasal bootstrapping (again)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;Philosopher&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Mon Nov 04&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  | it's mostly Nasal code in $FG_ROOT/Nasal where dependencies need to be better established and formalized to get rid of implicit assumptions regarding availability of certain subsystems (e.g. view.nas)&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=214206#p214206&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;FGCanvas Experiments &amp;amp; Updates&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sun Jul 06&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |revisit bootstrapping soon, because it's the only sane way to resolve dependencies (intra-module or even subsystem support).&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=214207#p214207&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: FGCanvas Experiments &amp;amp; Updates&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;Philosopher&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sun Jul 06&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |Given my recent &amp;quot;FGCanvas&amp;quot; experiments (making ~60% of the subsystems optional), and successes there, I'd probably consider handing off control to a hard-coded Nasal script in FGNasalSys, even though we could make the file-name property-configurable, whereas it would default to something like &amp;quot;default.boot&amp;quot;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
That would allow us to easily use --prop{{=}} (or a dedicated '''--mode{{=}}''') parameter to override the bootstrapping script. &amp;lt;br/&amp;gt;&lt;br /&gt;
Once that is place, we could also move certain fg_init.cxx logic to Nasal space by using Zakalawe's add-subsystem/remove-subsystem fgcommands, which I already started extending to allow subsystems to be registered as SGSubsystemGroup instead of &amp;quot;just&amp;quot; SGSubsystem - which allows us to use groups as &amp;quot;containers&amp;quot; for specific subsystems, like &amp;quot;aircraft&amp;quot; (fdm, autopilot, route  manager etc) or &amp;quot;audio&amp;quot; (fgcom, sound, voice). Making these entirely optional and runtime-configurable is becoming much more straightforward that way - also, because all the reset/re-init logic can be moved to each groups postinit/reinit methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Conceptually, that's straightforward to do, and apart from supporting different startup modes, we could even support &amp;quot;applications&amp;quot;, i.e. stuff  like running just the REPL, or just a canvas-map, or even just the Aircraft Center eventually.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
So, I'd prefer to load a single property-defined Nasal script and delegate control to it in FGNasalSys:init(), so that we can handle both there, nasal bootstrapping, but also subsystems at some point.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=214423#p214423&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Modular Nasal bootstrapping (again)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Wed Jul 09&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |for FGCanvas-testing, I just used a slightly-extended version of this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;diff&amp;quot;&amp;gt;&lt;br /&gt;
diff --git a/src/Main/options.cxx b/src/Main/options.cxx&lt;br /&gt;
index 0389faa..26eac9c 100644&lt;br /&gt;
--- a/src/Main/options.cxx&lt;br /&gt;
+++ b/src/Main/options.cxx&lt;br /&gt;
@@ -1434,8 +1434,9 @@ struct OptionDesc {&lt;br /&gt;
     int (*func)( const char * );&lt;br /&gt;
     } fgOptionArray[] = {&lt;br /&gt;
 &lt;br /&gt;
+    {&amp;quot;mode&amp;quot;,		     	     true,  OPTION_STRING, &amp;quot;/sim/startup/boot-script&amp;quot;, false, &amp;quot;default&amp;quot;, 0 },&lt;br /&gt;
     {&amp;quot;language&amp;quot;,                     true,  OPTION_IGNORE, &amp;quot;&amp;quot;, false, &amp;quot;&amp;quot;, 0 },&lt;br /&gt;
-	{&amp;quot;console&amp;quot;,                      false, OPTION_IGNORE,   &amp;quot;&amp;quot;, false, &amp;quot;&amp;quot;, 0 },&lt;br /&gt;
+    {&amp;quot;console&amp;quot;,                      false, OPTION_IGNORE,   &amp;quot;&amp;quot;, false, &amp;quot;&amp;quot;, 0 },&lt;br /&gt;
     {&amp;quot;disable-rembrandt&amp;quot;,            false, OPTION_BOOL,   &amp;quot;/sim/rendering/rembrandt/enabled&amp;quot;, false, &amp;quot;&amp;quot;, 0 },&lt;br /&gt;
     {&amp;quot;enable-rembrandt&amp;quot;,             false, OPTION_BOOL,   &amp;quot;/sim/rendering/rembrandt/enabled&amp;quot;, true, &amp;quot;&amp;quot;, 0 },&lt;br /&gt;
     {&amp;quot;renderer&amp;quot;,                     true,  OPTION_STRING, &amp;quot;/sim/rendering/rembrandt/renderer&amp;quot;, false, &amp;quot;&amp;quot;, 0 },&lt;br /&gt;
diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx&lt;br /&gt;
index fde6319..b8c2114 100644&lt;br /&gt;
--- a/src/Scripting/NasalSys.cxx&lt;br /&gt;
+++ b/src/Scripting/NasalSys.cxx&lt;br /&gt;
@@ -833,6 +833,7 @@ void FGNasalSys::init()&lt;br /&gt;
       .member(&amp;quot;singleShot&amp;quot;, &amp;amp;TimerObj::isSingleShot, &amp;amp;TimerObj::setSingleShot)&lt;br /&gt;
       .member(&amp;quot;isRunning&amp;quot;, &amp;amp;TimerObj::isRunning);&lt;br /&gt;
 &lt;br /&gt;
+#if 0&lt;br /&gt;
     // Now load the various source files in the Nasal directory&lt;br /&gt;
     simgear::Dir nasalDir(SGPath(globals-&amp;gt;get_fg_root(), &amp;quot;Nasal&amp;quot;));&lt;br /&gt;
     loadScriptDirectory(nasalDir);&lt;br /&gt;
@@ -845,6 +846,20 @@ void FGNasalSys::init()&lt;br /&gt;
         simgear::PathList scripts = dir.children(simgear::Dir::TYPE_FILE, &amp;quot;.nas&amp;quot;);&lt;br /&gt;
         addModule(directories[i].file(), scripts);&lt;br /&gt;
     }&lt;br /&gt;
+#endif&lt;br /&gt;
+&lt;br /&gt;
+    const char* boot_script = fgGetString(&amp;quot;/sim/startup/boot-script&amp;quot;, &amp;quot;default&amp;quot;);&lt;br /&gt;
+    SGPath fullpath(globals-&amp;gt;get_fg_root(), &amp;quot;Boot&amp;quot;);&lt;br /&gt;
+    fullpath.append(boot_script);&lt;br /&gt;
+    fullpath.concat(&amp;quot;.boot&amp;quot;);&lt;br /&gt;
+&lt;br /&gt;
+&lt;br /&gt;
+    SG_LOG(SG_NASAL, SG_INFO, &amp;quot;Using boot script:&amp;quot; &amp;lt;&amp;lt; fullpath);&lt;br /&gt;
+    SGPath file = fullpath.file();&lt;br /&gt;
+    if(!loadModule(fullpath, &amp;quot;boot&amp;quot;)) {&lt;br /&gt;
+    	SG_LOG(SG_NASAL, SG_ALERT, &amp;quot;Error could not load boot script:&amp;quot; &amp;lt;&amp;lt; fullpath);&lt;br /&gt;
+    exit(-1);&lt;br /&gt;
+    }&lt;br /&gt;
 &lt;br /&gt;
     // set signal and remove node to avoid restoring at reinit&lt;br /&gt;
     const char *s = &amp;quot;nasal-dir-initialized&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
As you can see, the file name of the &amp;quot;boot script&amp;quot; defaults to $FG_ROOT/Boot/default.boot but can be easily overridden to add custom modes.&amp;lt;br/&amp;gt;&lt;br /&gt;
Which is kinda where we could now add your bootstrap.nas logic and review the necessary C++ changes to make it work.&amp;lt;br/&amp;gt;&lt;br /&gt;
For testing purposes, I used io.nas as the template for my own boot script, i.e. to load globals.nas, props.nas etc&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Once the hard-coded functionality is re-implemented, we can explore making things better configurable, i.e. more optional, over time.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=214428#p214428&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Modular Nasal bootstrapping (again)&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Wed Jul 09&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For the sake of simplicity, we could refactor the ::init() method such that the common init code could be shared, between the initial startup Nasal interpreter, and the final runtime interpreter - so that we could load init code from a separate $FG_ROOT directory to do such things, without parsing all the stuff in $FG_ROOT/Nasal.&lt;br /&gt;
&lt;br /&gt;
Referring to the GLSL segfault fix and my earlier comment about defaulting to a NON-SHADER environment by adjusting shader quality level to 0 if shaders are unsupported: For now, this is obviously easy to simply hard-code by showing an ALERT message and overriding the shader settings from there on. &lt;br /&gt;
&lt;br /&gt;
However, in the long run, we'd probably want to simply delegate such stuff to Nasal space. While Nasal is currently not available that early, we could use a bare (or just temporary) Nasal instance during initialization to hand-off such stuff to scripting space. This seems to be an old idea actually (see the comments below from 2008) - and peopel were actually working on having Nasal + GUI code up really early back in 2008.&lt;br /&gt;
&lt;br /&gt;
Given the state of the current init code in fg_init.cxx, the idea of factoring stuff out into Nasal space is very appealing - which means having less unmaintained C++ spaghetti code, and things like processing startup arguments can be really easily done from Nasal space, what's needed is &amp;quot;only&amp;quot; the props code - or rather just setprop/getprop, which would allow simple logic to be moved to scripting space - and it would not even be performance-critical.&lt;br /&gt;
&lt;br /&gt;
In other words, it would be sensible to pick up the old idea and make a minimal Nasal interpreter available early on, and pass control to it - so that things like thís can be easily run, without hard-coding any logic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
if (getprop(&amp;quot;/sim/rendering/gl-shading-language-version&amp;quot;)==&amp;quot;UNSUPPORTED&amp;quot;) {&lt;br /&gt;
print(&amp;quot;Warning: Shaders unavailable, defaulting to quality level 0!\n&amp;quot;)&lt;br /&gt;
setprop(&amp;quot;/sim/rendering/shaders/quality-level&amp;quot;, 0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{cquote|The only catch is, subsystems are initialised late, but I need a handful to be up before I can use the GUI dialogs; obviously the GUI subsystem itself, but also Nasal and a few others. (There are some issues with initialising nasal early, it is currently deliberately being done very late, but more on that later...)&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg03373.html|title=&amp;lt;nowiki&amp;gt;[Flightgear-devel]&amp;lt;/nowiki&amp;gt; Subsystem run-levels|author=James Turner|date=Mon, 17 Apr 2006 13:51:07 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I would appreciate if Nasal were around the first subsystems to be initialized. But this would require some Nasal dependency resolution. Almost all Nasal code needs globals.nas, and most need props.nas, too (which needs globals.nas). gui.nas needs globals.nas and props.nas, and screen.nas&lt;br /&gt;
needs all three etc. This needs to be taken care of if Nasal is to be initialized early.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg03390.html|title=&amp;lt;nowiki&amp;gt;[Flightgear-devel]&amp;lt;/nowiki&amp;gt; Re: Subsystem run-levels|author=Melchior FRANZ|date=Tue, 18 Apr 2006 03:37:04 -0700}}&amp;lt;/ref&amp;gt;|Melchior FRANZ}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|starting up the interpreter (the first part of  FGNasalSys::init) can be done very early (and quickly), and the subsytem would then wait for a relatively high-valued 'init' call before running scripts (the part that needs all other properties to be defined).&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg03373.html|title=&amp;lt;nowiki&amp;gt;[Flightgear-devel]&amp;lt;/nowiki&amp;gt; Subsystem run-levels|author=James Turner|date=Mon, 17 Apr 2006 13:51:07 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I'm sure other people can propose potential groups, but I'd imagine:&lt;br /&gt;
&lt;br /&gt;
	early (nasal itself, GUI)&lt;br /&gt;
	time based subsystems (ephemeris, datetime, warp, properties, interpolator)&lt;br /&gt;
	environmental (weather fetch)&lt;br /&gt;
	aircraft systems (FDM, electrical, cockpit?, instruments, failures, GPS)&lt;br /&gt;
	scenery (tile manager, views, panels)&lt;br /&gt;
	input &lt;br /&gt;
	IO subsystems - ATC, traffic, multiplayer&lt;br /&gt;
	sound&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg03401.html|title=Re: &amp;lt;nowiki&amp;gt;[Flightgear-devel]&amp;lt;/nowiki&amp;gt; Subsystem run-levels|author=James Turner|date=Tue, 18 Apr 2006 08:23:01 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I will start the systems I need (Nasal, GUI and input) early. This might also help make the startup progress a bit more fine-grained.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg03418.html|title=&amp;lt;nowiki&amp;gt;[Flightgear-devel]&amp;lt;/nowiki&amp;gt; Run-levels redux.|author=James Turner|date=Wed, 19 Apr 2006 06:43:14 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|In the even longer run, we'd actually want to associate the Nasal scripts with run-levels (/etc/rc.d, anyone?), since the frontend GUI might want a few scripts loaded, while I assume most are only relevant when actually flying. Such a change also makes postinit() unnecessary, I think - since the effect can always be achieved by having init() watch for a higher run-level.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg03373.html|title=&amp;lt;nowiki&amp;gt;[Flightgear-devel]&amp;lt;/nowiki&amp;gt; Subsystem run-levels|author=James Turner|date=Mon, 17 Apr 2006 13:51:07 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
[[Category:Developer Plans]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Animate_gear_scissors&amp;diff=73450</id>
		<title>Howto:Animate gear scissors</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Animate_gear_scissors&amp;diff=73450"/>
		<updated>2014-06-29T10:47:13Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This [[:Category:Howto|HOWTO]] describes how to create an animation for landing gear scissors using an interpolation lookup table and no [[nasal]] code.&lt;br /&gt;
&lt;br /&gt;
{{Note|For FlightGear 2.11+ the [[Tracking_animation|tracking animation]] provides a more accurate and easier way of animating gear scissor.}}&lt;br /&gt;
&lt;br /&gt;
== Required tools ==&lt;br /&gt;
* A tool to measure distances in 3D models like [[AC3D]] or [[Blender]]. The images shown in this HOWTO uses AC3D but any other application should be fine.&lt;br /&gt;
* The standalone version of the nasal interpreter. Get it here: [http://www.plausible.org/nasal/ http://www.plausible.org/nasal/]&lt;br /&gt;
* A XML editor or a plain text editor. EDLIN should do but there are probably others...&lt;br /&gt;
* This little peace of nasal code. Copy and paste this code into a file called '''gearscissor.nas'''.&lt;br /&gt;
 import(&amp;quot;math&amp;quot;);&lt;br /&gt;
 var acos = func(x) { math.atan2(math.sqrt(math.abs(1-x*x)), x) }&lt;br /&gt;
 var R2D = 180.0 / math.pi;&lt;br /&gt;
 &lt;br /&gt;
 var scissor_dist = PUT SCISSOR_DIST HERE;&lt;br /&gt;
 var scissor = PUT SCISSOR HERE;&lt;br /&gt;
 var oleo = PUT OLEO HERE;&lt;br /&gt;
 &lt;br /&gt;
 var theta0 = acos(scissor_dist/2/scissor) * R2D;&lt;br /&gt;
 print( &amp;quot;&amp;lt;?xml version = '1.0' encoding = 'UTF-8' ?&amp;gt;\n&amp;quot; );&lt;br /&gt;
 print( &amp;quot;&amp;lt;PropertyList&amp;gt;\n&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
 for( var i = 0; i &amp;lt; 1.05; i += 0.05 ) {&lt;br /&gt;
   print( &amp;quot;&amp;lt;entry&amp;gt;\n&amp;quot; );&lt;br /&gt;
   var l = (1.0-i) * oleo/2;&lt;br /&gt;
   l += (scissor_dist-oleo)/2;&lt;br /&gt;
   print( &amp;quot;&amp;lt;ind&amp;gt;&amp;quot; ~ sprintf(&amp;quot;%4.3f&amp;quot;, i ) ~ &amp;quot;&amp;lt;/ind&amp;gt;\n&amp;quot; );&lt;br /&gt;
   print( &amp;quot;&amp;lt;dep&amp;gt;&amp;quot; ~ sprintf(&amp;quot;%4.3f&amp;quot;, acos( l / scissor ) * R2D - theta0 ) ~ &amp;quot;&amp;lt;/dep&amp;gt;\n&amp;quot; );&lt;br /&gt;
   print( &amp;quot;&amp;lt;/entry&amp;gt;\n&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
 print( &amp;quot;&amp;lt;/PropertyList&amp;gt;\n&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
== Let's go ==&lt;br /&gt;
[[File:Howto- animate gear scissors scissor dist.jpg|thumb|250px|The scissor distance]]&lt;br /&gt;
First open the 3D model in AC3D and look for the gear to animate. The two scissor elements need to be named as individual objects. Let's call them '''A''' and '''B''' as an example. It is not within the scope of this document to describe how to create or name objects in the 3D model.&lt;br /&gt;
Our first step is to create the interpolation table to be included in the animation xml file.&lt;br /&gt;
Open your above created file gearscissor.nas in a text editor and look for the line&lt;br /&gt;
 var scissor_dist = PUT SCISSOR_DIST HERE;&lt;br /&gt;
Measure the distance between the two vertices marking the two rotation axes of the two scissor elements. Check the image on the right, the two vertices are marked as green dots. Replace the text PUT SCISSOR_DIST HERE with this value.&lt;br /&gt;
&lt;br /&gt;
[[File:Howto- animate gear scissors scissor.jpg|thumb|250px|The scissor length]]&lt;br /&gt;
Next, measure the distance between the two rotation axes of one scissor arm. Check the image on the right as a visual reference. Put the value into the line&lt;br /&gt;
 var scissor = PUT SCISSOR HERE&lt;br /&gt;
and replace the text PUT SCISSOR HERE with this value.&lt;br /&gt;
&lt;br /&gt;
[[File:Howto- animate gear scissors oleo.jpg|thumb|250px|The oleo strut]]&lt;br /&gt;
Finally you need the length of the oleo strut, the maximum compression length of the oleo strut. Measure the distance like in the examle image and place the value into the line &lt;br /&gt;
 var oleo = PUT OLEO HERE;&lt;br /&gt;
Replace PUT OLEO HERE with the value.&lt;br /&gt;
&lt;br /&gt;
Save the file, and run the file through the nasal interpreter by calling&lt;br /&gt;
 nasal gearscissor.nas&lt;br /&gt;
&lt;br /&gt;
This should produce a lot of output. This is the interpolation table that checks the compression of the gear strut and derives the angular deflection of the scissor arm. It should look like this:&lt;br /&gt;
 &amp;lt;?xml version = '1.0' encoding = 'UTF-8' ?&amp;gt;&lt;br /&gt;
 &amp;lt;PropertyList&amp;gt;&lt;br /&gt;
 &amp;lt;entry&amp;gt;&lt;br /&gt;
 &amp;lt;ind&amp;gt;0.000&amp;lt;/ind&amp;gt;&lt;br /&gt;
 &amp;lt;dep&amp;gt;-0.074&amp;lt;/dep&amp;gt;&lt;br /&gt;
 &amp;lt;/entry&amp;gt;&lt;br /&gt;
 &amp;lt;entry&amp;gt;&lt;br /&gt;
 &amp;lt;ind&amp;gt;0.050&amp;lt;/ind&amp;gt;&lt;br /&gt;
 &amp;lt;dep&amp;gt;3.816&amp;lt;/dep&amp;gt;&lt;br /&gt;
 &amp;lt;/entry&amp;gt;&lt;br /&gt;
 &amp;lt;entry&amp;gt;&lt;br /&gt;
 &amp;lt;ind&amp;gt;0.100&amp;lt;/ind&amp;gt;&lt;br /&gt;
 &amp;lt;dep&amp;gt;7.345&amp;lt;/dep&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 &amp;lt;/PropertyList&amp;gt;&lt;br /&gt;
Your numbers will look different but the structure should be the same. Save this output into a file named '''GearScissorInterpolation.xml''' and save this file in the same folder where your 3D model lives.&lt;br /&gt;
Note: in a console environment, you can usually save a program's output by forwarding it to a file using the &amp;gt; operator:&lt;br /&gt;
&lt;br /&gt;
  ./nasal gearscissor.nas &amp;gt; GearScissorInterpolation.xml&lt;br /&gt;
&lt;br /&gt;
== The animation XML ==&lt;br /&gt;
Before you continue, locate the rotation points of the two scissor arms where they are connected to the main strut. These are the vertices that were marked to measure the scissor distance.&lt;br /&gt;
Open the XML file that contains the animations for you model and add the following lines within the &amp;lt;PropertyList&amp;gt;&amp;lt;/PropertyList&amp;gt; elements:&lt;br /&gt;
 &amp;amp;lt;animation&amp;gt;&lt;br /&gt;
    &amp;amp;lt;type&amp;gt;rotate&amp;lt;/type&amp;gt;&lt;br /&gt;
    &amp;amp;lt;object-name&amp;gt;A&amp;lt;/object-name&amp;gt;&lt;br /&gt;
    &amp;amp;lt;property&amp;gt;gear/gear[1]/compression-norm&amp;lt;/property&amp;gt;&lt;br /&gt;
    &amp;amp;lt;axis&amp;gt;&lt;br /&gt;
      &amp;amp;lt;x&amp;gt;-1&amp;lt;/x&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/axis&amp;gt;&lt;br /&gt;
    &amp;amp;lt;center&amp;gt;&lt;br /&gt;
      &amp;amp;lt;x-m&amp;gt;YOUR X LOCATION OF THE ROTATION POINT HERE&amp;lt;/x-m&amp;gt;&lt;br /&gt;
      &amp;amp;lt;y-m&amp;gt;YOUR Y LOCATION OF THE ROTATION POINT HERE&amp;lt;/y-m&amp;gt;&lt;br /&gt;
      &amp;amp;lt;z-m&amp;gt;YOUR Z LOCATION OF THE ROTATION POINT HERE&amp;lt;/z-m&amp;gt;&lt;br /&gt;
    &amp;amp;lt;/center&amp;gt;&lt;br /&gt;
    &amp;amp;lt;interpolation include=&amp;quot;GearScissorInterpolation.xml&amp;quot;/&amp;gt;&lt;br /&gt;
 &amp;lt;/animation&amp;gt;&lt;br /&gt;
Fill in your values for x-m, y-m and z-m for the location of the rotation vertices. Add another section for the second scissor arm, replace the object-name with '''B''' and set the axis to +1 instead of -1.&lt;br /&gt;
If you see the scissors move in the opposite direction, exchange the sign in the axis definition.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
Check out the [[Hamburger Flugzeugbau HFB 320 Hansa Jet|HansaJet]] and the [[Piper PA34-200T Seneca II|Seneca II]]. Both [[aircraft]] use the above technique for the animation.&lt;br /&gt;
&lt;br /&gt;
[[Category:Howto|Animate gear scissors]]&lt;br /&gt;
[[Category:Modeling|Animate gear scissors]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Nasal_Metaprogramming&amp;diff=73442</id>
		<title>Howto:Nasal Metaprogramming</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Nasal_Metaprogramming&amp;diff=73442"/>
		<updated>2014-06-29T02:39:02Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* bind() */ huh... I always believed bind() returned its first argument and mutated the closures, but apparently it never has... not since it was introduced in 2005: https://github.com/andyross/nasal/commit/3bb78b7bdcd01ae9ff6afee51338253a0fea99f6.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Nasal Navigation}}&lt;br /&gt;
{{WIP}}&lt;br /&gt;
&lt;br /&gt;
== call() ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var foo = func {&lt;br /&gt;
 print( me.x );&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
call( foo, [], {x:100} );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== closure() ==&lt;br /&gt;
Find the closure of a function, or nil if it does not exist. &amp;quot;Closure&amp;quot; is the name given to an outer namespace of a function; when considering a variable name (like &amp;quot;i&amp;quot;), that variable name is looked for in the current execution frame (the &amp;quot;locals&amp;quot; namespace) then any closures of the function. Closures are stored via two items in the internal structure of a function: a namespace (hash), which is the first to recurse to, and a link to another function (or nil if there isn't one), which stores an additional namespace and potentially another outer function. This creates a chain of namespaces stored in the functions.&lt;br /&gt;
&lt;br /&gt;
The default closures for a new function (either a &amp;lt;tt&amp;gt;func {}&amp;lt;/tt&amp;gt; expression or the return from compile()) are the immediate caller's namespace and function, so any local variables declared before/after the function (not inside!) become the first closure, and any closures of the current function are found by the new function. The closures, once set, become semi-permanent, and remain with the function until changed via bind(), even though they may be referenced from completely different places and namespaces. For more on closures see [[#bind()]].&lt;br /&gt;
&lt;br /&gt;
;1st argument&lt;br /&gt;
* The function to find the closure of.&lt;br /&gt;
;2nd argument (optional; default&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt; 0)&amp;lt;!-- FIXME: why nowiki?--&amp;gt;&lt;br /&gt;
* The number of closures to look through.&lt;br /&gt;
&lt;br /&gt;
== caller() ==&lt;br /&gt;
&lt;br /&gt;
== compile () ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var x = 100;&lt;br /&gt;
var source_code = &amp;quot;print(x);&amp;quot;;&lt;br /&gt;
var code = compile(source_code);&lt;br /&gt;
code();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var location = func {&lt;br /&gt;
  var called_by = caller();&lt;br /&gt;
  var file = called_by [2];&lt;br /&gt;
  var line = called_by [3];&lt;br /&gt;
  return &amp;quot;file:&amp;quot;~ file ~'@ line:'~ line;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var x = 100;&lt;br /&gt;
var source_code = &amp;quot;print(x);&amp;quot;;&lt;br /&gt;
print( location() );&lt;br /&gt;
var code = compile(source_code, location() );&lt;br /&gt;
code();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var namespace = {&lt;br /&gt;
 x:1, y:2, z:3,&lt;br /&gt;
 print: print&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var source_code = &amp;quot;print(x);&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
var code = compile(source_code );&lt;br /&gt;
code = bind(code, namespace,nil);&lt;br /&gt;
code();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== bind() ==&lt;br /&gt;
Creates a new function based on the function that is passed and sets its first closure and closure function.&lt;br /&gt;
&lt;br /&gt;
;1st argument&lt;br /&gt;
* The function whose closures will be modified.&lt;br /&gt;
;2nd argument (optional)&lt;br /&gt;
* The first closure (i.e., outer namespace) to bind to, as a hash.&lt;br /&gt;
;3rd argument (optional)&lt;br /&gt;
* Another function, whose closure(s) are recursed into.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
# make a function&lt;br /&gt;
var fn = func ;&lt;br /&gt;
# make a &amp;quot;namespace&amp;quot;&lt;br /&gt;
var namespace = {};&lt;br /&gt;
# re-bind the function to that namespace, which becomes the first closure of the function, erasing any/all others&lt;br /&gt;
var fn = bind(fn, namespace);&lt;br /&gt;
# assertion&lt;br /&gt;
if (closure(fn, 0) != namespace) die(&amp;quot;bind() or closure() error!&amp;quot;);&lt;br /&gt;
# another function: the currently executing one&lt;br /&gt;
var other_fn = caller(0)[1];&lt;br /&gt;
# re-bind the function to the namespace and all closures of *other_fn*&lt;br /&gt;
var fn = bind(fn, namespace, other_fn);&lt;br /&gt;
# same assertion holds&lt;br /&gt;
if (closure(fn, 0) != namespace) die(&amp;quot;bind() or closure() error!&amp;quot;);&lt;br /&gt;
# assertion for all other closures: closure(fn, i) must equal closure(other_fn, i-1)&lt;br /&gt;
var i = 1;&lt;br /&gt;
while ((var cl = closure(other_fn, i-1)) != nil) {&lt;br /&gt;
    if (closure(fn, i) != nil) die(&amp;quot;bind() or closure() error!&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
# re-bind the function to the default closures, viz., namespace=caller(0)[0] and fn=caller(0)[1]&lt;br /&gt;
# (this is the default when we have a *func {}* expression, or equivalently, any function we get from compile())&lt;br /&gt;
var fn = bind(fn, caller(0)[0], caller(0)[1]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calling methods in Bindings ==&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var function = namespace.class.method;&lt;br /&gt;
var arguments = [&amp;quot;Hello World&amp;quot;];&lt;br /&gt;
var me = caller(0)[0];&lt;br /&gt;
call(function, arguments, me );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Browser&amp;diff=73391</id>
		<title>Nasal Browser</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Browser&amp;diff=73391"/>
		<updated>2014-06-28T12:10:23Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Nasal Namespace Browser Prototype.png|350px|thumb|Screen shot showing the new [[Nasal Browser|Nasal Namespace Browser]] that is currently being worked on by Philosopher.]]&lt;br /&gt;
{{Nasal Navigation}}&lt;br /&gt;
{{WIP}}&lt;br /&gt;
The '''Nasal '''('''Namespace''')''' Browser''' is a new dialog (3.3+) that allows the user to peek at the internal state of Nasal (starting from the global namespace). It displays a alphabetical list of keys mapped to values using the [[Canvas]] framework. Hashes and vectors are shown as their size and can be entered into via clicking on them; scalars' complete values are shown while ghosts and other types and represented in brackets.&lt;br /&gt;
&lt;br /&gt;
{{Note|Per-update performance of the dialog (i.e. how fast it runs) is determined by how big the namespace is. On the developer's computer, it takes about 20–30ms to update the global namespace, much less for much smaller namespaces. The dialog is automatically updated about every 0.6 seconds.}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Each entry is color-coded by type and scrollable via the Canvas scroll widget, sorted either by name or type and name. In a hash, each key is shown as either a string, a number, or a symbol, depending on what it really is (i.e. a scalar may be numeric but still a string; also, interned symbols are special cases of strings). Strings are shown in single quotes, symbols and numbers are shown without quotes. For strings, the brightness of the color is optionally reduced.&lt;br /&gt;
&lt;br /&gt;
If the binary includes the debug.decompile extension function (i.e. is part of [[User:Philosopher/Nasal introspection|extended-nasal]]) then functions can a optionally be shown with their arguments, e.g. isa = &amp;amp;lt;func(obj,class)&amp;amp;gt; while _setlistener = &amp;amp;lt;internal func&amp;amp;gt; (in the sense of a function implemented in C/C++).&lt;br /&gt;
&lt;br /&gt;
Values can be edited when they are clicked on; the edit bar then becomes activated and will capture key presses. A valid Nasal expression should be entered, which will be executed on {{key press|Enter}}.&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Nasal_introspection&amp;diff=73318</id>
		<title>User:Philosopher/Nasal introspection</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Nasal_introspection&amp;diff=73318"/>
		<updated>2014-06-26T18:52:38Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Nasal Internals}}&lt;br /&gt;
&lt;br /&gt;
Used to be working on getting Nasal to profile itself in a running FlightGear session. Currently more focused on introspection through debug.decompile()/.recompile() helpers that expose code objects. See progress at the &amp;quot;extended-nasal&amp;quot; branches of [https://gitorious.org/~philosopher/fg/philosophers-simgear] [https://gitorious.org/~philosopher/fg/philosophers-flightgear] [https://gitorious.org/~philosopher/fg/philosophers-fgdata] and the gen library [https://gitorious.org/nasal-library/gen-lib].&lt;br /&gt;
&lt;br /&gt;
The basic concept is to expose hooks/callbacks from the C source that get exposed to Nasal – so that Nasal does all the processing (and even collection of stats), but this requires a lot of core changes and is hard even to do from the Nasal end (I've found quite a challenge in it). The profiling script is currently fgdata:extended-nasal/Nasal/test.nas (WIP).&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Nasal_introspection&amp;diff=73317</id>
		<title>User:Philosopher/Nasal introspection</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Nasal_introspection&amp;diff=73317"/>
		<updated>2014-06-26T18:49:52Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Nasal Internals}}&lt;br /&gt;
&lt;br /&gt;
Used to be working on getting Nasal to profile itself in a running FlightGear session. Currently more focused on introspection through debug.decompile()/.recompile() helpers that expose code objects. See progress at the &amp;quot;extended-nasal&amp;quot; branches of [https://gitorious.org/~philosopher/fg/philosophers-simgear] [https://gitorious.org/~philosopher/fg/philosophers-flightgear] [https://gitorious.org/~philosopher/fg/philosophers-fgdata].&lt;br /&gt;
&lt;br /&gt;
The basic concept is to expose hooks/callbacks from the C source that get exposed to Nasal – so that Nasal does all the processing (and even collection of stats), but this requires a lot of core changes and is hard even to do from the Nasal end (I've found quite a challenge in it). The profiling script is currently fgdata:extended-nasal/Nasal/test.nas (WIP).&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher&amp;diff=73301</id>
		<title>User:Philosopher</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher&amp;diff=73301"/>
		<updated>2014-06-26T18:03:59Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Sub-pages:''' (mostly stubs ATM)&lt;br /&gt;
* [[User:Philosopher/Advanced Input Programming|Advanced Input Programming]]&lt;br /&gt;
* [[User:Philosopher/Howto:Write Optimized Nasal Code|Howto Write Optimized Nasal Code]]&lt;br /&gt;
* [[User:Philosopher/Nasal introspection|Nasal introspection!]]&lt;br /&gt;
* [[User:Philosopher/Optimization findings|Optimization findings]] (from [[User:Philosopher/Nasal introspection|Nasal introspection]])&lt;br /&gt;
&lt;br /&gt;
Sometimes working on improving Nasal internals and documenting them. Has the '''best''' joystick bindings (for a cheap joystick :P) at [http://flightgear.org/forums/viewtopic.php?t=17263 this topic]. Most recently working on various Canvas dialogs/frameworks.&lt;br /&gt;
&lt;br /&gt;
Likes reading through C/C++ code for fun, and understanding, documenting, and improving it – though I'm far from an expert in either and my hat is continually off to Andy, Thomas, and James (and everyone else) for their wonderful code. Oddly enough, I find Nasal code to be harder to read, probably due to the fact that C/C++ and very structured languages and Nasal is not (it almost needs DbC at times!).&lt;br /&gt;
&lt;br /&gt;
Favorite languages:&lt;br /&gt;
* Nasal (of course)&lt;br /&gt;
* Python (was my first language; I like most things about it except its duck typing – which works well until I actually need typing)&lt;br /&gt;
* C &amp;amp; C++ (different beasts; I like C++'s classes and ::iterators in particular)&lt;br /&gt;
* Languages yet to be discovered: I hope to find more that I like!&lt;br /&gt;
&lt;br /&gt;
Things to be doing:&lt;br /&gt;
* [[Improving the Joystick GUI]]: porting to Canvas, tweaking things, and integration with back-end when ready.&lt;br /&gt;
* Nasal bootstrapping: get started again, commit in a useable state, but needs design and implementation first.&lt;br /&gt;
* Joystick-Philosopher (bindings for Cyborg-X): improve the control_function library.&lt;br /&gt;
* Nasal improvement for whatever release (LaTeX document, making patches and applying patches to SimGear), making sure it doesn't crash.&lt;br /&gt;
* Canvas Map: working on [[MapStructure]].nas, to replace old map.nas &amp;amp;c.&lt;br /&gt;
* Consolidating gen library, hopefully committing once bootstrapping is also committed. Make sure it doesn't crash the interpreter or reinstall Linux!&lt;br /&gt;
* Fixing bugs, tweaking small things :-).&lt;br /&gt;
&lt;br /&gt;
Projects on the wiki:&lt;br /&gt;
* [[Interactive Nasal Console]]&lt;br /&gt;
* [[Nasal Browser]]&lt;br /&gt;
* [[MapStructure]]&lt;br /&gt;
* [[User:Philosopher/Nasal introspection|Nasal Introspection]]&lt;br /&gt;
&lt;br /&gt;
Good ideas:&lt;br /&gt;
* Expose the catapult locations to the property tree, for JSBSim 'craft and Nasal tutorials.&lt;br /&gt;
* [http://flightgear.org/forums/viewtopic.php?f=18&amp;amp;t=19666 Changing behavior of SGPropertyNodes without tying] (something like {{issue|336}}).&lt;br /&gt;
* (In conjunction with Hooray) Have Nasal load itself: besides for one file (either Nasal/globals.nas or something in [[$FG_ROOT]]), ''all'' Nasal should be loaded from Nasal.  (Including &amp;lt;tt&amp;gt;--prop:/nasal/module_name/script&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--prop:/nasal/module_name/file&amp;lt;/tt&amp;gt;.) See [http://flightgear.org/forums/viewtopic.php?f=30&amp;amp;t=21083] &amp;amp; [http://forum.flightgear.org/viewtopic.php?f=30&amp;amp;t=21083] {{Progressbar|50}}.&lt;br /&gt;
&lt;br /&gt;
Nasal thoughts area:&lt;br /&gt;
* I would like to include small improvements that enhance my quality of life in SimGear: string slicing, hash iteration using foreach/forindex, save/restore aka stash? (latter to be discussed)&lt;br /&gt;
* Hooray and I talk about more extension functions to allow looking into internals; I need to review all of these, gather them up, add to them, etc., and hope they can be included somewhere (Hooray was saying maybe just the standalone Nasal in SimGear, not FlightGear's runtime).&lt;br /&gt;
** Sub-idea: if we only include the extensions in standalone and we have optimizer/post-compiler scripts ready, then make a script to be run with standalone that optimizes any or all Nasal files and outputs an optimized version (*.nas.optimized) or even just the bytecode (*.nas.opcode, textual file ofc) and have that be the preferred loading method (if the text is older than the optimized version).&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Browser&amp;diff=73299</id>
		<title>Nasal Browser</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Browser&amp;diff=73299"/>
		<updated>2014-06-26T17:57:14Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Features */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Nasal Namespace Browser Prototype.png|350px|thumb|Screen shot showing the new [[Nasal Browser|Nasal Namespace Browser]] that is currently being worked on by Philosopher.]]&lt;br /&gt;
{{Nasal Navigation}}&lt;br /&gt;
{{WIP}}&lt;br /&gt;
The '''Nasal '''('''Namespace''')''' Browser''' is a new dialog (3.3+) that allows the user to peek at the internal state of Nasal (starting from the global namespace). It displays a alphabetical list of keys mapped to values using the [[Canvas]] framework. Hashes and vectors are shown as their size and can be entered into via clicking on them; scalars' complete values are shown while ghosts and other types and represented in brackets.&lt;br /&gt;
&lt;br /&gt;
{{Note|Per-update performance of the dialog (i.e. how fast it runs) is determined by how big the namespace is. On the developer's computer, it takes about 20–30ms to update the global namespace, much less for much smaller namespaces. The dialog is automatically updated about every 0.6 seconds.}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Each entry is color-coded by type and scrollable via the Canvas scroll widget, sorted either by name or type and name. In a hash, each key is shown as either a string, a number, or a symbol, depending on what it really is (i.e. a scalar may be numeric but still a string; also, interned symbols are special cases of strings). Strings are shown in single quotes, symbols and numbers are shown without quotes. For strings, the brightness of the color is optionally reduced.&lt;br /&gt;
&lt;br /&gt;
If the binary includes the debug.decompile extension function (i.e. is part of [[User:Philosopher/Nasal introspection|extended-nasal]]) then functions can a optionally be shown with their arguments, e.g. isa = &amp;amp;lt;func(obj,class)&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Values can be edited when they are clicked on; the edit bar becomes activated and will capture key presses. A valid Nasal expression should be entered, which will be executed on {{key press|Enter}}.&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher&amp;diff=73298</id>
		<title>User:Philosopher</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher&amp;diff=73298"/>
		<updated>2014-06-26T17:46:24Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: updates now that summer is here&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Sub-pages:''' (mostly stubs ATM)&lt;br /&gt;
* [[User:Philosopher/Advanced Input Programming|Advanced Input Programming]]&lt;br /&gt;
* [[User:Philosopher/Howto:Write Optimized Nasal Code|Howto Write Optimized Nasal Code]]&lt;br /&gt;
* [[User:Philosopher/Nasal introspection|Nasal introspection!]]&lt;br /&gt;
* [[User:Philosopher/Optimization findings|Optimization findings]] (from [[User:Philosopher/Nasal introspection|Nasal introspection]])&lt;br /&gt;
&lt;br /&gt;
Currently working on improving Nasal internals and documenting them. Has the '''best''' joystick bindings (for a cheap joystick :P) at [http://flightgear.org/forums/viewtopic.php?t=17263 this topic].&lt;br /&gt;
&lt;br /&gt;
Likes reading through C/C++ code for fun, and understanding, documenting, and improving it – though I'm far from an expert in either and my hat is continually off to Andy, Thomas, and James (and everyone else) for their wonderful code. Oddly enough, I find Nasal code to be harder to read, probably due to the fact that C/C++ and very structured languages and Nasal is not (it almost needs DbC at times!).&lt;br /&gt;
&lt;br /&gt;
Favorite languages:&lt;br /&gt;
* Nasal (of course)&lt;br /&gt;
* Python (was my first language; I like most things about it except its duck typing – which works well until I actually need typing)&lt;br /&gt;
* C &amp;amp; C++ (different beasts; I like C++'s classes and ::iterators in particular)&lt;br /&gt;
* Languages yet to be discovered: I hope to find more that I like!&lt;br /&gt;
&lt;br /&gt;
Things to be doing:&lt;br /&gt;
* [[Improving the Joystick GUI]]: porting to Canvas, tweaking things, and integration with back-end when ready.&lt;br /&gt;
* Nasal bootstrapping: get started again, commit in a useable state, but needs design and implementation first.&lt;br /&gt;
* Joystick-Philosopher (bindings for Cyborg-X): improve the control_function library.&lt;br /&gt;
* Nasal improvement for whatever release (LaTeX document, making patches and applying patches to SimGear), making sure it doesn't crash.&lt;br /&gt;
* Canvas Map: working on [[MapStructure]].nas, to replace old map.nas &amp;amp;c.&lt;br /&gt;
* Consolidating gen library, hopefully committing once bootstrapping is also committed. Make sure it doesn't crash the interpreter or reinstall Linux!&lt;br /&gt;
* Fixing bugs, tweaking small things :-).&lt;br /&gt;
&lt;br /&gt;
Projects on the wiki:&lt;br /&gt;
* [[Interactive Nasal Console]]&lt;br /&gt;
* [[Nasal Browser]]&lt;br /&gt;
* [[MapStructure]]&lt;br /&gt;
* [[User:Philosopher/Nasal introspection|Nasal Introspection]]&lt;br /&gt;
&lt;br /&gt;
Good ideas:&lt;br /&gt;
* Expose the catapult locations to the property tree, for JSBSim 'craft and Nasal tutorials.&lt;br /&gt;
* [http://flightgear.org/forums/viewtopic.php?f=18&amp;amp;t=19666 Changing behavior of SGPropertyNodes without tying] (something like {{issue|336}}).&lt;br /&gt;
* (In conjunction with Hooray) Have Nasal load itself: besides for one file (either Nasal/globals.nas or something in [[$FG_ROOT]]), ''all'' Nasal should be loaded from Nasal.  (Including &amp;lt;tt&amp;gt;--prop:/nasal/module_name/script&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--prop:/nasal/module_name/file&amp;lt;/tt&amp;gt;.) See [http://flightgear.org/forums/viewtopic.php?f=30&amp;amp;t=21083] &amp;amp; [http://forum.flightgear.org/viewtopic.php?f=30&amp;amp;t=21083] {{Progressbar|50}}.&lt;br /&gt;
&lt;br /&gt;
Nasal thoughts area:&lt;br /&gt;
* I would like to include small improvements that enhance my quality of life in SimGear: string slicing, hash iteration using foreach/forindex, save/restore aka stash? (latter to be discussed)&lt;br /&gt;
* Hooray and I talk about more extension functions to allow looking into internals; I need to review all of these, gather them up, add to them, etc., and hope they can be included somewhere (Hooray was saying maybe just the standalone Nasal in SimGear, not FlightGear's runtime).&lt;br /&gt;
** Sub-idea: if we only include the extensions in standalone and we have optimizer/post-compiler scripts ready, then make a script to be run with standalone that optimizes any or all Nasal files and outputs an optimized version (*.nas.optimized) or even just the bytecode (*.nas.opcode, textual file ofc) and have that be the preferred loading method (if the text is older than the optimized version).&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Nasal_Namespace_Browser_Prototype.png&amp;diff=73297</id>
		<title>File:Nasal Namespace Browser Prototype.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Nasal_Namespace_Browser_Prototype.png&amp;diff=73297"/>
		<updated>2014-06-26T17:35:55Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: Philosopher uploaded a new version of &amp;amp;quot;File:Nasal Namespace Browser Prototype.png&amp;amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Screen shot showing the new [[Nasal Browser|Nasal Namespace Browser]] that is currently being worked on by Philosopher.}}&lt;br /&gt;
|date=2014-06-26 10:31:21&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:Hooray|Hooray]]&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{self|cc-by-sa-3.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Canvas development projects]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Nasal_Navigation&amp;diff=73259</id>
		<title>Template:Nasal Navigation</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Nasal_Navigation&amp;diff=73259"/>
		<updated>2014-06-26T02:13:10Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
Navigation box for core [[Nasal]] articles.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
Put this at the top of the article:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{Nasal Navigation}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Navigation templates]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&amp;lt;includeonly&amp;gt;[[Category:Nasal]]&amp;lt;/includeonly&amp;gt;{{forum|30|Nasal Scripting}}&lt;br /&gt;
{{sidebar&lt;br /&gt;
| topimage = [[File:Nasallogo3.png]]&lt;br /&gt;
| name	= Nasal Navigation&lt;br /&gt;
| title = [[Nasal|Nasal scripting]]&lt;br /&gt;
| contentstyle= text-align: left;&lt;br /&gt;
&lt;br /&gt;
| content1 = &lt;br /&gt;
* [[What is Nasal]]?&lt;br /&gt;
* [[Nasal success stories|Success stories]]&lt;br /&gt;
* [[Nasal FAQ]]&lt;br /&gt;
* [[Nasal features|Features]]&lt;br /&gt;
* [[Nasal Snippets]]&lt;br /&gt;
* [[Nasal Style Guide]]&lt;br /&gt;
* [[Howto:Syntax highlighting for Nasal]]&lt;br /&gt;
&lt;br /&gt;
| heading2 = Tools and utilities&lt;br /&gt;
| content2 =&lt;br /&gt;
* [[Nasal Console|The Nasal Console]]&lt;br /&gt;
* [[Interactive Nasal Console|The Nasal REPL Console]] (3.2+)&lt;br /&gt;
* [[Nasal Browser|The Nasal Browser]] (3.3+)&lt;br /&gt;
&lt;br /&gt;
| heading3 = Getting started&lt;br /&gt;
| content3 =&lt;br /&gt;
* [[Nasal for C++ programmers]]&lt;br /&gt;
* [[Creating new Nasal scripts]]&lt;br /&gt;
* [[Nasal Hello World]]&lt;br /&gt;
* [[Howto:Create a new Nasal module]]&lt;br /&gt;
* [[Using Nasal functions]]&lt;br /&gt;
* [[Nasal Variables]]&lt;br /&gt;
* [[Nasal Namespaces]]&lt;br /&gt;
* [[Howto:Understand Namespaces and Methods|Namespace and Methods]]&lt;br /&gt;
* [[Nasal Namespaces in-depth]]&lt;br /&gt;
* [[Nasal Conditionals]]&lt;br /&gt;
* [[Nasal Loops]]&lt;br /&gt;
* [[Nasal Operators]]&lt;br /&gt;
* [[Howto:Use vectors and foreach loops to write shorter code]]&lt;br /&gt;
* [[Howto:Start using vectors and hashes in Nasal]]&lt;br /&gt;
* [[Nasal library functions]]&lt;br /&gt;
* [[Nasal Flightplan]]&lt;br /&gt;
* [[Object oriented programming in Nasal|OOP Introduction]]&lt;br /&gt;
* [[Object Oriented Programming with Nasal]]&lt;br /&gt;
* [[Nasal Callbacks Explained]]&lt;br /&gt;
* [[Exception handling with Nasal]]&lt;br /&gt;
* [[Using listeners and signals with Nasal]]&lt;br /&gt;
* [[List of Nasal extension functions]]&lt;br /&gt;
* [[List of Nasal modules in $FG_ROOT]]&lt;br /&gt;
* [[Developing and debugging Nasal code]]&lt;br /&gt;
* [[Nasal Flightplan]]&lt;br /&gt;
&lt;br /&gt;
| heading4 = Advanced Tutorials&lt;br /&gt;
| content4 =&lt;br /&gt;
* [[Caching Nasal function calls]]&lt;br /&gt;
* [[Nasal Unit Testing Framework]] (WIP)&lt;br /&gt;
* [[Nasal Meta-Programming]]&lt;br /&gt;
* [[A GPX flight logger in Nasal]]&lt;br /&gt;
* [[Multiplayer scripting in Nasal]]&lt;br /&gt;
* [[Howto:Making HTTP Requests from Nasal]]&lt;br /&gt;
* [[Howto:Transmit properties over MP]]&lt;br /&gt;
* [[Howto:Terrain sampling in Nasal]]&lt;br /&gt;
* [[Howto:Create a new system in Nasal]]&lt;br /&gt;
* [[Howto:Load a Nasal file at runtime]]&lt;br /&gt;
* [[Howto:Control the route manager in Nasal]]&lt;br /&gt;
* [[Howto:Get a number of elevation offsets for a number of objects]]&lt;br /&gt;
* [[Howto:Nasal in scenery object XML files]]&lt;br /&gt;
* [[Howto:Create animation XML files from Nasal]]&lt;br /&gt;
* [[Howto:Port I/O from Nasal]]&lt;br /&gt;
* [[Howto:Continuation-passing style programming in Nasal]]&lt;br /&gt;
* [[Howto:Start worker threads using listeners in Nasal]]&lt;br /&gt;
* [[Howto:Developing a DSL interpreter in Nasal]]&lt;br /&gt;
* [[Howto:Nasal Metaprogramming]]&lt;br /&gt;
* [[Nasal/JavaScript Subset]]&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Nasal Internals}}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Browser&amp;diff=73251</id>
		<title>Nasal Browser</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Browser&amp;diff=73251"/>
		<updated>2014-06-25T22:00:36Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: Created page with &amp;quot;{{Nasal Navigation}} {{WIP}} The '''Nasal '''('''Namespace''')''' Browser''' is a new dialog (3.3+) that allows the user to peek at the internal state of Nasal (starting from...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Navigation}}&lt;br /&gt;
{{WIP}}&lt;br /&gt;
The '''Nasal '''('''Namespace''')''' Browser''' is a new dialog (3.3+) that allows the user to peek at the internal state of Nasal (starting from the global namespace). It displays a alphabetical list of keys mapped to values using the [[Canvas]] framework. Hashes and vectors are shown as their size and can be entered into via clicking on them; scalars' complete values are shown while ghosts and other types and represented in brackets.&lt;br /&gt;
&lt;br /&gt;
{{Note|Per-update performance of the dialog (i.e. how fast it runs) is determined by how big the namespace is. On the developer's computer, it takes about 20–30ms to update the global namespace, much less for much smaller namespaces. The dialog is automatically updated about every 0.6 seconds.}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
Each entry is color-coded by type and scrollable via the Canvas scroll widget. In a hash, each key is shown as either a string, a number, or a symbol, depending on what it really is (i.e. a scalar may be numeric but still a string; also, interned symbols are special cases of strings). Strings are shown in single quotes, symbols and numbers are shown without quotes. For strings, the brightness of the color is optionally reduced.&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Interactive_Nasal_Console&amp;diff=73250</id>
		<title>Interactive Nasal Console</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Interactive_Nasal_Console&amp;diff=73250"/>
		<updated>2014-06-25T21:44:50Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Updates */ 06/2014&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Non-stable|version=3.2|progress=70}}&lt;br /&gt;
&lt;br /&gt;
{{infobox subsystem&lt;br /&gt;
|image =Interactive-Nasal-Console-REPL.png&lt;br /&gt;
|name =Nasal Console REPL&lt;br /&gt;
|started= 03/2014 (Available since FlightGear 3.1)&lt;br /&gt;
|description = Fully-interactive Nasal console REPL&lt;br /&gt;
|status = Under active development as of 03/2014&lt;br /&gt;
|maintainers  = Philosopher&lt;br /&gt;
|developers = [[User:Philosopher]] (since 03/2014),&lt;br /&gt;
|folders = $FG_ROOT/Nasal/console&lt;br /&gt;
|topic-fgdata= https://gitorious.org/fg/philosophers-fgdata/source/nasal-console:Nasal/console&lt;br /&gt;
|subforum= http://forum.flightgear.org/viewforum.php?f=71&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
Philosopher has created a very cool [[Canvas]]-based, fully-interactive, Nasal Console with a real [http://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop REPL interpreter (Read-eval-print loop)]. See his gitorious clone (branch &amp;quot;nasal-console&amp;quot;) for the code: [https://gitorious.org/fg/philosophers-fgdata/source/nasal-console:Nasal/console] - it's currently one file (which can even be copied into the existing [[Nasal Console]]) with a menubar entry (under &amp;quot;Debug&amp;quot;) for easy access. You can also uncomment the [https://gitorious.org/fg/philosophers-fgdata/source/022bef27f05d4837d720f63c6507b47466ff2a59:Nasal/console/repl.nas#L436 last line] of the file to open it immediately. The dialog accepts user input in lines, and if it detects the user has completed a snippet, it executes the last code it's seen and prints a result of the expression on the same area. The most common way to continue input onto another line is to have an unclothed pair of braces/brackets/parentheses, but this REPL is unique in allowing unfinished expressions: blocks (e.g. just plain &amp;quot;if&amp;quot; on one line -- no condition, no body -- or &amp;quot;foreach (var e; list)&amp;quot; -- no body of the loop) and binary/prefix operators (e.g. &amp;quot;1 &amp;gt;&amp;quot;, since that doesn't have a right side of the &amp;quot;&amp;gt;&amp;quot;). This however needs some work and tweaking, so it's always a WIP. The other big issue is the text styling -- the latest optimization leads to overlapping if a line of input/output is more than one line when wrapped. The output of print()/printlog()/etc. still goes to the startup OS terminal instead of the dialog. However, it still is useful for experimenting quickly -- ''quam celerrime revera''.&lt;br /&gt;
&lt;br /&gt;
== Updates ==&lt;br /&gt;
; 04/2014&lt;br /&gt;
* Used scrollbar widget.&lt;br /&gt;
* Added compatibility with resize flag on window.&lt;br /&gt;
; 06/2014&lt;br /&gt;
* Compatible with new Canvas layout engine.&lt;br /&gt;
* Fixed bug on multi-line input, e.g. when pasting text with newlines or pressing shift+enter: now ''all'' lines are parsed, not just the last line.&lt;br /&gt;
&lt;br /&gt;
== Gallery ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed widths=230px heights=230px&amp;gt;&lt;br /&gt;
Interactive-Nasal-Console-REPL.png|Philosopher's interactive Nasal console REPL.&lt;br /&gt;
Interactive-Nasal-Console-REPL-Transparent-KSFO.png|Now at KSFO with transparency enabled (no title bar/styling).&lt;br /&gt;
Interactive Nasal Console REPL Random Theming.png|Don't look, it's bad color choices! This shows how colors can be changed while running.&lt;br /&gt;
Interactive Nasal Console REPL White Example.png|Showing a simple example of functional closures, with white styling.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73213</id>
		<title>Canvas MessageBox</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73213"/>
		<updated>2014-06-24T20:37:29Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Examples */ canvas.MessageBox.info -&amp;gt; canvas.MessageBox.information, looks good!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Non-stable|version=3.2|progress=100}}&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
Message boxes provide a simple way to report information and warnings or ask questions. In FlightGear 3.1+ using &amp;lt;code&amp;gt;canvas.MessageBox&amp;lt;/code&amp;gt; with the Nasal scripting language, allows showing standard message boxes to the user.&lt;br /&gt;
&lt;br /&gt;
== Predefined Severity Levels/Icons ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Icon !! Icon Name !! Standard MessageBox !! Description&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | [[File:Dialog-question.png|link=]] || &amp;lt;code&amp;gt;&amp;quot;dialog-question&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;canvas.MessageBox.question(&lt;br /&gt;
  &amp;lt;title&amp;gt;,&lt;br /&gt;
  &amp;lt;text&amp;gt;,&lt;br /&gt;
  cb = nil,&lt;br /&gt;
  buttons = canvas.MessageBox.Yes&lt;br /&gt;
          | canvas.MessageBox.No&lt;br /&gt;
);&amp;lt;/syntaxhighlight&amp;gt; || Ask the user a (yes/no) question.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | [[File:Dialog-info.png|link=]] || &amp;lt;code&amp;gt;&amp;quot;dialog-info&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;canvas.MessageBox.information(&lt;br /&gt;
  &amp;lt;title&amp;gt;,&lt;br /&gt;
  &amp;lt;text&amp;gt;,&lt;br /&gt;
  cb = nil,&lt;br /&gt;
  buttons = canvas.MessageBox.Ok&lt;br /&gt;
);&amp;lt;/syntaxhighlight&amp;gt; || Show the user some information, with only the possiblity to close the dialog.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | [[File:Dialog-warning.png|link=]] || &amp;lt;code&amp;gt;&amp;quot;dialog-warning&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;canvas.MessageBox.warning(&lt;br /&gt;
  &amp;lt;title&amp;gt;,&lt;br /&gt;
  &amp;lt;text&amp;gt;,&lt;br /&gt;
  cb = nil,&lt;br /&gt;
  buttons = canvas.MessageBox.Ok&lt;br /&gt;
);&amp;lt;/syntaxhighlight&amp;gt; || Show the user a non critical warning, with only the possiblity to close the dialog.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | [[File:Dialog-error.png|link=]] || &amp;lt;code&amp;gt;&amp;quot;dialog-error&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;canvas.MessageBox.critical(&lt;br /&gt;
  &amp;lt;title&amp;gt;,&lt;br /&gt;
  &amp;lt;text&amp;gt;,&lt;br /&gt;
  cb = nil,&lt;br /&gt;
  buttons = canvas.MessageBox.Ok&lt;br /&gt;
);&amp;lt;/syntaxhighlight&amp;gt; || Notify the user of a critical error or failure, with only the possiblity to close the dialog.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| [[File:Canvas-MessageBox-demo information.png|link=]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
canvas.MessageBox.information(&amp;quot;Success&amp;quot;, &amp;quot;The operation has successfully completed.&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| [[File:Canvas-MessageBox-demo question.png|link=]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
canvas.MessageBox.question(&lt;br /&gt;
  &amp;quot;Do you want it?&amp;quot;,&lt;br /&gt;
  &amp;quot;The question is: Do you want to get a real question?.&amp;quot;,&lt;br /&gt;
  func(sel)&lt;br /&gt;
  {&lt;br /&gt;
    if( sel == canvas.MessageBox.Yes )&lt;br /&gt;
      print(&amp;quot;I only know that the answer is 42.&amp;quot;);&lt;br /&gt;
    else&lt;br /&gt;
      print(&amp;quot;Ok, I will not give you a real question.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|- style=&amp;quot;vertical-align:top;&amp;quot;&lt;br /&gt;
| [[File:Canvas-MessageBox-demo warning dont-show-again.png|link=]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
canvas.MessageBox.warning(&lt;br /&gt;
  &amp;quot;Warning...&amp;quot;,&lt;br /&gt;
  &amp;quot;Have you read this warning? If you want it will not be shown again.&amp;quot;,&lt;br /&gt;
  func(sel)&lt;br /&gt;
  {&lt;br /&gt;
    if( sel != canvas.MessageBox.Ok )&lt;br /&gt;
      return;&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;You have been warned. Let the games begin...&amp;quot;);&lt;br /&gt;
  },&lt;br /&gt;
    canvas.MessageBox.Ok&lt;br /&gt;
  | canvas.MessageBox.Cancel&lt;br /&gt;
  | canvas.MessageBox.DontShowAgain&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Entitlement&amp;diff=72561</id>
		<title>Entitlement</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Entitlement&amp;diff=72561"/>
		<updated>2014-06-10T12:55:59Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* The FSX threat */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
'''Entitlement''' is the errorneous perception by a subgroup of users that the Flightgear development team 'owes' them certain things for no other reason than that they are using Flightgear. This basic misunderstanding makes communication between developers and users prone to fail.&lt;br /&gt;
&lt;br /&gt;
The reality is that Flightgear is developed by a team of volunteers who work for the project in their spare time and that users get the finished product for free (that 'free' includes costs for infrastructure  like download bandwidth and file hosting), so it is difficult to see in what sense developers would owe  users in addition to the service already rendered. If anything, it would be the other way round.&lt;br /&gt;
&lt;br /&gt;
In practice, entitlement comes in various forms, often in statements like 'users should get more of a say where the project goes', requests to make binding votes and polls or unrealistic expectations in problem reporting situations.&lt;br /&gt;
&lt;br /&gt;
== Votes and polls ==&lt;br /&gt;
&lt;br /&gt;
With some regularity, users express their ideas on where they think the project should be going and feel that the project should be more democratic and take their vote into account and are disappointed that this leads nowhere. However, Flightgear is in essence a meritocracy in which the influence on where the project goes roughly scales with the merits a developer already has.&lt;br /&gt;
&lt;br /&gt;
There are at least two basic reasons why the project does not let vote users into which direction future development should be going. First, making such decision requires insight into what the issues and alternatives are, and what they would imply. Some seemingly small changes may in fact require large changes in the basic architecture of the software. Inofficial opinion polls &amp;lt;i&amp;gt;backed up with arguments&amp;lt;/i&amp;gt; are sometimes held on the developer's mailing list, but the aim is more to distill the arguments than the individual opinions. Basically, project decisions should be made by the people who have the skills and experience to make them. This has real-life analogies - in case of an emergency, an airliner crew does not give the passengers a vote what should be done, the cockpit crew decides that, as they have the skill and experience necessary, the passengers do not.&lt;br /&gt;
&lt;br /&gt;
The second reason is tied to the volunteer nature of the project. Volunteers can not be compelled to work on something they do not like. Even if a user vote would make sense conceptually, if the people who have the ability to code a certain feature that has been voted in do not want to do it, it all stops there. It is completely unreasonable to ask people who devote their free time to coding for Flightgear to regularly do things someone else tells them to - especially if that someone else has not done any service for the project.&lt;br /&gt;
&lt;br /&gt;
== The FSX threat ==&lt;br /&gt;
&lt;br /&gt;
Sometimes users threaten to leave Flightgear for another simulation software if their idea is not taken into account. From a developer's perspective, this is an empty threat, as the number of people who just use the software is irrelevant for the continuation of the project. This is very different from commercial projects where the number of users largely is the number of customers who finance the project, but in the Flightgear case, things actually work the other way round in that a larger userbase creates a larger drain on the infrastructure, making it more difficult to offer it for free.&lt;br /&gt;
&lt;br /&gt;
Thus, approaching Flightgear with the attitude of a paying customer who is crucial for the project leads nowhere - Flightgear users are not paying customers, and users leaving for FSX will not have any impact on the project.&lt;br /&gt;
&lt;br /&gt;
What will have an impact is contributors leaving the project - but contributors have rendered services to the project already, and so they may receive some attention from other contributors in return.&lt;br /&gt;
&lt;br /&gt;
== The silent majority ==&lt;br /&gt;
&lt;br /&gt;
Several users have in the past questioned whether the feedback provided via the forum and other channels is really representative and argued that they represent the position of the (much larger) silent majority of users who do not provide feedback anywhere.&lt;br /&gt;
&lt;br /&gt;
It is certainly true that the sample of users reporting back is skewed - but the skew goes the opposite direction, since a main driving force for users appearing in the forum is that they experience problems - in all likelihood, the silent majority is therefore silent because these users don't see problems.&lt;br /&gt;
&lt;br /&gt;
However, as argued above, the (non)-existence of a large number of users having one opinion or the other who do not want to get in contact with the project is irrelevant for the way the project works. Unlike paying customers, the sheer number makes no difference anywhere. So even if the silent majority could be demonstrated to be of a certain opinion, the argument would not be stronger.&lt;br /&gt;
&lt;br /&gt;
== Bug reporting ==&lt;br /&gt;
&lt;br /&gt;
The Flightgear project does not have the resources to pay for a user support department, so again all bug reports are handled by volunteers. Most bug reports are answered with requests for more information. The reason is that it is almost impossible to find the cause of a bug if it can't be reproduced. Some users react rather violently to this, apparently out of a notion that they have done their part by reporting the bug, so now it's the developers' duty to fix it, not to ask more questions.&lt;br /&gt;
&lt;br /&gt;
Needless to say, this is an unproductive attitude. Nobody likes to trace bugs, people volunteer nevertheless because they realize there is need. However, to expect that a volunteer will put up with rudeness and go out of his way to investigate many possible causes of a problem he can't see because a user doesn't provide enough information is unrealistic. Users are not paying customers, and the people trying to help with problems are not a paid support department.&lt;br /&gt;
&lt;br /&gt;
== Support for outdated hardware ==&lt;br /&gt;
&lt;br /&gt;
On occasion, users have accused to project of discriminating against them, as they can't run the recent versions of the program on their hardware. Note first that the premise is likely not true - Flightgear is known to run fine on very old hardware using a [[Howto:Debugging FlightGear Crashes|minimum startup profile]] and legacy support is strong driving force for decisions made in the devel community. &lt;br /&gt;
&lt;br /&gt;
However, leaving that aside and assuming that there are systems on which a recent Flightgear version no longer runs - in what way would that be discrimination? Especially since older versions are still available? Why would the project have an obligation to support every bit of hardware in existence? With the same logic that 'free' equals 'everyone must be able to use it' - should the project provide computers for everyone who wants to use the simulator but does not own a computer at all?&lt;br /&gt;
&lt;br /&gt;
Users who invest in high end graphics cards have at least just as much reason to expect that new version make use of their computers' performance. Many novel features are implemented optionally can can be switched off, the project tries hard to be backward compatible (and is probably much more so than any commercial software) but fundamentally there is no right of a user that his hardware is supported, and accusations of discrimination against users with low end hardware are just baseless.&lt;br /&gt;
&lt;br /&gt;
Finally, there are features that cannot be realistically run on very outdated hardware, this includes deferred rendering schemes like Rembrandt, many shaders/effects,  but also osgEarth support - more often than not, these feature actually '''require''' fairly recent hardware. And in the case of osgEarth, or many other OSG-based features, the hardware requirements (such as e.g. shader/multi-threading support and lots of RAM/VRAM) are actually beyond the control of the FlightGear project - FlightGear merely uses existing software.&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File_talk:Wikipedia_icon_15px.png&amp;diff=72460</id>
		<title>File talk:Wikipedia icon 15px.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File_talk:Wikipedia_icon_15px.png&amp;diff=72460"/>
		<updated>2014-06-07T12:26:31Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: forgot the header!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Linux Libertine crossed W for Wikipedia ==&lt;br /&gt;
&lt;br /&gt;
Hi Johan,&lt;br /&gt;
&lt;br /&gt;
Thanks for the icon, it really helps with visibility of the Wikipedia links. I'm also glad to see that I'm not the only one who uses Linux Libertine (it's the only font I like!). However, if you look at their main page, a few articles down they have a &amp;quot;New Wikipedia-Logo using LinuxLibertine&amp;quot;, where they explain the W vs crossed-W. It is the latter I would suggest you use, as it's quite distinctive. I think you can find it in the private use area, last time I checked. [[User:Philosopher|—Philosopher]] ([[User talk:Philosopher|talk]]) 12:22, 7 June 2014 (UTC)&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File_talk:Wikipedia_icon_15px.png&amp;diff=72459</id>
		<title>File talk:Wikipedia icon 15px.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File_talk:Wikipedia_icon_15px.png&amp;diff=72459"/>
		<updated>2014-06-07T12:22:52Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: Linux Libertine crossed W for Wikipedia&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi Johan,&lt;br /&gt;
&lt;br /&gt;
Thanks for the icon, it really helps with visibility of the Wikipedia links. I'm also glad to see that I'm not the only one who uses Linux Libertine (it's the only font I like!). However, if you look at their main page, a few articles down they have a &amp;quot;New Wikipedia-Logo using LinuxLibertine&amp;quot;, where they explain the W vs crossed-W. It is the latter I would suggest you use, as it's quite distinctive. I think you can find it in the private use area, last time I checked. [[User:Philosopher|—Philosopher]] ([[User talk:Philosopher|talk]]) 12:22, 7 June 2014 (UTC)&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_wiki:Instant-Refs&amp;diff=72098</id>
		<title>FlightGear wiki:Instant-Refs</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_wiki:Instant-Refs&amp;diff=72098"/>
		<updated>2014-05-31T22:06:07Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: clear selection only if user doesn't hit &amp;quot;cancel&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* A simple userscript extension implemented in JavaScript&lt;br /&gt;
* Supported by FireFox, Chrome, Chromium, probably Opera and others&lt;br /&gt;
* in case of doubt, just install the GreaseMonkey/[https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en TamperMonkey] extension&lt;br /&gt;
* install the script&lt;br /&gt;
* go to some sourceforge.net mail archive URL, for example: http://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/5389094A.3080601%40gmail.com/#msg32400727&lt;br /&gt;
: or to any forum message&lt;br /&gt;
* copy/mark some relevant portion of text&lt;br /&gt;
* and directly get a full cquote paragraph that you can add to the wiki here&lt;br /&gt;
* [http://wiki.flightgear.org/User_talk:Hooray stop whining that proper cquotes are too painful] :-)&lt;br /&gt;
&lt;br /&gt;
{{Note|For testing purposes, the alert showing the cleaned up fields are still enabled. You can comment it out in extractInfo().}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// ==UserScript==&lt;br /&gt;
// @name       auto cquotes for sourceforge ml and forum&lt;br /&gt;
// @namespace  http://wiki.flightgear.org/&lt;br /&gt;
// @version    0.5&lt;br /&gt;
// @description automatically create proper wikimedia cquotes for sourceforge ml and forum text selections&lt;br /&gt;
// @match      http://sourceforge.net/p/flightgear/mailman/* &lt;br /&gt;
// @match	   http://forum.flightgear.org/*&lt;br /&gt;
// @copyright  2013+, FlightGear.org&lt;br /&gt;
// ==/UserScript==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* for each domain, fields: author, title, date, url.&lt;br /&gt;
 * for each field:&lt;br /&gt;
        xpath - relative to the text body element&lt;br /&gt;
        regex - will extract the first capture group (i.e. '(xxx)')&lt;br /&gt;
        prepend - a string to be prepended (useful for urls)&lt;br /&gt;
*/&lt;br /&gt;
var CONFIG = {&lt;br /&gt;
    &amp;quot;sourceforge.net&amp;quot;: { &lt;br /&gt;
        author: {&lt;br /&gt;
            xpath: &amp;quot;../../../tr/td/div/small/text()&amp;quot;,&lt;br /&gt;
            regex: &amp;quot;/^From: (.*) &amp;lt;.*@.*&amp;gt;/&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        title: {&lt;br /&gt;
            xpath: &amp;quot;../../../tr/td/div/div/b/a/text()&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        date: {&lt;br /&gt;
            xpath: &amp;quot;../../../tr/td/div/small/text()&amp;quot;,&lt;br /&gt;
            regex: &amp;quot;/ - (.*-.*-.*) /&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        url: {&lt;br /&gt;
            xpath: &amp;quot;../../../tr/td/div/div/b/a/@href&amp;quot;,&lt;br /&gt;
            prepend: &amp;quot;http://sourceforge.net&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;forum.flightgear.org&amp;quot;: {&lt;br /&gt;
        author: {&lt;br /&gt;
            xpath: &amp;quot;../p/strong/a/text()&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        title: {&lt;br /&gt;
            xpath: &amp;quot;../h3/a/text()&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        date: {&lt;br /&gt;
            xpath: &amp;quot;../p/text()[2]&amp;quot;,&lt;br /&gt;
            regex: &amp;quot;/ » (.*),/&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        url: {&lt;br /&gt;
            xpath: &amp;quot;../p/a/@href&amp;quot;,&lt;br /&gt;
            regex: &amp;quot;/\.(.*)/&amp;quot;,&lt;br /&gt;
            prepend: &amp;quot;http://forum.flightgear.org&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
function getPathTo(element) {&lt;br /&gt;
    if (element.id!=='')&lt;br /&gt;
        return 'id(&amp;quot;'+element.id+'&amp;quot;)';&lt;br /&gt;
    if (element===document.body)&lt;br /&gt;
        return element.tagName;&lt;br /&gt;
    &lt;br /&gt;
    var ix= 0;&lt;br /&gt;
    var siblings= element.parentNode.childNodes;&lt;br /&gt;
    for (var i= 0; i&amp;lt;siblings.length; i++) {&lt;br /&gt;
        var sibling= siblings[i];&lt;br /&gt;
        if (sibling===element)&lt;br /&gt;
            return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';&lt;br /&gt;
        if (sibling.nodeType===1 &amp;amp;&amp;amp; sibling.tagName===element.tagName)&lt;br /&gt;
            ix++;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function nowiki(text) {&lt;br /&gt;
    return &amp;quot;&amp;lt;nowiki&amp;gt;&amp;quot; + text + &amp;quot;&amp;lt;/nowiki&amp;gt;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function extractInfo(parentPath, profile) {&lt;br /&gt;
    var info = {};&lt;br /&gt;
    for (field in profile) {&lt;br /&gt;
        var fieldInfo = &amp;quot;&amp;quot;;&lt;br /&gt;
        if (profile[field].xpath) {&lt;br /&gt;
            var fullPath =  parentPath + &amp;quot;/&amp;quot; + profile[field].xpath;&lt;br /&gt;
            fieldInfo = document.evaluate(fullPath, document, null, XPathResult.STRING_TYPE, null ).stringValue;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (profile[field].regex) {&lt;br /&gt;
            var regex = eval(profile[field].regex); // to cleanup info&lt;br /&gt;
            fieldInfo = fieldInfo.match(regex)[1];&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        if (profile[field].prepend) {&lt;br /&gt;
            fieldInfo = &amp;quot;http://&amp;quot; + window.location.hostname + fieldInfo;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        alert(field+&amp;quot; = &amp;quot;+fieldInfo);&lt;br /&gt;
        info[field] = fieldInfo;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return info;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// FIXME: remove extra \CR \LF (?)&lt;br /&gt;
function CreateCquote(text, parent) {&lt;br /&gt;
    var info = {};&lt;br /&gt;
    &lt;br /&gt;
    if(parent) {&lt;br /&gt;
        var profile = CONFIG[window.location.hostname];&lt;br /&gt;
        var parentPath = getPathTo(parent);&lt;br /&gt;
        &lt;br /&gt;
        info = extractInfo(parentPath, profile);&lt;br /&gt;
    } else {&lt;br /&gt;
        // fallback. XXX: not tested&lt;br /&gt;
        info.url = document.URL;&lt;br /&gt;
        info.title = &amp;quot;from &amp;quot; + window.location.hostname;&lt;br /&gt;
        info.author = &amp;quot;&amp;quot;;&lt;br /&gt;
        info.date = &amp;quot;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    //TODO: add template string to profile&lt;br /&gt;
    var template = &amp;quot;{{cquote&amp;quot; + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;  |&amp;quot; + nowiki(text) + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;  |{{cite web |url=&amp;quot; + info.url + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;     |title=&amp;quot; + nowiki(info.title) + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;     |author=&amp;quot; + nowiki(info.author) + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;     |date=&amp;quot; + nowiki(info.date) + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;   }}&amp;quot; + &amp;quot;\n&amp;quot; +&lt;br /&gt;
        &amp;quot;}}&amp;quot;;&lt;br /&gt;
    return template;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function GetSelectedText () {    &lt;br /&gt;
    var text = &amp;quot;&amp;quot;;&lt;br /&gt;
    var parent = null;&lt;br /&gt;
    &lt;br /&gt;
    if (document.getSelection) {&lt;br /&gt;
        var sel = document.getSelection (); &lt;br /&gt;
        parent = sel.anchorNode.parentNode;// anchorNode is the textnode, parentNode is the actual parent, i.e. html element&lt;br /&gt;
        text = sel;&lt;br /&gt;
    } else if (document.selection) { // for IE &amp;lt;= v8&lt;br /&gt;
        var textRange = document.selection.createRange ();&lt;br /&gt;
        parent = textRange.parentElement(); // XXX: not tested!&lt;br /&gt;
        text = textRange.text;&lt;br /&gt;
    }&lt;br /&gt;
        &lt;br /&gt;
    // check if we got text&lt;br /&gt;
    if ( text != &amp;quot;&amp;quot; ) {&lt;br /&gt;
        var cquote = CreateCquote(text, parent);&lt;br /&gt;
        if (window.prompt (&amp;quot;Copy to clipboard: Ctrl+C, Enter&amp;quot;, cquote) != null)&lt;br /&gt;
            window.getSelection().removeAllRanges(); // deselect all text&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function register() {&lt;br /&gt;
    // check if we have a matching domain in the CONFIG hash&lt;br /&gt;
    if (CONFIG.hasOwnProperty(window.location.hostname) ) {        &lt;br /&gt;
        // if yes, register a callback to handle mouse events&lt;br /&gt;
        document.onmouseup = GetSelectedText;&lt;br /&gt;
    }        &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
window.addEventListener('load', register );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Wiki maintenance]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_development&amp;diff=72066</id>
		<title>Canvas development</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_development&amp;diff=72066"/>
		<updated>2014-05-30T21:09:11Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Placement/Element for Streaming: Computer Vision */ little bug in citation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Note|This article is primarily of interest to people familiar with [[Building FlightGear]] from source, and wanting to extend the [[Canvas]] system in SimGear. Readers are assumed to be familiar with [[Programming_Resources|C++ and {{abbr|OSG|OpenSceneGraph}}&lt;br /&gt;
]], the [[Property Tree]] and basic FlightGear {{abbr|API|Application Programming Interface}}s like [http://docs.freeflightsim.org/simgear/classSGPropertyNode.html SGPropertyNode], [[Howto:Use Property Tree Objects|Property Objects]], [[Howto:Create new subsystems|SGSubsystem and SGPropertyChangeListener]]. The Canvas code itself makes extensive use of the {{abbr|STL|Standard Template Library}} and Boost. The latest Canvas/Doxygen docs can be found [http://docs.freeflightsim.org/simgear/classsimgear_1_1canvas_1_1Canvas.html here]. &lt;br /&gt;
&lt;br /&gt;
There are two main ways to extend FlightGear's Canvas system:&lt;br /&gt;
* new/extended elements (elements determine '''what/how''' something is to be rendered (text,image,line,circle), i.e. new rendering primitives that cannot be easily/efficiently expressed using existing means, e.g. a moving map, camera views or ESRI support)&lt;br /&gt;
* new/extended placements (placements determine '''where''' a canvas is to be placed, e.g. cockpit, scenery, GUI dialog or osgviewer window)&lt;br /&gt;
&lt;br /&gt;
Whenever all existing elements (group, map, text, image, path) should benefit from an addition, such as for example adding effects/shader support, it makes sense to extend the underlying base class itself, i.e. [http://docs.freeflightsim.org/simgear/classsimgear_1_1canvas_1_1Element.html Canvas::Element].&lt;br /&gt;
In addition, the '''map''' element (a subclass of group) can be extended to support additional map projections.&lt;br /&gt;
People just wanting to add a new layer to an existing dialog or instrument, will probably want to refer to [[Canvas MapStructure]] instead.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The canvas system is a property-driven FlightGear subsystem that allows creating, rendering and updating dynamic OpenGL textures at runtime by setting properties in the FlightGear Property Tree. &lt;br /&gt;
&lt;br /&gt;
The property tree is the sole interfacing mechanism in use by the Canvas system. A so called listener-based subsystem (via SGPropertyChangeListener) will watch the canvas sub tree in the main property tree for &amp;quot;events&amp;quot; (i.e. properties being set, written to/modified), and then update each associated texture accordingly, e.g. by adding a requested vector or raster image, drawing a map, placing symbols or placing text labels with custom fonts. &lt;br /&gt;
&lt;br /&gt;
Elements can be nested and added to groups which support showing/hiding and clipping of segments. Vector drawing is handled via ShivaVG.&lt;br /&gt;
&lt;br /&gt;
All property updates result in native C++/{{abbr|OSG|OpenSceneGraph}} data structures being updated (typically using {{abbr|OSG|OpenSceneGraph}}&lt;br /&gt;
/STL/Boost containers), so that the property tree and scripting are solely used to send update events, which ensures that Canvas-based systems are typically fast enough, often delivering frame rates beyond ~40-60 {{abbr|fps|frames per second}}.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Animations are currently not directly supported, instead these can be implemented by using separate canvas groups and hiding/showing them as needed, or simply by changing the size/color/styling attributes of a canvas group using Nasal timers. Another option to update a canvas without relying on Nasal timers (i.e. due to {{abbr|GC|Nasal Garbage Collection}} considerations) is using so called &amp;quot;Property Rules&amp;quot;, which are currently not yet exposed to Nasal, but which can be used for any needs where scripting overhead should be minimal.&lt;br /&gt;
&lt;br /&gt;
The Canvas fully supports recursion, by allowing other canvases (and sub-regions of them via texture-mapping) to be referenced and used as raster images, so that multiple canvases can be chained together, but also through the notion of &amp;quot;groups&amp;quot;, which are containers for other canvas elements, including child groups or elements referencing other canvases. &lt;br /&gt;
&lt;br /&gt;
This can be particularly useful for projects requiring multi-texturing and other multi-pass texturing stages. This mechanism is also one of the main building blocks used by the [[MapStructure]] charting framework to implement caching support via texture maps, without needing any changes on the C++ side.&lt;br /&gt;
&lt;br /&gt;
The canvas itself is developed with a focus on primarily being an enabling technology. In other words, the canvas is not about implementing individual features like a {{abbr|PFD|Primary Flight Display}}, {{abbr|ND|Navigational Display}}, EFIS, EICAS or other {{abbr|MFD|Multi-Function Display}} instruments like a moving map or a {{abbr|GUI|Graphical User Interface}} library. Rather, the Canvas system is all about coming up with a flexible and efficient system that allows end-users (aircraft developers and other base package contributors) to develop such features themselves in user space (i.e. the base package) via scripting - without having to be proficient C++ programmers, without having to rebuild FlightGear from source, and without having to be familiar with OpenSceneGraph, OpenGL or other technologies that typically involve a steep learning curve (i.e. STL/Boost).  &lt;br /&gt;
&lt;br /&gt;
This approach has several major advantages - in particular, it frees core developers from having to develop and maintain end-user features like a wxradar, groundradar or [[Navigational Display]]/{{abbr|PFD|Primary Flight Display}} by empowering content (base package) developers to handle the implementation of such features themselves. &lt;br /&gt;
&lt;br /&gt;
Thus, development of content is moved to user space (i.e. the base package). Recently, we've seen a shift in trend here, because more and more core developers focusing on end user requests, instead of implementing those feature requests, they implement the building blocks and infrastructure to delegate the implementation of these features to user space.&lt;br /&gt;
&lt;br /&gt;
Besides, core developers are generally overstretched, and there are not enough core developers to handle all core development related tasks:&lt;br /&gt;
&lt;br /&gt;
{{cquote|Unfortunately, most of the active FG developers are currently very overstretched in terms of the areas that they have ownership of, which is affecting how much can actually be done.  Fundamentally we need more core devs. &amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg39921.html|title=Atmospheric Light Scattering|author=Stuart Buchanan|date=Thu, 25 Apr 2013 07:28:28 -0700}}&amp;lt;/ref&amp;gt;|Stuart Buchanan}}&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only way to deal with this is to occasionally shift the core development focus from developing complex high level end users features (such as an {{abbr|ND|Navigational Display}}, TCAS or WXRADAR) that take years to develop, to just providing lower level {{abbr|API|Application Programming Interface}}&lt;br /&gt;
s (like a navdb {{abbr|API|Application Programming Interface}}  or a 2D drawing {{abbr|API|Application Programming Interface}} like [[Canvas]]) to enable base package developers to develop those really high level features themselves. &lt;br /&gt;
&lt;br /&gt;
This is the route that seemed to work out fairly well for the local weather system, which was prototyped and implemented by a single base package developer in scripting space, who just asked for certain scripting hooks to be provided at some point. &lt;br /&gt;
&lt;br /&gt;
For example, when Stuart, Torsten or Erik implemented LW-specific core extensions, these were about providing new hooks to be used by Thorsten. They didn't commit to implementing a weather system, they just enabled somebody else to continue his work. So this strategy is as much about delegation, as it is about organizing core development.&lt;br /&gt;
&lt;br /&gt;
Core developers cannot possibly implement all the ideas and feature requests that end users may have, but they can at least provide a toolbox for base package developers to implement such features. Now, without doubt, implementing a WXRADAR, TCAS, AGRADAR or even a full {{abbr|ND|Navigational Display}}&lt;br /&gt;
/{{abbr|MFD|Multi-Function Display}} is incredibly complex and time-consuming. &lt;br /&gt;
&lt;br /&gt;
Exposing a 2D drawing {{abbr|API|Application Programming Interface}} or a navdb {{abbr|API|Application Programming Interface}} to base package developers would have been much simpler and less time-consuming, at the cost of possibly not providing certain instruments/features directly - while still providing the building blocks for skilled base package contributors to implement such instruments eventually within the base package, rather than within the C++ source code where evolution and maintenance of such instruments is inherently limited by the availability of C++ developers.&lt;br /&gt;
&lt;br /&gt;
Given the progress we've seen in Canvas-related contributions boosted by having a 2D {{abbr|API|Application Programming Interface}}, this is a very worthwhile route for developing {{abbr|MFD|Multi-Function Display}}-style instruments or other end-users features without being limited by our shortage of core developers.&lt;br /&gt;
&lt;br /&gt;
Furthermore, the amount of specialized code in the main FlightGear code base is significantly reduced and increasingly unified: One major aspect of adopting the Canvas system was [[Unifying the 2D rendering backend via canvas]], so that more and more of the old/legacy code can be incrementally re-implemented and modernized through corresponding wrappers, which includes scripting-space frameworks for existing features like the [[Hud]] system, but also our existing PLIB/PUI-based GUI, and the old 2D panels code or the [[Map]] dialog. &lt;br /&gt;
&lt;br /&gt;
Many of these features are currently using legacy code that hasn't been maintained in years, causing issues when it comes to making use of certain OSG optimizations.&lt;br /&gt;
&lt;br /&gt;
In addition, widgets and instruments will no longer be hard-coded, but rather &amp;quot;compiled&amp;quot; into hardware-accelerated Canvas data structures while being initialized, which will be typically animated by using timers or listeners (via scripting or property rules). The fact that previously hard-coded widgets or instruments are now fully implemented in scripting space also means that deployment of updates no longer requires manual installations of binaries necessarily. &lt;br /&gt;
&lt;br /&gt;
This is analogous to how more and more software programs, such as browsers like Firefox/Chrome, are using an increasingly scripted approach towards implementing functionality, i.e. using JavaScript/XUL to move the implementation of certain features out of native code.&lt;br /&gt;
&lt;br /&gt;
Finally, an increasingly unified 2D rendering back-end also provides the opportunity to make porting/re-targeting FlightGear increasingly feasible, no matter if this is about mobile gaming platforms, mobile phones (e.g. Android) or embedded hardware like a Rasberry PI: Without a unified 2D rendering back-end, all other subsystems doing 2D rendering would need to be manually ported (hud, cockpit, instruments, GUI etc). &lt;br /&gt;
&lt;br /&gt;
A unified 2D rendering back-end using the Canvas system ensures instead that all Canvas-based features will remain functional, as long as the Canvas itself is able to run on the corresponding platform/hardware, because there's really just a single subsystem that handles '''all''' 2D rendering via different user-space wrappers, and that would need porting (e.g. to support OpenGL ES).&lt;br /&gt;
&lt;br /&gt;
Also, GUI dialogs and instruments can make use of other Canvas-based features, e.g. for showing a GUI dialog on an instrument, or instruments in dialogs.&lt;br /&gt;
&lt;br /&gt;
The property tree centric implementation approach of the Canvas also means that all Canvas-based frameworks could technically work in a standalone [[FGCanvas]]/[[FGPanel]] mode, but also in multi-instance (master/slave) setups such as those common for FSWeekend/LinuxTag. This is yet another novelty, because most existing hard-coded instruments cannot be easily modified to work in such multi-instance setup scenarios. The Canvas system however -being based on the property tree- could retrieve property updates from external instances, e.g. via telnet/UDP or [[HLA]] without requiring major re-architecting.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
// http://yuml.me/&lt;br /&gt;
// [note: Canvas Elements{bg:cornsilk}]&lt;br /&gt;
[Property Tree]-&amp;gt;[SGPropertyChangeListener]&lt;br /&gt;
[SGPropertyChangeListener]-&amp;gt;[PropertyBasedElement]&lt;br /&gt;
[PropertyBasedElement]-&amp;gt;[Canvas]&lt;br /&gt;
[PropertyBasedElement]-&amp;gt;[Element]&lt;br /&gt;
[PropertyBasedElement]-[note:Handles destruction of property elements&lt;br /&gt;
[Element]-&amp;gt;[Group]&lt;br /&gt;
[Group]-&amp;gt;[Map]&lt;br /&gt;
[Element]-&amp;gt;[Image]&lt;br /&gt;
[Image]-&amp;gt;[Window {bg:blue}]&lt;br /&gt;
[Window {bg:blue}]-[note:Implemented in FlightGear $FG_SRC/Canvas/window.?xx]&lt;br /&gt;
[Element]-&amp;gt;[Text]&lt;br /&gt;
[Element]-&amp;gt;[Path]&lt;br /&gt;
[SGPropertyChangeListener]-[note:Fires events and runs callbacks once properties change]&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:PropertyTree and Canvas.png|1000px|property tree &amp;amp; canvas]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Frameworks ==&lt;br /&gt;
&lt;br /&gt;
[[File:CanvasOverview02-2014.png|thumb|Overview of the Canvas system and its scripting space frameworks]] &lt;br /&gt;
&lt;br /&gt;
Obviously, the Canvas {{abbr|API|Application Programming Interface}} s themselves are not intended for specific end-user features like developing a {{abbr|PFD|Primary Flight Display}}, {{abbr|ND|Navigational Display}}  or EICAS - therefore, you will typically see wrappers implemented in scripting space for certain needs - i.e. Canvas frameworks intended to help with the development of certain types of instruments for example. Frameworks will usually use the Canvas scripting space API directly, while providing a more concrete, use-case specific API, on top.&lt;br /&gt;
&lt;br /&gt;
{{Canvas Frameworks}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Elements ==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
// http://yuml.me/diagram/scruffy/class/draw&lt;br /&gt;
[CanvasImage{bg:blue}]-[note:handles raster images-including texture maps and other canvases]&lt;br /&gt;
[CanvasMap{bg:blue}]-[note:directly projects child elements using geographic coordinates-can easily support additional projections-currently just Sanson-Flamsteed]&lt;br /&gt;
[CanvasPath{bg:blue}]-[note:wraps ShivaVG and is used by the scripted SVG parser]&lt;br /&gt;
[CanvasText{bg:blue}]-[note:wraps osgText (Fonts)]&lt;br /&gt;
[CanvasGroup{bg:orange}]-[note:groups are special: as a group is also the root element that serves as the main element for any other elements-including other groups-which is why groups serve as the registry for new elements]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:CanvasElements-Overview.png|800px|Overview of currently supported Canvas Elements]]&lt;br /&gt;
&lt;br /&gt;
All new canvas elements need to implement the Canvas::Element interface (new elements can also sub-class existing  elements, e.g. see the implementation of the Map and Window($FG_SRC/Canvas) elements), the canvas system currently supports the following primitives (see [[$SG_SRC]]/canvas/elements):&lt;br /&gt;
&lt;br /&gt;
* '''CanvasGroup''' - main element: for grouping (a group of arbitrary canvas primitives, including other groups)&lt;br /&gt;
* CanvasText - for rendering texts (mapped to osgText)&lt;br /&gt;
* CanvasPath - for rendering vector graphics (mapped to OpenVG, currently also used to render SVGs into groups)&lt;br /&gt;
* '''CanvasMap''' - for rendering maps (automatic projection of geographic coordinates to screen coordinates, subclass of group)&lt;br /&gt;
* CanvasImage - for rendering raster images (mapped to osg::Image)&lt;br /&gt;
* &amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;CanvasWindow - this is part of $FG_SRC/Canvas/Window.?xx, it's a subclass of CanvasImage, used to implement windows&amp;lt;/font&amp;gt; (as of 05/2014 also to be found in simgear)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
// http://yuml.me/diagram/scruffy/class/draw&lt;br /&gt;
[Canvas{bg:green}]-&amp;gt;[CanvasElement]&lt;br /&gt;
[CanvasElement]-[note:base class-must be subclassed by all elements]&lt;br /&gt;
[CanvasElement]-&amp;gt;[CanvasGroup{bg:blue}]&lt;br /&gt;
[CanvasElement]-&amp;gt;[CanvasText{bg:blue}]&lt;br /&gt;
[CanvasElement]-&amp;gt;[CanvasPath{bg:blue}]&lt;br /&gt;
[CanvasElement]-&amp;gt;[CanvasImage{bg:blue}]&lt;br /&gt;
[CanvasElement]-&amp;gt;[CanvasMap{bg:blue}]&lt;br /&gt;
[Canvas{bg:green}]-[note:represents a single FBO/offscreen RTT context]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-Elements.png|thumb|Canvas vs. Canvas Elements]]&lt;br /&gt;
&lt;br /&gt;
Most end-user features can be decomposed into lower-level components that need to be available in order to implement the corresponding feature in user-space.&lt;br /&gt;
&lt;br /&gt;
Thus, the canvas system is based on a handful of rendering modes, each supporting different primitives - each of those modes is implemented as a so called &amp;quot;Canvas Element&amp;quot;, which is a property-tree controlled subtree of a canvas texture using a certain name, that supports specific events and notifications.&lt;br /&gt;
&lt;br /&gt;
According to the development philosophy outlined above, you obviously won't see new canvas elements that are highly use-case specific, such as a &amp;quot;night vision&amp;quot; or FLIR element. Instead, what is more likely to be supported are the lower level building blocks to enable end-users creating such features, i.e. by adding support for running custom effects/shaders and by rendering scenery views to canvas textures.&lt;br /&gt;
&lt;br /&gt;
== Adding a new Element ==&lt;br /&gt;
You will want to add a new Canvas::Element whenever you want to add support for features which cannot be currently expressed easily (or efficiently) using existing means (i.e. via existing elements and scripting space frameworks). For example, this may involve projects requiring camera support, rendering scenery views to a texture, rendering 3D models to a texture or doing a complete moving map with terrain elevations/height maps  (even though the latter could be implemented by sub-classing Canvas::Image to some degree). &lt;br /&gt;
&lt;br /&gt;
To add a new element, these are the main steps:&lt;br /&gt;
&lt;br /&gt;
* Navigate to [[$SG_SRC]]/canvas/elements&lt;br /&gt;
* Create a new set of files myElement.cxx myElement.hxx&lt;br /&gt;
* add them to [[$SG_SRC]]/canvas/elements/CMakeLists.txt (as per [[Developing using CMake]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;diff&amp;quot;&amp;gt;&lt;br /&gt;
diff --git a/simgear/canvas/elements/CMakeLists.txt b/simgear/canvas/elements/CMakeLists.txt&lt;br /&gt;
index bd21c13..9fdd48d 100644&lt;br /&gt;
--- a/simgear/canvas/elements/CMakeLists.txt&lt;br /&gt;
+++ b/simgear/canvas/elements/CMakeLists.txt&lt;br /&gt;
@@ -1,6 +1,7 @@&lt;br /&gt;
 include (SimGearComponent)&lt;br /&gt;
 &lt;br /&gt;
 set(HEADERS&lt;br /&gt;
+  myElement.hxx&lt;br /&gt;
   CanvasElement.hxx&lt;br /&gt;
   CanvasGroup.hxx&lt;br /&gt;
   CanvasImage.hxx&lt;br /&gt;
@@ -14,6 +15,7 @@ set(DETAIL_HEADERS&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 set(SOURCES&lt;br /&gt;
+  myElement.cxx&lt;br /&gt;
   CanvasElement.cxx&lt;br /&gt;
   CanvasGroup.cxx&lt;br /&gt;
   CanvasImage.cxx&lt;br /&gt;
@@ -23,4 +25,4 @@ set(SOURCES&lt;br /&gt;
 )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, open the header file and add a new Element classs:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef CANVAS_MYELEMENT_HXX_&lt;br /&gt;
#define CANVAS_MYELEMENT_HXX_&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;simgear/props/propsfwd.hxx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;CanvasElement.hxx&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
namespace simgear&lt;br /&gt;
{&lt;br /&gt;
namespace canvas&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    class myElement :  public Element&lt;br /&gt;
  {&lt;br /&gt;
    public:&lt;br /&gt;
        static const std::string TYPE_NAME;&lt;br /&gt;
        static void staticInit();&lt;br /&gt;
&lt;br /&gt;
        myElement( const CanvasWeakPtr&amp;amp; canvas,&lt;br /&gt;
               const SGPropertyNode_ptr&amp;amp; node,&lt;br /&gt;
               const Style&amp;amp; parent_style = Style(),&lt;br /&gt;
               Element* parent = 0 );&lt;br /&gt;
        virtual ~myElement();&lt;br /&gt;
    protected:&lt;br /&gt;
        virtual void update(double dt);&lt;br /&gt;
    private:&lt;br /&gt;
      myElement(const myElement&amp;amp;) /* = delete */;&lt;br /&gt;
      myElement&amp;amp; operator=(const myElement&amp;amp;) /* = delete */;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
} // namespace canvas&lt;br /&gt;
} // namespace simgear&lt;br /&gt;
&lt;br /&gt;
#endif /* CANVAS_MYELEMENT_HXX_ */&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, add the source file implementing the new myElement class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;myElement.hxx&amp;quot;&lt;br /&gt;
#include &amp;lt;simgear/props/props.hxx&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;simgear/misc/sg_path.hxx&amp;gt;&lt;br /&gt;
namespace simgear&lt;br /&gt;
{&lt;br /&gt;
namespace canvas&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    const std::string myElement::TYPE_NAME = &amp;quot;myelement&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    void myElement::staticInit()&lt;br /&gt;
    {&lt;br /&gt;
      if( isInit&amp;lt;myElement&amp;gt;() )&lt;br /&gt;
        return;&lt;br /&gt;
      &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //----------------------------------------------------------------------------&lt;br /&gt;
    myElement::myElement( const CanvasWeakPtr&amp;amp; canvas,&lt;br /&gt;
                  const SGPropertyNode_ptr&amp;amp; node,&lt;br /&gt;
                  const Style&amp;amp; parent_style,&lt;br /&gt;
                  Element* parent ):&lt;br /&gt;
   Element(canvas, node, parent_style, parent)&lt;br /&gt;
    &lt;br /&gt;
    {&lt;br /&gt;
        SG_LOG(SG_GENERAL, SG_ALERT, &amp;quot;New Canvas::myElement element added!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    //----------------------------------------------------------------------------&lt;br /&gt;
    myElement::~myElement()&lt;br /&gt;
    {&lt;br /&gt;
        SG_LOG(SG_GENERAL, SG_ALERT, &amp;quot;Canvas::myElement element destroyed!&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void myElement::update(double dt)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
} // namespace canvas&lt;br /&gt;
} // namespace simgear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, edit CanvasGroup.cxx to register your new element (each canvas has a top-level '''root''' group, so that's how elements show up), navigate to Group::staticInit() and add your new element type there (don't forget to add your new header):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;diff&amp;quot;&amp;gt;&lt;br /&gt;
diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx&lt;br /&gt;
index 51523f4..24e19d3 100644&lt;br /&gt;
--- a/simgear/canvas/elements/CanvasGroup.cxx&lt;br /&gt;
+++ b/simgear/canvas/elements/CanvasGroup.cxx&lt;br /&gt;
@@ -21,6 +21,7 @@&lt;br /&gt;
 #include &amp;quot;CanvasMap.hxx&amp;quot;&lt;br /&gt;
 #include &amp;quot;CanvasPath.hxx&amp;quot;&lt;br /&gt;
 #include &amp;quot;CanvasText.hxx&amp;quot;&lt;br /&gt;
+#include &amp;quot;myElement.hxx&amp;quot;&lt;br /&gt;
 #include &amp;lt;simgear/canvas/CanvasEventVisitor.hxx&amp;gt;&lt;br /&gt;
 #include &amp;lt;simgear/canvas/MouseEvent.hxx&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
@@ -60,6 +61,7 @@ namespace canvas&lt;br /&gt;
       return;&lt;br /&gt;
 &lt;br /&gt;
     add&amp;lt;Group&amp;gt;(_child_factories);&lt;br /&gt;
+    add&amp;lt;myElement&amp;gt;(_child_factories);&lt;br /&gt;
     add&amp;lt;Image&amp;gt;(_child_factories);&lt;br /&gt;
     add&amp;lt;Map  &amp;gt;(_child_factories);&lt;br /&gt;
     add&amp;lt;Path &amp;gt;(_child_factories);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, navigate to [[$FG_ROOT]]/Nasal/canvas/api.nas and extend the module to add support for your new element:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;diff&amp;quot;&amp;gt;&lt;br /&gt;
diff --git a/Nasal/canvas/api.nas b/Nasal/canvas/api.nas&lt;br /&gt;
index 85f336a..81c0fa0 100644&lt;br /&gt;
--- a/Nasal/canvas/api.nas&lt;br /&gt;
+++ b/Nasal/canvas/api.nas&lt;br /&gt;
@@ -314,6 +314,18 @@ var Element = {&lt;br /&gt;
   }&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
+# myElement&lt;br /&gt;
+# ==============================================================================&lt;br /&gt;
+# Class for a group element on a canvas&lt;br /&gt;
+#&lt;br /&gt;
+var myElement = {&lt;br /&gt;
+# public:&lt;br /&gt;
+  new: func(ghost)&lt;br /&gt;
+  {&lt;br /&gt;
+    return { parents: [myElement, Element.new(ghost)] };&lt;br /&gt;
+  },&lt;br /&gt;
+};&lt;br /&gt;
+&lt;br /&gt;
 # Group&lt;br /&gt;
 # ==============================================================================&lt;br /&gt;
 # Class for a group element on a canvas&lt;br /&gt;
@@ -958,7 +970,8 @@ Group._element_factories = {&lt;br /&gt;
   &amp;quot;map&amp;quot;: Map.new,&lt;br /&gt;
   &amp;quot;text&amp;quot;: Text.new,&lt;br /&gt;
   &amp;quot;path&amp;quot;: Path.new,&lt;br /&gt;
-  &amp;quot;image&amp;quot;: Image.new&lt;br /&gt;
+  &amp;quot;image&amp;quot;: Image.new,&lt;br /&gt;
+  &amp;quot;myelement&amp;quot;: myElement.new,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, rebuild SG/FG and open the [[Nasal Console]] and run a simple demo to test your new element:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var CanvasApplication = {&lt;br /&gt;
 ##&lt;br /&gt;
 # constructor&lt;br /&gt;
 new: func(x=300,y=200) {&lt;br /&gt;
  var m = { parents: [CanvasApplication] };&lt;br /&gt;
  m.dlg = canvas.Window.new([x,y],&amp;quot;dialog&amp;quot;);&lt;br /&gt;
  m.canvas = m.dlg.createCanvas().setColorBackground(1,1,1,1);&lt;br /&gt;
  m.root = m.canvas.createGroup();&lt;br /&gt;
&lt;br /&gt;
  ##&lt;br /&gt;
  # creates a new element&lt;br /&gt;
  m.myElement = m.root.createChild(&amp;quot;myelement&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  m.init();&lt;br /&gt;
  return m;&lt;br /&gt;
 }, # new&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
init: func() {&lt;br /&gt;
 &lt;br /&gt;
 var filename = &amp;quot;Textures/Splash1.png&amp;quot;;&lt;br /&gt;
 # create an image child for the texture&lt;br /&gt;
 var child=me.root.createChild(&amp;quot;image&amp;quot;)&lt;br /&gt;
			           .setFile( filename )&lt;br /&gt;
				   .setTranslation(25,25)&lt;br /&gt;
                                   .setSize(250,250);&lt;br /&gt;
}, #init&lt;br /&gt;
&lt;br /&gt;
}; # end of CanvasApplication&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
var splash = CanvasApplication.new(x:300, y:300);&lt;br /&gt;
 &lt;br /&gt;
print(&amp;quot;Script parsed&amp;quot;);v&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
you may also want to check out [[$FG_SRC]]/Scripting/NasalCanvas.?xx to learn more about exposing custom elements to scripting space via [[Nasal/CppBind]].&lt;br /&gt;
Next, you'll want to implement the update() methods and the various notification methods supported by CanvasElement:&lt;br /&gt;
* childAdded&lt;br /&gt;
* childRemoved&lt;br /&gt;
* childChanged&lt;br /&gt;
* valueChanged&lt;br /&gt;
&lt;br /&gt;
For event handling purposes, you'll also want to check out the following virtual CanvasElement methods:&lt;br /&gt;
* accept()&lt;br /&gt;
* ascend()&lt;br /&gt;
* traverse()&lt;br /&gt;
* handleEvent()&lt;br /&gt;
* hitBound()&lt;br /&gt;
&lt;br /&gt;
== Discussed Enhancements ==&lt;br /&gt;
&lt;br /&gt;
{{Note|The features described in the following section aren't currently supported or being worked on, but they've seen lots of community discussion over the years, so that this serves as a rough overview.}}&lt;br /&gt;
=== An integrated Canvas based launcher ===&lt;br /&gt;
{{mergeto|Template:Canvas Frameworks|date=May 2014}}&lt;br /&gt;
&lt;br /&gt;
Also see {{Issue|1295}}, [[Reset &amp;amp; re-init#Benefits]] and [http://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/5387B0DB.4030001%40bham.ac.uk/#msg32396634]&lt;br /&gt;
&lt;br /&gt;
{{cquote|people have been working on making external launchers obsolete for most use-cases in future versions, which is likely to materialize around FG 4.2+ according to recent discussions and commits.&amp;lt;ref&amp;gt;{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=37&amp;amp;t=22330&amp;amp;p=202924&amp;amp;hilit=fgrun+obsolete#p202924|title=&amp;lt;nowiki&amp;gt;Dev and test environment&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;Thu May 15, 2014 1:33 pm&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|An integrated GUI launcher is something that we'd all like to see, and which we are working towards - it will probably happen within the next 12-18 months (just a guess), not because it's such a high priority, but because, by then, we should have all the pieces for it in place - and the 3-4 main core developers (main, in terms of activity) agree that this is the way forward, so from a middleware (Nasal/XML, Canvas) standpoint, we're going to help with creating a framework to parse our existing GUI dialogs and turn them into canvas-driven GUI widgets, which will need to be developed first of all though - that's the kind of stuff that Philosopher has been doing in his REPL interpreter: custom GUI work.&lt;br /&gt;
The chances are pretty good that the upcoming GUI will look much less 1940s style than the existing GUI, i.e. fairly modern actually.&lt;br /&gt;
But the good news for you is that styling/skinnig is intended to be supported eventually. Tom has in fact added quite a bit of code to make that fast and flexible, not just Nasal, but also C++ - so he seems to consider that a priority, too.&amp;lt;ref&amp;gt;{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=21617&amp;amp;p=209571&amp;amp;hilit=#p209586|title=&amp;lt;nowiki&amp;gt;Dev and test environment&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;Thu May 15, 2014 1:33 pm&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|The main thing here is &amp;quot;run-time reinitialization&amp;quot; - i.e. having code that doesn't need to be shut down to change settings, but that simply fetches the new settings and applies them.&lt;br /&gt;
Zakalawe has been working towards this as part of the reset/re-init effort - mid-term, the idea is to make GUI launchers obsolete for most people, by providing an in-sim GUI launcher where such settings can be directly changed, including changing aircraft, but also saving/loading flights.&lt;br /&gt;
For these reasons, most of us are not too eager to extend external GUI launchers.&lt;br /&gt;
&lt;br /&gt;
Canvas-wise, there isn't much missing to provide an integrated GUI launcher - what would be useful though, is having a new element that renders arbitrary 3D models/camera views to a texture, i.e. for aircraft/scenery previews. But otherwise, this is mostly a matter of having scripting (Nasal) and Canvas available earlier, so that a GUI launcher can created using ~200-300 lines of Nasal. This is also where we could provide a pulldown menu with settings for a handful of startup/run-time profiles.&lt;br /&gt;
&lt;br /&gt;
And of course there are still a handful of subsystems that cannot currently be re-intialized without shutting down the whole thing.&lt;br /&gt;
For non programmers, it's helpful to imagine it like exchanging your car radio, seats, brakes or even engine, while going 100 mph - not impossible to pull off, but quite a few - especially because the &amp;quot;car&amp;quot; (FG) was never designed with this requirement in mind.&amp;lt;ref&amp;gt;{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=21617&amp;amp;p=209571&amp;amp;hilit=#p209571|title=&amp;lt;nowiki&amp;gt;Dev and test environment&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;Thu May 15, 2014 1:33 pm&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;Hooray&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|I made some experiments with creating a GUI using Canvas, but it’s not an area I especially enjoy or feel comfortable working in, so progress was slow, and recently, non-existant. I have considered making a placeholder GUI using PUI widgets, which would only take a couple of days for something basic, but again hacking the PUI code is far from enjoyable.&amp;lt;ref&amp;gt;{{cite web |url=http://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/D4E91618-5AE0-4073-98B3-43711E70871A%40mac.com/#msg32375981|title=&amp;lt;nowiki&amp;gt;24 days from freeze: what happened to...&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;James Turner&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;2014-05-24 09:33:20&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;James Turner&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== Supporting Cameras ===&lt;br /&gt;
{{Note|People interested in working on this may want to check out the following pointers:&lt;br /&gt;
* [http://docs.freeflightsim.org/flightgear/classflightgear_1_1CameraGroup.html CameraGroup]&lt;br /&gt;
* [http://docs.freeflightsim.org/flightgear/structflightgear_1_1CameraInfo.html CameraInfo]&lt;br /&gt;
* Rembrandt Commits&lt;br /&gt;
* ...&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* {{Git link|gitorious|fg/simgear|next|src/canvas/CanvasPlacement.hxx|text=CanvasPlacement Interface in SimGear}}&lt;br /&gt;
* {{Git link|gitorious|fg/flightgear|next|src/Main/Viewer/WindowBuilder.cxx|text=$FG_SRC/Viewer/WindowBuilder.?xx}}&lt;br /&gt;
* {{Git link|gitorious|fg/flightgear|next|src/Main/Viewer/WindowSystemAdapter.cxx|text=$FG_SRC/Viewer/WindowSystemAdapter.?xx}}&lt;br /&gt;
* {{Git link|gitorious|fg/flightgear|next|src/Main/Canvas/window.cxx|text=Canvas Windows Implementation}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Background:&lt;br /&gt;
* [[Howto:Use a Camera View in an Instrument]]&lt;br /&gt;
* [[$FG_ROOT]]/Docs/README.multiscreen&lt;br /&gt;
* http://docs.freeflightsim.org/flightgear/classflightgear_1_1CameraGroup.html&lt;br /&gt;
* https://gitorious.org/fg/zans-flightgear/commits/09832d8076a985a329500c027c1ed4f9b72bb1a9&lt;br /&gt;
* http://trac.openscenegraph.org/projects/osg/wiki/Support/ProgrammingGuide/ViewerVSCompositeViewer&lt;br /&gt;
&lt;br /&gt;
Also see [[The FlightGear Rendering Pipeline]]&lt;br /&gt;
&lt;br /&gt;
{{cquote|I'm looking to replicate a camera with a fixed viewpoint from the aircraft. For example looking directly down.&lt;br /&gt;
&lt;br /&gt;
Is there a way I can use some scripting method to call a new window displayed in the bottom right hand side of the screen showing a fixed camera view, without having to edit the preferences for my machine? I'd like it to be easily distributable. &amp;lt;ref&amp;gt;{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=18&amp;amp;t=22376&amp;amp;p=203175#p203145|title=Sub window view|author=Avionyx|date=Wed Mar 12, 2014 7:08 am}}&amp;lt;/ref&amp;gt;|Avionyx }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I was wondering if it were possible to restrict the camera output to only one half of the running FG window? I'm hoping to do this so that I may have the map and route manager GUIs active in the other half, so that they aren't obscuring the camera view (and also have the entire HUD visible). So basically, half the window straight down the center - left half is just black, right half is the camera.&lt;br /&gt;
&lt;br /&gt;
Although this would also be solved if there were an external FG dynamic navigational map program, that also displayed waypoints... (I don't think there is one, right?).&lt;br /&gt;
&lt;br /&gt;
Additionally, I would love to hear that this question can be answered with Nasal, as I really can't afford to edit the source code and recompile (it's for a project, and I have no admin rights on the laboratory machines).&amp;lt;ref&amp;gt;{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=18&amp;amp;t=21897&amp;amp;p=200744&amp;amp;hilit=#p198735|title=&amp;quot;Half&amp;quot; the FG window?|author=seabutler|date=Fri Jan 24, 2014 5:38 am}}&amp;lt;/ref&amp;gt;|seabutler }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I'm trying to debug reflection shader I'm working on. I have a camera attached to a scene graph, which pre-renders (osg::Camera::PRE_RENDER) scene into offscreen surface (osg::Camera::FRAME_BUFFER_OBJECT); For a debugging purposes I have to see the result of that render pass.&lt;br /&gt;
I'm not very good yet in FG internal structure, so I'd like to ask - can this camera be somehow  attached to FG camera views (v), or embedded as separate window ?&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg20282.html|title=FG - camera for debugging purposes.|author=Vladimir Karmisin|date=Thu, 08 Jan 2009 05:17:07 -0800}}&amp;lt;/ref&amp;gt;|Vladimir Karmisin }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I want to give access to every stage of the rendering to the effect system. The geometry pass outputs to render target, but the fog,  the lights, the bloom need to have access to the textures of the buffer, and there is a separate one for each camera associated to windows or sub windows.  &amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg35553.html|title=Announcing Project Rembrandt|author=Frederic Bouvier |date=Sun, 01 Jan 2012 07:14:43 -0800}}&amp;lt;/ref&amp;gt;|Frederic Bouvier }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|It would be nice if the Effects framework had a way to load arbitrary textures and make them available to effects.I don't know if there is a better way to create your texture offline than write C++ code in simgear. {{abbr|OSG|OpenSceneGraph}} will read a TIFF file with 32bits per component as a floating point texture... assuming you can create&lt;br /&gt;
such a thing.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg37873.html|title=Functions to textures?|author=Tim Moore |date=Tue, 24 Jul 2012 22:38:35 -0700}}&amp;lt;/ref&amp;gt;|Tim Moore }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|modify the Renderer class to separate from the scenegraph, terrain and models on one hand, the skydome and stars on the other, and finally the clouds. &lt;br /&gt;
These three elements are passed to the CameraGroup class in order to be treated separately in the new rendering engine (and put together in the current one).&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg36481.html|title=RFC: changes to views and cameras|author=Frederic Bouvier |date=Wed, 07 Mar 2012 05:08:06 -0800}}&amp;lt;/ref&amp;gt;|Frederic Bouvier }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I want to point out my work on my &amp;quot;newcameras&amp;quot; branch: https://gitorious.org/~zan/fg/zans-flightgear/commits/newcameras which allows user to define the rendering pipeline in preferences.xml. It does not (yet?) have everything Rembrandt's pipeline needs, but most likely is easily enhanced to support those things.&lt;br /&gt;
&lt;br /&gt;
Basically this version adds support for multiple camera passes, texture targets, texture formats, passing textures from one pass to another etc, while preserving the standard rendering line if user wants that.&lt;br /&gt;
&lt;br /&gt;
I wish this work could be extended (or maybe even I can extend it ;) to handle the Rembrandt camera system. This will not solve all problems in the merge, but some of them.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg36481.html|title=Rembrandt the plan|author=Lauri Peltonen  |date= Wed, 07 Mar 2012 04:58:44 -0800}}&amp;lt;/ref&amp;gt;|Lauri Peltonen }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I was not aware of your work. But given what you write here, this looks pretty promising. Fred mentioned your name in an offline mail. I would highly apprechiate that we do not lock out low end graphics boards by not having any fallback. May you both should combine forces?&lt;br /&gt;
From what I read, I think both are heading in the same global direction and both implementations have some benefits over the other?&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg36481.html|title=Rembrandt the plan|author=Mathias Fröhlich |date= Wed, 07 Mar 2012 10:15:31 -0800}}&amp;lt;/ref&amp;gt;|Mathias Fröhlich }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I would like to extend the format to avoid duplicating the stages when you have more than one viewport. What I see is to specify a pipeline as a template, with conditions like in effects, and have the current camera layout refer the pipeline that would be duplicated, resized and positioned for each declared viewport&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg36481.html|title=RFC: changes to views and cameras|author=Frederic Bouvier |date=Wed, 07 Mar 2012 05:08:06 -0800}}&amp;lt;/ref&amp;gt;|Frederic Bouvier }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|Mapping cameras to different windows, which can be opened on arbitrary screens, will absolutely still be supported. I know that multi-GPU setups are&lt;br /&gt;
important for professional users and our demos.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg17026.html|title=RFC: changes to views and cameras|author=Tim Moore |date=30 Jun 2008 22:46:34 -0700}}&amp;lt;/ref&amp;gt;|Tim Moore }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I believe that we need to distinguish between different render to texture cameras. Camera nodes must be accessible from within flightgear. That ones that will end in mfd displays or hud or whatever that is pinned into models. And one that are real application windows like what you describe - additional fly by view, and so on. And I believe that we should keep that separate and not intermix the code required for application level stuff with building of 3d models that do not need anything application level code to animate the models ... I think of some kind of separation that will also be good if we would do HLA between a viewer and an application computing physical models or controlling an additional view hooking into a federate ...&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg17026.html|title=RFC: changes to views and cameras|author=Mathias Fröhlich |date=30 Jun 2008 22:46:34 -0700}}&amp;lt;/ref&amp;gt;|Mathias Fröhlich }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|I've done some work with setting up a model of a pan/tilt camera system that can point at a specific wgs84 point or along a specific NED vector&lt;br /&gt;
(i.e. nadir, or exactly at my shadow, etc.)  This was [unfortunately] for a paid consulting project so that code doesn't live in the FlightGear tree. However, it's really easy to configure a view that stays locked on a specific lon/lat and I hacked a small bit of nasal to copy the point  you click on over into the view target variables so you can click any where in the scene and the pan/tilt camera will hold center on that exact location. FlightGear offers a lot of flexibility and comparability in this arena.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg37331.html|title=LiDAR simulation in FG and powerline scenery|author=Curtis Olson |date= Tue, 15 May 2012 14:19:34 -700}}&amp;lt;/ref&amp;gt;|Curtis Olson }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|Would it be possible to place the new &amp;quot;view&amp;quot; into a window instead of having a dedicated view?  That would allow you to have an instrument panel with a blank cut-out that could hold this newscam/FLIR window.The easiest way to visualize the idea I have is to think about the view you'd see in one of the rear-view mirrors that most fighters have along the canopy bow (and the Spitfire has mounted on top of the canopy bow, outside the cockpit).  You'd see your full screen view as usual, but you'd also have these &amp;quot;mirrors&amp;quot; showing the view behind you at the same time.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg22880.html|title=view manager &amp;quot;look at&amp;quot; mode|author=Gene Buckle |date=  Thu, 23 Jul 2009 10:11:05 -0700}}&amp;lt;/ref&amp;gt;|Gene Buckle }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|One thing we have to consider with rear view mirrors is that we don't currently have the ability to flip the display for the &amp;quot;mirror&amp;quot; affect.There's got to be a very simple view transform matrix that would invert the display in the horizontal direction.  Probably the identity matrix with the appropriate axis negated (-1).  It might be a relatively simple thing to add to the view transform pipeline at some point.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg22880.html|title=view manager &amp;quot;look at&amp;quot; mode|author=Curtis Olson |date=  Thu, 23 Jul 2009 10:11:05 -0700}}&amp;lt;/ref&amp;gt;|Curtis Olson }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I had a look at the this idea a while back - the problem I came across was that the camera would show the view to the rear NOT the mirror image. I&lt;br /&gt;
couldn't see a way around that without a great deal of processing. At hat point I gave up.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg22880.html|title=view manager &amp;quot;look at&amp;quot; mode|author=Vivian Meazza |date=  Thu, 23 Jul 2009 10:11:05 -0700}}&amp;lt;/ref&amp;gt;|Vivian Meazza }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* http://sourceforge.net/p/flightgear/mailman/message/32394673/&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Effects / Shaders ===&lt;br /&gt;
{{cquote| I'm currently experimenting with a 2D Canvas and rendering everything to a texture. For this I use FGODGauge to render to texture and&lt;br /&gt;
FGODGauge::set_texture to replace a texture in the cockpit with the texture from the fbo. This works very well [...] I have just extended the ReplaceStaticTextureVisitor::apply(osg::Geode&amp;amp; node) method to also replace texture inside effects.&lt;br /&gt;
&lt;br /&gt;
It works now by using the same technique as for the SGMaterialAnimation where a group is placed in between the object whose texture should be changed and its parent. This group overrides the texture:&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;virtual void apply(osg::Geode&amp;amp; node)&lt;br /&gt;
    {&lt;br /&gt;
      simgear::EffectGeode* eg =&lt;br /&gt;
        dynamic_cast&amp;lt;simgear::EffectGeode*&amp;gt;(&amp;amp;node);&lt;br /&gt;
      if( eg )&lt;br /&gt;
      {&lt;br /&gt;
        osg::StateSet* ss = eg-&amp;gt;getEffect()-&amp;gt;getDefaultStateSet();&lt;br /&gt;
        if( ss )&lt;br /&gt;
          changeStateSetTexture(ss);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
        if( node.getStateSet() )&lt;br /&gt;
          changeStateSetTexture(node.getStateSet());&lt;br /&gt;
      int numDrawables = node.getNumDrawables();&lt;br /&gt;
      for (int i = 0; i &amp;lt; numDrawables; i++) {&lt;br /&gt;
          osg::Drawable* drawable = node.getDrawable(i);&lt;br /&gt;
          osg::StateSet* ss = drawable-&amp;gt;getStateSet();&lt;br /&gt;
          if (ss)&lt;br /&gt;
              changeStateSetTexture(ss);&lt;br /&gt;
      }&lt;br /&gt;
      traverse(node);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
stateSet-&amp;gt;setTextureAttribute(0, _new_texture,&lt;br /&gt;
osg::StateAttribute::OVERRIDE);&lt;br /&gt;
        stateSet-&amp;gt;setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg37225.html|title=&amp;lt;nowiki&amp;gt;Replace texture with RTT&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;Thomas Geymayer&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;Tue, 01 May 2012 15:34:41 -0700&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;Thomas Geymayer&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|If you want to pass substantial amounts of data, I’d suggest to use a texture (with filtering disabled, probably) to pass the info. Since we don’t have much chance of using the ‘correct’ solution (UBOs) in the near future.&lt;br /&gt;
&lt;br /&gt;
If you need help generating a suitable texture on the CPU side, let me know.&amp;lt;ref&amp;gt;{{cite web |url=http://sourceforge.net/p/flightgear/mailman/message/32072598/|title=&amp;lt;nowiki&amp;gt;Passing arrays to a shader&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;James Turner&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt; 2014-03-07 10:27:40&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;James Turner&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At some point, the canvas system itself could probably benefit from being also able to use the Effects/Shader framework, so that canvas textures can also be processed via effects and shaders optionally, before they get drawn. That should make all sorts of fancy effects possible, such as night vision cameras or thermal view, rendered to canvas textures/groups.&lt;br /&gt;
&lt;br /&gt;
It is currently not yet clear how to address this best, the easiest option might be to specify if effects or vertex/fragment shaders shall be invoked via properties (boolean), including their file names referring to [[$FG_ROOT]]?&lt;br /&gt;
&lt;br /&gt;
That would then disable the default rendering pipeline for those canvas textures and use shaders.&lt;br /&gt;
&lt;br /&gt;
Basically, anything that's not directly possible via the core canvas system or via its Nasal wrappers, would then be handled via effects/shaders. So we would gain lots of flexibility, and performance benefits.&lt;br /&gt;
&lt;br /&gt;
Ideally, there could be a simple interface class, so that these things can be customized via listeners, like the property-observer helper, just specific to enabling shaders for a canvas texture.&lt;br /&gt;
So if people really want to create really fancy textures or camera views, they could use effects/shaders then, which would keep the design truly generic, and it would ensure that there's no bloat introduced into the main canvas system.&lt;br /&gt;
&lt;br /&gt;
We did have some discussions about supporting per-canvas (actually per canvas::Element) effects and shaders via properties, TheTom even mentioned that he was interested in supporting this at some point, especially given the number of projects that could be realized like that (FLIR, night vision, thermal imaging etc) - but so far, there are quite a few other things that are taking precedence obviously - so, as far as I am aware, there's nobody working on effects/shader support for canvas, even though I am sure that this would be highly appreciated. &lt;br /&gt;
&lt;br /&gt;
At the time of writing this (02/2014) the Canvas does not yet include any support for applying custom effects or [[Shaders]] to canvas elements or the whole canvas itself - however, supporting this is something that's been repeatedly discussed over time, so we're probably going to look into supporting this eventually[http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37210.html].&lt;br /&gt;
&lt;br /&gt;
If the canvas can internally be referenced by a texture2D() call, then it should be easy - the fragment shader knows screen resolution pixel coordinates, so it's straightforward to look up the local pixel from the texture and then blur or recolor it, distort it or whatever you have in mind. &lt;br /&gt;
&lt;br /&gt;
Menu lighting based on light in the scene might be cool &lt;br /&gt;
&lt;br /&gt;
These shouldn't even be very complicated to do&lt;br /&gt;
&lt;br /&gt;
Assuming the canvas is internally a quad with a properly uv-mapped texture, then:&lt;br /&gt;
&lt;br /&gt;
* making the vertex shader just pass everything through and &lt;br /&gt;
* uniform sampler2D myTexture; should make that texture available to the fragment shader&lt;br /&gt;
* vec2 coords = gl_TexCoord[0].xy; should get the coordinates of the local pixel inside the texture&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
#version 120&lt;br /&gt;
uniform sampler2D input_tex;&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
&lt;br /&gt;
// get the texture coords of the pixel&lt;br /&gt;
 vec2 coords = gl_TexCoord[0].xy;&lt;br /&gt;
&lt;br /&gt;
//look up the pixel color from the input texture&lt;br /&gt;
vec4 color =   texture2D( input_tex, coords) ;&lt;br /&gt;
&lt;br /&gt;
// and pass the pixel color through&lt;br /&gt;
gl_FragColor = color;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are at least 2-3 people who can help with pointers, but we don't have time to implement this ourselves - so if anybody is interested, please get in touch via the canvas subforum.&lt;br /&gt;
&lt;br /&gt;
The Effects framework is implemented in SimGear: http://gitorious.org/fg/simgear/trees/next/simgear/scene/material&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-glsl-support.png|thumb|airport selection dialog with a greyscale fragment shader applied to the canvas]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-Fragment-Shader-red.png|thumb|a trivial fragment shader applied to a canvas (the original colors used in the Nasal code were not changed!)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
void main(void) {&lt;br /&gt;
	gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-Fragment-Shader-circles.png|thumb|unmodified airport  selection canvas with fragment shader applied]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;glsl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// http://people.freedesktop.org/~idr/OpenGL_tutorials/03-fragment-intro.html&lt;br /&gt;
void main(void)&lt;br /&gt;
  {  &lt;br /&gt;
      vec2 pos = mod(gl_FragCoord.xy, vec2(50.0)) - vec2(25.0);&lt;br /&gt;
      float dist_squared = dot(pos, pos);&lt;br /&gt;
&lt;br /&gt;
      if (dist_squared &amp;lt; 400.0) &lt;br /&gt;
        gl_FragColor = vec4(.90, .90, .90, 0.0);&lt;br /&gt;
      else gl_FragColor = vec4(.20, .20, .40, 0.8);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-Fragment-Shader-experiments.png|thumb|more canvas fragment shading experiments]]&lt;br /&gt;
&lt;br /&gt;
Implementation-wise, supporting shaders per canvas seems straightforward to support - but it would probably be better to support shaders per element, where each element would render its own sub-texture if shaders/effects are specified, and apply the canvas' osg::StateSet otherwise. We could add an Interface on top of SimGear's &amp;quot;Effects&amp;quot; framework which would be implemented by the Canvas itself, but also by Canvas::Element&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Probably need to extend the Effects framework to support reloading effects/shaders from disk for testing purposes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;diff&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also see: &lt;br /&gt;
* http://trac.openscenegraph.org/projects/osg/wiki/Support/Tutorials/ShadersIntroduction&lt;br /&gt;
* http://trac.openscenegraph.org/projects/osg/wiki/Support/Tutorials/ShadersUpdating&lt;br /&gt;
* http://en.wikipedia.org/wiki/OpenGL_Shading_Language&lt;br /&gt;
* http://www.cuboslocos.com/tutorials/OSG-Shader&lt;br /&gt;
* http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=22166&lt;br /&gt;
* http://forum.flightgear.org/search.php?st=0&amp;amp;sk=t&amp;amp;sd=d&amp;amp;sr=posts&amp;amp;keywords=canvas+shader&lt;br /&gt;
* http://forum.flightgear.org/search.php?st=0&amp;amp;sk=t&amp;amp;sd=d&amp;amp;sr=posts&amp;amp;keywords=canvas+shaders&lt;br /&gt;
* http://forum.flightgear.org/search.php?st=0&amp;amp;sk=t&amp;amp;sd=d&amp;amp;sr=posts&amp;amp;keywords=canvas+effects&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Appendix}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Nasal]]&lt;br /&gt;
[[Category:Property Tree]]&lt;br /&gt;
[[Category:Core development projects]]&lt;br /&gt;
&lt;br /&gt;
=== Discussed new Elements ===&lt;br /&gt;
&lt;br /&gt;
The previously mentioned primitives alone can already be used to create very sophisticated avionics and dialogs - however, depending on your needs, you may want to extend the canvas system to support additional primitives. Typically, you'll want to add new primitives in order to optimize performance or simplify the creation of more sophisticated avionics and/or dialogs (e.g. for  mapping/charting purposes).&lt;br /&gt;
If you are interested in adding new primitives, please take a look at the sources in [[$SG_SRC]]/canvas/elements.&lt;br /&gt;
&lt;br /&gt;
For example, there's been talk about possibly adding the following additional primitives at some point. However, none of these are currently a priority or being worked on by anybody:&lt;br /&gt;
* support for a vertical mapping mode (e.g. to create Vertical Situation Displays or flight path evaluation dialogs), would probably make sense to use [http://trac.osgeo.org/proj/ PROJ4] for additional projcetion support?&lt;br /&gt;
* support for [[Howto:Use a Camera View in an Instrument|rendering scenery views]] (e.g. for tail cameras or mirrors etc) [http://forum.flightgear.org/viewtopic.php?f=4&amp;amp;t=15722&amp;amp;p=192595#p158690] [http://forum.flightgear.org/viewtopic.php?f=37&amp;amp;t=21192] {{Issue|1250}}&lt;br /&gt;
* support for ESRI shapefiles (instead of using shapelib, it would make sense to use GDAL/OGR here, or directly the {{abbr|OSG|OpenSceneGraph}}/ReaderWriterOGR plugin) [http://trac.openscenegraph.org/projects/osg/browser/OpenSceneGraph/trunk/src/osgPlugins/ogr] (FlightGear/osgEarth now depends on GDAL, so should be straightforward dependency-wise).&lt;br /&gt;
* support for GeoTIFF files or terrain height profiles using the tile cache&lt;br /&gt;
* rendering 3D objects&lt;br /&gt;
* support for ortographic moving map displays, e.g. using atlas [http://forum.flightgear.org/viewtopic.php?p=201955#p201955] (ideally using[[CompositeViewer Support]])&lt;br /&gt;
&lt;br /&gt;
If you are interested in working on any of these, please get in touch via the canvas sub forum first.&lt;br /&gt;
&lt;br /&gt;
There is already support for creating multiple osgviewer windows in FlightGear, this is commonly used in multiscreen setups - to support the creation and usage of [[Howto:Configure camera view windows|osgviewer windows]] in Canvas, we would need to look into adding a new placement type to the canvas system, so that osgviewer/OS windows can be created and controlled via the canvas system and a handful of placement-specific properties  [http://forum.flightgear.org/viewtopic.php?f=37&amp;amp;t=2985].&lt;br /&gt;
&lt;br /&gt;
== Placements ==&lt;br /&gt;
&lt;br /&gt;
Obviously, users can use the canvas system for developing all sorts of features that may need to be accessible using different interfaces - for these reasons, the canvas uses the concept of so called '''placements''', so that a canvas-texture can be shown inside GUI windows, GUI dialogs, cockpits, aircraft textures (liveries) - and also as part of the scenery (e.g. for a VGDS).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
// http://yuml.me/diagram/scruffy/class/draw&lt;br /&gt;
[Scenery{bg:cyan}]-[note:can be used to place a canvas in scenery (e.g.VGDS etc) ]&lt;br /&gt;
[Canvas Window (OSG){bg:cyan}]-[note:used for the new GUI]&lt;br /&gt;
[CanvasWidget (PUI){bg:cyan}]-[note:used for placing a canvas in old PUI/GUI dialogs]&lt;br /&gt;
[Aircraft{bg:cyan}]-[note:used to place  a canvas on aircraft (cockpit/livery etc)]&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-Placements.png|650px|supported canvas placements as of 03/2014]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Note|The features described in the following section aren't currently supported or being worked on, but they've seen lots of community discussion over the years, so that this serves as a rough overview.}}&lt;br /&gt;
&lt;br /&gt;
=== Scenery Overlays ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also see [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=21882&amp;amp;p=201862#p201862 Photoscenery via Canvas?] and  [http://forum.flightgear.org/viewtopic.php?f=3&amp;amp;t=22784&amp;amp;p=206581#p206581 A project to create a source of free geo-referenced instrument charts]&lt;br /&gt;
&lt;br /&gt;
{{cquote|Texture overlays - FG scenery engine does the chopping and texture co-ord  generation. &amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40flightgear.org/msg18530.html|title=Scenery engine features.|author=Paul Surgeon|Thu, 13 Nov 2003 15:37:22 -0800}}&amp;lt;/ref&amp;gt;|Paul Surgeon}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I am looking for a method for adding a graphical overlay channel to Flightgear. This overlay would consist of a dynamic texture that can be&lt;br /&gt;
modified in real time. I've used other OpenGL based systems with this feature but don't know where to start with implementing it in Flightgear.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg11324.html|title=Overlay Plane|author=Noah Brickman|Fri, 29 Jun 2007 13:27:15 -0700}}&amp;lt;/ref&amp;gt;|Noah Brickman}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|Once the frame is converted to an opengl texture, then it would be a very simple matter of displaying it on the screen with a textured rectangle drawn in immediate mode ... possibly with some level of transparancy, or not ...&lt;br /&gt;
&lt;br /&gt;
I'm involved in some UAV research where we are using FlightGear to render a synthetic view from the perspective of a live flying uav.  Would be really cool to super impose the live video over the top of the FlightGear synthetic view.  Or super impose an F-16 style HUD on top of the live video ... I have lots of fun ideas for someone with a fast frame grabber and a bit of time [...]&lt;br /&gt;
&lt;br /&gt;
Then do whatever bit fiddling is needed to scale/convert the raster image to an opengl texture.  Then draw this texture on a quad that is aligned correctly relative to the camera.  It might be possible to get fancy and alpha blend the edges a bit.&lt;br /&gt;
&lt;br /&gt;
Given an image and the location and orientation of the camera, it would be possible to locate world coordinates across a grid on that image.  That would allow a  quick/crude orthorectification where the image could be rubber sheeted onto the terrain.  This would take some offline processing, but you could end up building up a near real time 3d view of the world than could then be viewed from a variety of perspectives.  The offline tools could update the master images based on resolution or currency ... that's probably a phd project for someone, but many of the pieces are already in place and the results could be extremely nice and extremely useful (think managing the effort to fight a dynamic forest fire, or other emergency/disaster management, traffic monitoring, construction sites, city/county management &amp;amp; planning, etc.)  I could even imagine some distrubuted use of this so that if you have several uav's out flying over an area, they could send their imagery back to a central location to update a  master database ... then the individual operators could see near real time 3d views of places that another uav has already overflown.&lt;br /&gt;
&lt;br /&gt;
If we started building up more functionality in this area, there are a lot of different directions we could take it, all of which could be extremely cool.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg15459.html|title=Replace fg visualization with streaming video&lt;br /&gt;
Curtis Olson Fri, 25 Jan 2008 07:51:41 -0800|author=Curtis Olson |Tue, 29 Jul 2008 13:11:15 -0700}}&amp;lt;/ref&amp;gt;|Curtis Olson}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|Could we generate the texture on the fly? Based on landclass and road data? I could see a number of advantages/disadvantages here as compared to our current, generic textures:&lt;br /&gt;
* much better autogen scenery possible: many textured streets/railroads without additional scenery vertices&lt;br /&gt;
* shared models with an individual piece of ground texture&lt;br /&gt;
* get rid of sharp landclass borders&lt;br /&gt;
* possibly improved resolution&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg39692.html|title=Generating ground textures on the fly?|author=Thomas Albrecht|Mon, 11 Mar 2013 13:37:47 -0700}}&amp;lt;/ref&amp;gt;|Thomas Albrecht}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|A very interesting idea - so interesting I thought of it and discussed it with some people last year :) The summary answer is, it should be possible, it would &lt;br /&gt;
have pretty much the benefits and drawbacks you mention (especially the VRAM consumption), and it would allow nice LoD and solve some other issues. &lt;br /&gt;
Especially it avoid the nasty clipping issues we have with surface data in TerraGear, since you just paint into the texture, no need to clip all the &lt;br /&gt;
linear data.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg39692.html|title=Generating ground textures on the fly?|author=James Turner|Mon, 11 Mar 2013 13:37:47 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
What we could do is identify which hooks are needed to make this work and provide those via the Canvas system: Canvas textures can already be placed in the scenery, so there should be very little needed in terms of placement-specific attributes, and the corresponding code should be available in SimGear/FlightGear already.&lt;br /&gt;
&lt;br /&gt;
[http://fgphotoscenery.square7.ch/flightgear_photo_combined_2.8.patch The patch] required to modify FlightGear obviously already uses shaders and effects, and it's mostly about exposing additional parameters to the shaders.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Native Windows ===&lt;br /&gt;
{{Note|People interested in working on this may want to check out the following files:&lt;br /&gt;
* {{Git link|gitorious|fg/simgear|next|src/canvas/CanvasPlacement.hxx|text=CanvasPlacement Interface in SimGear}}&lt;br /&gt;
* {{Git link|gitorious|fg/flightgear|next|src/Main/Viewer/WindowBuilder.cxx|text=$FG_SRC/Viewer/WindowBuilder.?xx}}&lt;br /&gt;
* {{Git link|gitorious|fg/flightgear|next|src/Main/Viewer/WindowSystemAdapter.cxx|text=$FG_SRC/Viewer/WindowSystemAdapter.?xx}}&lt;br /&gt;
* {{Git link|gitorious|fg/flightgear|next|src/Main/Canvas/window.cxx|text=Canvas Windows Implementation}}&lt;br /&gt;
}}&lt;br /&gt;
Currently, all placements are within the main FlightGear window, however there's been talk about providing support for additional Canvas placements, such as e.g. osgviewer placements to help generalize our [[Howto:Configure camera view windows|Window Management]] routines, so that a canvas can be rendered inside a dedicated OS window:&lt;br /&gt;
&lt;br /&gt;
{{cquote|&amp;lt;nowiki&amp;gt;Support multiple views/windows: Currently the GUI can only be placed inside one view/window (see Docs/README.multiscreen) but it would be nice to be able to move windows between views.&amp;lt;/nowiki&amp;gt;&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37907.html|title=&amp;lt;nowiki&amp;gt;Switching from PUI to osgWidget&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;Thomas Geymayer&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;07-30-2012&amp;lt;/nowiki&amp;gt;}}&amp;lt;/ref&amp;gt;|&amp;lt;nowiki&amp;gt;Thomas Geymayer&amp;lt;/nowiki&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|I have just been trying out the multiple screen feature in FG. I found that the GUI camera (including the menu bar, hud and 2D panel) appears in only one of the windows. Is there any way I can make the GUI to appear in all the windows? Actually I want to be able to view the hud and 2D panel in all the windows.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg27112.html|title=&amp;lt;nowiki&amp;gt;[Flightgear-devel] Help needed with multi-screen&amp;lt;/nowiki&amp;gt;|author=Kavya Meyyappan|date=Fri, 19 Mar 2010 03:31:50 -0700}}&amp;lt;/ref&amp;gt;|Kavya Meyyappan}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|there's a limitation in Plib that forces the GUI to be drawn on one window.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg27134.html|title=&amp;lt;nowiki&amp;gt;Re: [Flightgear-devel] Help needed with multi-screen&amp;lt;/nowiki&amp;gt;|author=Tim Moore|date=Sat, 20 Mar 2010 01:42:31 -0700}}&amp;lt;/ref&amp;gt;|Tim Moore}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I think you have just summarized all the limitations of the FlightGear multi-camera/view/display system. I know that in the case of menus, hud, 2d instrument panels, there would need to be some significant code restructuring to allow these to be displayed on other windows.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg27114.html|title=&amp;lt;nowiki&amp;gt;Re: [Flightgear-devel] Help needed with multi-screen&amp;lt;/nowiki&amp;gt;|author=Curtis Olson|date=Fri, 19 Mar 2010 08:36:22 -0700}}&amp;lt;/ref&amp;gt;|Curtis Olson}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|Good thing to have!!! Just still support graphics context on different screens/displays too ...&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg17016.html|title=&amp;lt;nowiki&amp;gt;Re: [Flightgear-devel] RFC: changes to views and cameras&amp;lt;/nowiki&amp;gt;|author=Mathias Fröhlich|date=Sat, 28 Jun 2008 00:05:19 -0700}}&amp;lt;/ref&amp;gt;|Mathias Fröhlich}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|it can be solved by using multiple osg windows to contain whatever GUI solution we go with - canvas, osgWidget or PUI-port.&lt;br /&gt;
&lt;br /&gt;
Or to put it another way - the actual hard part is running the widgets in the main OpenGL window - which *is* a requirement for full-screen apps and &lt;br /&gt;
multi-monitor setups. (Some people have claimed otherwise, but I believe we need the option of 'in-window' UI for many cases).&lt;br /&gt;
&lt;br /&gt;
So, this is a desirable feature, but doesn't dictate the choice of GUI technology. And can be done as a separate step from replacing PLIB.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37875.html|title=&amp;lt;nowiki&amp;gt;Switching from PUI to osgWidget&amp;lt;/nowiki&amp;gt;|author=James Turner|date= Wed, 25 Jul 2012 02:28:42 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Placement/Element for Streaming: Computer Vision ===&lt;br /&gt;
&lt;br /&gt;
{{Note|There seem to be two main use-cases discussed by contributors: 1) The UAV guys want to view/use external live video inside FlightGear as an instrument/texture (which would require a new Canvas::Element to render an external video stream to a canvas) and 2) the computer vision (OpenCV) guys want to stream FlightGear live video itself to another application for image processing purposes - the latter would require streaming FlightGear's main window view to an external program (i.e. by using FlightGear's CameraGroup code), possibly by using a corresponding &amp;quot;virtual Placement&amp;quot; that opens a socket to provide a live stream of the FlightGear main window via background thread.}} &lt;br /&gt;
&lt;br /&gt;
People interested in doing UAV work that involves computer vision (e.g. using OpenCV, see {{Issue|924}}, [http://forum.flightgear.org/viewtopic.php?f=36&amp;amp;t=16015&amp;amp;hilit=opencv], [http://forum.flightgear.org/viewtopic.php?f=37&amp;amp;t=21192&amp;amp;p=192915&amp;amp;hilit=#p192817]) will probably also want to look into using a dedicated Canvas placement for this, in combination with adding a dedicated Canvas::Element to render scenery views to a texture using [[CompositeViewer Support]] - these two features would provide a straightforward mechanism to export a live video stream of FlightGear via a dedicated port.&lt;br /&gt;
&lt;br /&gt;
{{Note|There were several early attempts at bringing streaming capabilities to FlightGear in the pre-{{abbr|OSG|OpenSceneGraph}} days that are meanwhile unmaintained, e.g.:&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg11213.html Experimental screen streamer patch]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg12262.html New screen streamer and mpcam]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I'm new to FlightGear, and am trying to use it as an image generator for a simulator I'm developing...I've got it configured to take inputs&lt;br /&gt;
from a UDP port to fly, but I want to disable a lot of features so that all FlightGear does is draw scenery. &amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg30338.html|title=Disabling functionality|author=Drew |date=Tue, 25 Jan 2005 09:24:30 -0800}}&amp;lt;/ref&amp;gt;|Drew}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I would like to use FlightGear to generate the scene observed by a UAV's onboard camera. &lt;br /&gt;
 &lt;br /&gt;
Basically, this would translate to feeding FlightGear the FDM data and visualizing the image generated by FlightGear in another computer, across a network, using for example streaming video.&lt;br /&gt;
 &lt;br /&gt;
I suppose this is a bit of a far-fetched idea, but is there any sort of support for this (or something similar) already implemented? &amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel%40lists.sourceforge.net/msg10528.html|title=Flightgear visualization as streaming video|author=Antonio Almeida |date=Tue, 22 May 2007 10:14:46 -0700}}&amp;lt;/ref&amp;gt;|Antonio Almeida}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|I am interested in using it as a visualization tool for UAV's. I would like to replace the fg scenery with images captured from a camera onboard an aircraft. I was wondering if there is any way to import images into flightgear on the fly. The basic goal would be to show live video where available and fall over to flight gear visuals when the feed is lost(using a custom view from the camera perspective) .&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg15463.html|title=Replace fg visualization with streaming video|author=STEPHEN THISTLE  |date=Fri, 25 Jan 2008 06:32:03 -0800}}&amp;lt;/ref&amp;gt;|STEPHEN THISTLE}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I'm hooking up a lumenera Camera for a live video feed  from a UAV, so that the video gets handed to Flightgear, which then draws its HUD over the video stream. In order to do this, I need to be able to communicate with the window controls. My camera can display the video in a new window, but I want it to draw to the video screen that Flightgear is already using.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg17203.html|title=Window controls|author=cullam Bruce-Lockhart  |date=Tue,29 Jul 2008 09:23:54 -0700}}&amp;lt;/ref&amp;gt;|Bruce-Lockhart }}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I don't think there's any current way to do this.  However, I think what is needed is to link in some video capture library to do frame grabs from your video camera as quickly as possible.  Then do whatever bit fiddling is needed to scale/convert the raster image to an opengl texture.  Then draw this texture on a quad that is aligned correctly relative to the camera.  It might be possible to get fancy and alpha blend the edges a bit.&lt;br /&gt;
&lt;br /&gt;
Given an image and the location and orientation of the camera, it would be possible to locate world coordinates across a grid on that image.  That would allow a  quick/crude orthorectification where the image could be rubber sheeted onto the terrain.  This would take some offline processing, but you could end up building up a near real time 3d view of the world than could then be viewed from a variety of perspectives.  The offline tools could update the master images based on resolution or currency ... that's probably a phd project for someone, but many of the pieces are already in place and the results could be extremely nice and extremely useful (think managing the effort to fight a dynamic forest fire, or other emergency/disaster management, traffic monitoring, construction sites, city/county management &amp;amp; planning, etc.)  I could even imagine some distrubuted use of this so that if you have several uav's out flying over an area, they could send their imagery back to a central location to update a  master database ... then the individual operators could see near real time 3d views of places that another uav has already overflown.&lt;br /&gt;
&lt;br /&gt;
If we started building up more functionality in this area, there are a lot of different directions we could take it, all of which could be extremely cool.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg15459.html|title=Replace fg visualization with streaming video&lt;br /&gt;
Curtis Olson Fri, 25 Jan 2008 07:51:41 -0800|author=Curtis Olson |Tue, 29 Jul 2008 13:11:15 -0700}}&amp;lt;/ref&amp;gt;|Curtis Olson}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|Getting live video onto a texture is pretty standard stuff in the OpenSceneGraph community&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg15464.html|title=&amp;lt;nowiki&amp;gt;Replace fg visualization with streaming video&amp;lt;/nowiki&amp;gt;|author=Tim Moore|date=Fri, 25 Jan 2008 08:31:40 -0800}}&amp;lt;/ref&amp;gt;|Tim Moore}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I imagined embedding some minimal routine that talks to the camera and grabs an image frame.  Then usually you can directly map this into an opengl texture if you figure out the pixel format of your frame grab and pass the right flags to the opengl texture create call.  Then you should be able to draw this texture on top of any surface just like any other texture ... you could map it to a rectangular area of the screen, you could map it to a rotating cube, map it to the earth surface, etc. That's about as far as far as I've gone with thinking through the problem.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg17206.html|title=Window controls|author=Curtis Olson |Tue, 29 Jul 2008 13:11:15 -0700}}&amp;lt;/ref&amp;gt;|Curtis Olson}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|I want draw something in the front face of the FlightGear view, but I don't wan to recompile / modify any codes, so, if the FlightGear could give me a interface to draw something myself through DLL, that's perfect.&amp;lt;ref&amp;gt;{{cite web |url=http://forum.flightgear.org/viewtopic.php?f=6&amp;amp;t=22995|title=&amp;lt;nowiki&amp;gt;One suggestion: FlightGear wolud support plugins like this!&amp;lt;/nowiki&amp;gt;|author=CHIV|date=Thu May 08, 2014 3:03 am}}&amp;lt;/ref&amp;gt;|CHIV}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding new Placements ===&lt;br /&gt;
&lt;br /&gt;
== Projections ==&lt;br /&gt;
Also see {{Issue|550}} and http://docs.freeflightsim.org/simgear/classsimgear_1_1canvas_1_1Projection.html&lt;br /&gt;
&lt;br /&gt;
=== Adding new Projections ===&lt;br /&gt;
{{Note|Discuss base class that needs to be implemented}}&lt;br /&gt;
&lt;br /&gt;
== Event Handling ==&lt;br /&gt;
{{Note|Discuss CanvasEventManager, CanvasEvent, CanvasEventVisitor}}&lt;br /&gt;
&lt;br /&gt;
== Canvas Integration ==&lt;br /&gt;
{{Note|Discuss FGCanvasSystemAdapter}}&lt;br /&gt;
&lt;br /&gt;
==Suggested reading ==&lt;br /&gt;
* [[Howto:Create_new_subsystems|Using Property Listeners]]&lt;br /&gt;
* [http://docs.freeflightsim.org/simgear/classSGPropertyChangeListener.html SGPropertyChangeListener]&lt;br /&gt;
* [[PropertyBasedElement]]&lt;br /&gt;
* [[Howto:Use Property Tree Objects]]&lt;br /&gt;
* [[Programming_resources#OSG.2FOpenSceneGraph_related|OSG Programming]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=New_to_FlightGear&amp;diff=71953</id>
		<title>New to FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=New_to_FlightGear&amp;diff=71953"/>
		<updated>2014-05-27T20:13:03Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Getting FlightGear */ Mac too! plus a few typos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Getting started ==&lt;br /&gt;
=== Hardware requirements ===&lt;br /&gt;
For FlightGear to run smoothly, it requires a video card with OpenGL drivers. OpenGL 2.0 or higher is required for FlightGear 2.0 and later. Most modern PCs support OpenGL, but if you are having trouble with slow frame-rates, see [[Fr/Hardware Recommendations|Hardware Recommendations]] for more information.&lt;br /&gt;
&lt;br /&gt;
Many laptops with insufficient 3D hardware acceleration capabilities are known to have issues with running FlightGear. Since laptops are smaller, the graphics card(s) on them are usually lower-end. See [[notebooks known to run FlightGear]] for reviews of several laptop systems.&lt;br /&gt;
&lt;br /&gt;
=== Getting FlightGear ===&lt;br /&gt;
You may download the latest files from [http://www.flightgear.org/download/ FlightGear Downloads] page. Choose the source or binary files appropriate for your particular system. Most Linux users will find that most distributions have a packaged version of FlightGear (the package name could be fgfs or flightgear.)&lt;br /&gt;
&lt;br /&gt;
Depending on your technical expertise you may choose the [[Git]] development version of FlightGear, which typically has more features and can be required by some of the latest developmental aircraft, but can be unstable and is more complicated to acquire and install. In general, the development version is not advised to the average user, but if you're willing to do some testing there's a nightly build for Windows or Mac available for download at the [[FlightGear Build Server]].&lt;br /&gt;
&lt;br /&gt;
You may also order FlightGear on a set of DVDs, available at [http://www.flightgear.org/dvd/].&lt;br /&gt;
&lt;br /&gt;
=== Installing on Windows ===&lt;br /&gt;
After installing FlightGear on Windows a dialog box appears to define file locations. This is [[FlightGear Launch Control]], also known as FGRun.&lt;br /&gt;
&lt;br /&gt;
Apply the following settings:&lt;br /&gt;
* '''Executable''': the full path to the FlightGear program (&amp;lt;tt&amp;gt;fgfs.exe&amp;lt;/tt&amp;gt;, usually &amp;lt;tt&amp;gt;C:/Program Files/FlightGear/bin/win32/fgfs.exe&amp;lt;/tt&amp;gt; ). One can choose it directly using the file selection dialog that pops up when the folder button is hit.&lt;br /&gt;
* '''[[$FG ROOT|FG_ROOT]]''': the full path to the FlightGear base package (&amp;lt;tt&amp;gt;data/&amp;lt;/tt&amp;gt; directory, usually &amp;lt;tt&amp;gt;C:/Program Files/FlightGear/data&amp;lt;/tt&amp;gt;). If this path is wrong, no [[aircraft]] would be displayed and FlightGear won't run.&lt;br /&gt;
&lt;br /&gt;
Once you have defined these default settings, you can press &amp;lt;tt&amp;gt;Next&amp;lt;/tt&amp;gt; to select an airport, aircraft and edit additional settings.&lt;br /&gt;
&lt;br /&gt;
=== Installing on Mac OS X ===&lt;br /&gt;
Installing [[FlightGear Mac OS X|FlightGear on Mac OS X]] is very simple. Just drag and drop the FlightGear icon to the &amp;lt;tt&amp;gt;/Applications&amp;lt;/tt&amp;gt; folder. That's it. &lt;br /&gt;
&lt;br /&gt;
The first time you launch FlightGear, its icon on the Dock bounces for several seconds while loading aircraft and airport info. When the GUI launcher appears, select an aircraft and and airport by clicking the &amp;quot;Gear&amp;quot; buttons at the right of the names. Pressing &amp;quot;Start flight&amp;quot; will launch the simulator. You can configure more options using the GUI launcher. see the [http://macflightgear.sourceforge.net/home/documents/users-guide/ Users Guide] for more details.&lt;br /&gt;
&lt;br /&gt;
If you'd like to launch FlightGear using command-line, launch &amp;lt;tt&amp;gt;/Applications/Utilities/Terminal.app&amp;lt;/tt&amp;gt; and type the following.&lt;br /&gt;
&lt;br /&gt;
 cd /Applications/FlightGear.app/Contents/Resources&lt;br /&gt;
 ./fgfs --options..... &lt;br /&gt;
&lt;br /&gt;
The [[$FG ROOT]] and [[$FG SCENERY]] are not set on Mac OS X. If you want to specify these variables yourself for command-line use, run the followings on Terminal.app:&lt;br /&gt;
&lt;br /&gt;
 FG_ROOT=/Applications/FlightGear.app/Contents/Resources/data&lt;br /&gt;
 FG_SCENERY=[[$FG_ROOT]]/Scenery&lt;br /&gt;
&lt;br /&gt;
After launching the GUI launcher, you will have the alias to [[$FG ROOT]] at &amp;lt;tt&amp;gt;$HOME/Documents/Flightgear/&amp;lt;version&amp;gt;&amp;lt;/tt&amp;gt; so you can browse the data folder using Finder.&lt;br /&gt;
&lt;br /&gt;
Note: Once you have installed FlightGear, mac users can locate their [[$FG_ROOT]] folder by opening their applications folder in Finder, right clicking on FlightGear, and clicking &amp;quot;Show Package Contents&amp;quot;. This will take you inside the FlightGear folder. You are now able to access all files including Data/Aircraft for [[Howto: Install aircraft#Macintosh OS X|installing new aircraft]].&lt;br /&gt;
&lt;br /&gt;
=== Configuring OpenGL ===&lt;br /&gt;
FlightGear runs best with current [[OpenGL]] video drivers. If you are having trouble running FlightGear smoothly, see [[Graphics drivers configuration]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Getting scenery ===&lt;br /&gt;
A limited set of [[scenery]] comes installed with FlightGear, which consists of the area surrounding [[San Francisco International Airport]] (KSFO).&lt;br /&gt;
&lt;br /&gt;
In FlightGear, scenery is generally stored in you [[$FG_ROOT]] directory, and is divided into three kinds of data:&lt;br /&gt;
* '''Airports''' holds airport data, like runway usage and parking spots.&lt;br /&gt;
* '''Objects''' are the buildings, bridges and radio towers, etc. that represent three-dimensional structures.&lt;br /&gt;
* '''Terrain''' represents the contours, elevations and type of ground you fly/taxi over.&lt;br /&gt;
&lt;br /&gt;
The current way of &amp;quot;installing&amp;quot; new scenery is using [[TerraSync]], which will automatically download and update any place you visit - even on the fly! However, some might have problems with that, so you can also manually download and install new scenery parts, either official, the [[World Scenery]], or custom.&lt;br /&gt;
&lt;br /&gt;
The official scenery is available at [http://www.flightgear.org/download/scenery/ the scenery download section] of the FlightGear website, and can be installed following [[Howto: Install scenery]]. You may obtain additional and more up to date scenery objects as they become available through the [http://scenemodels.flightgear.org/ FlightGear Scenery Database].&lt;br /&gt;
&lt;br /&gt;
=== Getting aircraft ===&lt;br /&gt;
{{Main article|Howto: Install aircraft}}&lt;br /&gt;
To download additional [[aircraft]] for FlightGear individually, go to the FlightGear website and navigate to the [http://www.flightgear.org/download/ download page], then choose the aircraft download link that fits your FlightGear version.&lt;br /&gt;
&lt;br /&gt;
Once the aircraft package has downloaded, decompress and extract the archived files onto your computer. You may extract to a temporary directory and move them, or extract directly into the Aircraft/ directory in FlightGear. This is typically &amp;lt;tt&amp;gt;[[$FG ROOT]]/Aircraft&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Starting FlightGear ===&lt;br /&gt;
Many users choose to start FlightGear from the command line (&amp;quot;console&amp;quot; or &amp;quot;shell&amp;quot; as it is known to Unix users). Alternatively some use graphical interfaces such as [[FlightGear Launch Control|Fgrun]] (FlightGear Launch Control). &lt;br /&gt;
&lt;br /&gt;
To start FlightGear type on the command line:&lt;br /&gt;
&lt;br /&gt;
 fgfs&lt;br /&gt;
&lt;br /&gt;
and hit enter. This will start FlightGear.&lt;br /&gt;
&lt;br /&gt;
If FlightGear fails to start, it is likely the compiled FlightGear binary software is not in your path. If you know Unix, you may add the location of the binary to your path and try starting again. Otherwise, you may find the location of the 'fgfs' binary and enter an absolute path to it like&lt;br /&gt;
&lt;br /&gt;
 /usr/games/fgfs&lt;br /&gt;
&lt;br /&gt;
The location depends on your particular system and choices you made during compile and installation.&lt;br /&gt;
&lt;br /&gt;
It is important to understand when not using a graphical interface to start FlightGear, your interaction will be entirely from the command line. To see available aircraft, you specify an option on the command line. To specify an aircraft, an airport, multiplayer server, etc. you add an option to the command line when starting FlightGear. Please consult the list of [[Command Line Parameters]]. The parameters are also useful to those starting FlightGear from [[FlightGear Launch Control]] graphical interface, as it allows you to specify parameters.&lt;br /&gt;
&lt;br /&gt;
=== Displaying available aircraft ===&lt;br /&gt;
From the command line:&lt;br /&gt;
&lt;br /&gt;
 fgfs --show-aircraft&lt;br /&gt;
&lt;br /&gt;
displays a list of available (installed) aircraft.&lt;br /&gt;
&lt;br /&gt;
=== Choosing an aircraft ===&lt;br /&gt;
From the command line:&lt;br /&gt;
&lt;br /&gt;
 fgfs --aircraft=foo&lt;br /&gt;
&lt;br /&gt;
where foo is the name of the aircraft's &amp;lt;tt&amp;gt;*-set.xml&amp;lt;/tt&amp;gt; file (eg. for the c172p this is &amp;lt;tt&amp;gt;&amp;lt;u&amp;gt;c172p&amp;lt;/u&amp;gt;-set.xml&amp;lt;/tt&amp;gt;, so the command is &amp;lt;tt&amp;gt;--aircraft=c172p&amp;lt;/tt&amp;gt;). See also [[Command Line Parameters]]. The following commands gives a list of available aircraft:&lt;br /&gt;
&lt;br /&gt;
 fgfs --show-aircraft&lt;br /&gt;
&lt;br /&gt;
=== Online multiplayer flying ===&lt;br /&gt;
{{Main article|Howto: Multiplayer}}&lt;br /&gt;
&lt;br /&gt;
=== Using the keyboard and/or mouse ===&lt;br /&gt;
Users with limited access to a [[joystick]] or other controllers sometimes use the keyboard or mouse to control their aircraft. Using the keyboard to fly can be difficult and the mouse is recommended over the keyboard for flying. Adjustments (like throttle, instruments etc.) may be made with the keyboard.&lt;br /&gt;
&lt;br /&gt;
To get help with keyboard commands, with FlightGear running, go to the Help [[menu]], look under Basic Keys (for simulator related commands) and Common Aircraft Keys (for commands universal to all aircraft) and Aircraft Help for key commands specific to your aircraft. A list displaying what each key does will display.&lt;br /&gt;
&lt;br /&gt;
Coming from an other simulator? Check [[key commands compared to other simulators]] for an overview of the difference between the key commands of that sim and FlightGear.&lt;br /&gt;
&lt;br /&gt;
To use the mouse to fly the aircraft, right click (the cursor should change to a cross) and move the mouse to direct the aircraft. Right click again to look around (cursor should show a two sided arrow), click again to return to normal mode.&lt;br /&gt;
&lt;br /&gt;
=== First time in the cockpit ===&lt;br /&gt;
Finding your way around the cockpit can be daunting the first time.&lt;br /&gt;
&lt;br /&gt;
Where is the 'virtual cockpit?' Not all FlightGear aircraft come with an interior, including a virtual cockpit. (Due to FlightGear being used by various research projects, some aircraft may not even come with an exterior model. Remember, FlightGear is very flexible.) A 2D panel may display over the 3d cockpit if one exists. You may turn this off using the View menu. Otherwise, you should be sitting in the virtual cockpit when FlightGear starts, as long as the Cockpit View is selected.&lt;br /&gt;
&lt;br /&gt;
You may find it difficult to read some of the displays, dials and gauges on the instrument panel. Use the Zoom keys to zoom in on an instrument. The 'x' and Shift-X keys control eyepoint zoom in the Cockpit View. Use the joystick hat (or other controller assigned to this function) to pan the eyepoint to the instrument you wish to read. Then zoom in.&lt;br /&gt;
&lt;br /&gt;
Alternate Method: Click the right mouse button until you get a cursor with two arrows (like this &amp;lt;=&amp;gt;). You can now move your view around the cockpit. Press 'x' and Shift-X to zoom in and out.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Some functions, such as starter or magneto, may be difficult to use or lack &amp;quot;hotspots&amp;quot; to control with your mouse. Especially when flying an aircraft model that is still undergoing development. In this case, look for equivalent controls on a 2D panel or resort to the keyboard. The keyboard controls always work according to the assignments listed on the Help Menu (unless reassigned by an aircraft or configuration). Go to the main window menu, click Help, then click Basic Keys or Common Aircraft Keys.&lt;br /&gt;
&lt;br /&gt;
One of the first steps I take on entering an unfamiliar cockpit is to press Ctrl-C to highlight all the &amp;quot;hotspots&amp;quot; on the 3d cockpit instrument panel. This enables you to easily see where to place the mouse to operate an instrument's controls, buttons, knobs, etc.&lt;br /&gt;
&lt;br /&gt;
Many aircraft offer a help menu specific to that aircraft on the Aircraft Help menu (go to Help, then Aircraft Help.&lt;br /&gt;
&lt;br /&gt;
== Making your first flight ==&lt;br /&gt;
One of the most frequent questions novice pilots ask about any flight sim, but more so to FlightGear, is &amp;quot;why is my aircraft turning left all the time?&amp;quot; Although it could be due to wind gusts crossing the runway, it is more likely due to the increased realism FlightGear provides. In a certain other flight simulator, some settings are turned down to make the aircraft easier to fly. This reduces effects such as propeller torque and p-factor, which may be the cause of the tendency to turn to the left (to figure out which effect, you may read more in [[Understanding Propeller Torque and P-Factor]]).&lt;br /&gt;
&lt;br /&gt;
Despite marketing slogans to the contrary, some flight simulators are aimed at a casual game player market, and ship with their &amp;quot;realism&amp;quot; turned down. The realism is always turned up in FlightGear.&lt;br /&gt;
&lt;br /&gt;
FlightGear offers a great deal of realism, which may be confusing to first time pilots.&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;Left Turning Syndrome&amp;quot; for the previously mentioned reasons.&lt;br /&gt;
* Compass Turning Error: A compass, when subjected to the forces of flight, tends to turn in the opposite direction for a brief period before settling on the correct heading. This is not a malfunction.&lt;br /&gt;
* The Vertical Speed Indicator is also subject to error.&lt;br /&gt;
* The Horizontal Situation Indicator is driven by a gyroscope (that is why it's sometimes called a Directional Gyroscope), which is subject to a phenomenon called gyro drift. For a number of reasons, the gyro will drift from its current heading and must be periodically (about every 15 minutes) calibrated to agree with the magnetic compass heading.&lt;br /&gt;
&lt;br /&gt;
Many forces act on an aircraft in flight as well as on the instruments and systems used for control and navigation, and may be counter-intuitive. Pilots must learn to recognize these phenomena and compensate for their effects. FlightGear models instrument errors that exist in the real world.&lt;br /&gt;
&lt;br /&gt;
=== Flying using navigational aids and the autopilot ===&lt;br /&gt;
To make this very clear for new users: Some aircraft require you to use the [[autopilot]] available from the Autopilot menu, which is the original FlightGear autopilot. This is a '''generic''' autopilot and as such, many aircraft come with their own '''specific''' autopilot, frequently a model of the real life one. '''For aircraft that provide their own autopilot in the cockpit, you must use the autopilot controls available in the virtual cockpit'''. This means clicking on the instrument panel in the virtual cockpit. The Autopilot menu will be grayed out and unavailable when the aircraft supplies its own autopilot (generally).&lt;br /&gt;
&lt;br /&gt;
FlightGear, as of version 0.9.9, comes with a &amp;quot;built-in&amp;quot; autopilot. The Autopilot dialog accessible from the FlightGear toolbar in the main FlightGear window does not work with all aircraft. It only works with aircraft that either&lt;br /&gt;
* do not specify an autopilot&lt;br /&gt;
* use the default autopilot. When an aircraft does not specify an autopilot, the default is used.&lt;br /&gt;
&lt;br /&gt;
For aircraft that supply their own autopilot, you must use the autopilot controls in the 2D or virtual cockpit. The Cessna comes with a KAP140 autopilot in its virtual cockpit. You cannot use the Autopilot dialog with this aircraft. It has no effect. You must use the autopilot device in the panel.&lt;br /&gt;
&lt;br /&gt;
For help with navigation see [[Understanding Navigation]].&lt;br /&gt;
&lt;br /&gt;
=== Airports and navigation aids ===&lt;br /&gt;
When you first start FlightGear, whether from the command line or the graphical interface, you may wonder how to determine what airports are available. FGRun displays a list of airports, but you will not see details such as tower or [[ILS]] frequencies. You will not find a map showing [[VOR]]s and their frequencies. Short of finding an actual sectional map for the area you wish to fly, what can you do?&lt;br /&gt;
&lt;br /&gt;
[http://maps.google.com Google Maps] and the [[MPMap|FlightGear Online Map for multiplayers]] are both good resources as well as the FlightGear [http://fgfs.i-net.hu/modules/fgplanner/ Community Flight Planner].&lt;br /&gt;
&lt;br /&gt;
== Getting help ==&lt;br /&gt;
Besides this wiki, there are more places that can be visited to obtain information or request help:&lt;br /&gt;
* Documents bundled with the release package.&lt;br /&gt;
* [http://forum.flightgear.org FlightGear Forum]&lt;br /&gt;
* [[FlightGear IRC channel]], the quickest way to get help.&lt;br /&gt;
* [[Malinglists|FlightGear users mailing list]], biggest chance to get in contact with developers.&lt;br /&gt;
&lt;br /&gt;
== Getting more detailed information ==&lt;br /&gt;
This page is designed to give the user the essential things they need to know about using FG for the first time.&lt;br /&gt;
&lt;br /&gt;
You now know enough to get started with FlightGear. To learn more, you may wish to start at the main page of this wiki and read the more detailed Getting Started section, or Using FlightGear section or study the Flying Resources to learn more about flight instruments and how to navigate and fly your aircraft.&lt;br /&gt;
&lt;br /&gt;
Also, note that those using the Git version of FlightGear may choose to update their aircraft files through the Git system.&lt;br /&gt;
&lt;br /&gt;
The following are some issues raised by new users of FlightGear. More detailed troubleshooting and answers can be found in [[Troubleshooting Problems]] and the [[FAQ]].&lt;br /&gt;
&lt;br /&gt;
=== I do not want to compile FlightGear, what can I do? ===&lt;br /&gt;
[http://www.flightgear.org/Downloads/ Our website] offers precompiled binaries for download and install on a variety of systems. Current platforms are Windows, Linux, Solaris, SGI, Mac OSX and FreeBSD. These are offered as a convienence and availablility may vary at times.&lt;br /&gt;
&lt;br /&gt;
Note: FlightGear is highly configurable through editable [[XML]] files. You are free, and encouraged to, make changes to aircraft flight models and any other feature you wish to change for your personal satisfaction or to share with other FlightGear users. The flight model is not defined in a binary file. It is easy to modify (given enough knowledge). Although the install is binary, most of FlightGear's system is open to configuration through XML files and [[NASAL scripting]].&lt;br /&gt;
&lt;br /&gt;
=== Does FlightGear come with a printed manual? ===&lt;br /&gt;
You are invited to read the [[FlightGear Manual]] online as HTML or download it as PDF for viewing with Acrobar Reader or printing. It's not always up to date with bleeding-edge developments but provides a good start for beginners and it's a ''must read'' if you have no or little idea of how to fly.&lt;br /&gt;
&lt;br /&gt;
== How you can help ==&lt;br /&gt;
{{Main article|Volunteer}}&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
* [[Building Flightgear|Build]] the latest Git code or download snapshots (link)&lt;br /&gt;
* [http://flightgear-bugs.googlecode.com File bug reports]&lt;br /&gt;
&lt;br /&gt;
=== Debugging &amp;amp; Profiling ===&lt;br /&gt;
* Running FlightGear via valgrind to track down memory leaks&lt;br /&gt;
&lt;br /&gt;
=== Support ===&lt;br /&gt;
* Help new users with downloading, compiling, installing and running FlightGear (http://forum.flightgear.org or on IRC)&lt;br /&gt;
* Provide Ideas &amp;amp; Suggestions, see: [[Feature Requests / Proposals / Ideas]]&lt;br /&gt;
* Help clean up this wiki&lt;br /&gt;
* Help provide new contents for missing wiki pages&lt;br /&gt;
&lt;br /&gt;
=== Development ===&lt;br /&gt;
* Writing documentation! Everyone is welcome to contribute to &amp;quot;The Manual&amp;quot;; having at least a little experience with LaTeX makes the task easier. Please contact the authors of The Manual if you would like to add corrections or whole chapters, you may also simply use this wiki to contribute fixes, modifications and new contents.&lt;br /&gt;
* C/C++ Coding:&lt;br /&gt;
** provide source code cleanups (i.e. help in the process of migrating over to a primarily smart pointer-based memory management approach using SGSharedPtr)&lt;br /&gt;
** provide bug fixes [[Bugs]]&lt;br /&gt;
** provide enhanced features [[Feature Requests / Proposals / Ideas]]&lt;br /&gt;
** provide new features &lt;br /&gt;
** get involved in any of the other FlightGear-affiliated projects &lt;br /&gt;
* Aircraft development (3D modelling, textures, FDMs, scripting)&lt;br /&gt;
* Scenery development&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear]]&lt;br /&gt;
&lt;br /&gt;
[[de:Neu bei FlightGear]]&lt;br /&gt;
[[Nl:Nieuw bij FlightGear]]&lt;br /&gt;
[[es:Nuevo para FlightGear]]&lt;br /&gt;
[[fr:Nouveau sur flightgear]]&lt;br /&gt;
[[Pt:Novo no FlightGear]]&lt;br /&gt;
[[zh:FlightGear新手]]&lt;br /&gt;
[[ja:FlightGear入門]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71952</id>
		<title>Nasal Operators</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71952"/>
		<updated>2014-05-27T20:09:55Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: mm.. have to escape everything&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
Nasal has support for various operators, both mathematical (add, subtract, multiply, and divide) and programming-specific (assignment, concatenation, control-flow, etc.). Most operators are in [http://en.wikipedia.org/wiki/Infix_notation infix notation] – that is, the operator is in the middle of its operands as in &amp;quot;{{code|3 + 5}}&amp;quot;. As mentioned, Nasal supports the four basic math operators as {{code|+}}, {{code|-}}, {{code|*}}, and {{code|/}}  (power is ''not'' available as {{code|**}} (Python) or {{code|^}} (Visual basic), but rather is done in the '''math''' namespace as: {{code|math.pow(}}''base'', ''exponent''{{code|)}}). For other math ones, assignment is just a single equals sign ({{code|{{=}}}}, as in {{code|var pi {{=}} 3.14}}) and equality comparison is double-equals ({{code|{{=}}{{=}}}}, as in {{code|3 {{=}}{{=}} 3}}). Relative comparisons such as less-than ({{code|&amp;amp;lt;}}), greater-than ({{code|&amp;amp;gt;}}), less-than-or-equal-to ({{code|&amp;amp;lt;{{=}}}}), and greater-than-or-equal-to ({{code|&amp;amp;gt;{{=}}}}) also can be used (see [[Howto:Add a new binary operator to Nasal]] for an example of adding another comparison operator: the Perl &amp;quot;spaceship&amp;quot; operator, {{code|&amp;amp;lt;{{=}}&amp;amp;gt;}}). When operating on two variables using these operators (excepting assignment), Nasal uses a notion of &amp;quot;scalars&amp;quot; if applicable. Instead of the mathematical notion of scalars as non-vectors, a scalar in programming is defined as a number ''or'' numeric string – essentially duplicity of datatypes available to represent a number. This allows a string to also represent a number, which makes, e.g., parsing a number out of a file or string very easy, since the programmer doesn't have to think about the conversion. According to Andy (the creator of Nasal):&lt;br /&gt;
&lt;br /&gt;
{{cquote| Like perl, and unlike everything else, nasal combines numbers and strings into a single &amp;quot;scalar&amp;quot; datatype. No conversion needs to happen in user code, which simplifies common string handling tasks. &amp;lt;ref&amp;gt;{{cite web |url=http://plausible.org/nasal/doc.html |title= Nasal – Not another scripting language.|author=Andy Ross|date=2007}}&amp;lt;/ref&amp;gt;|Andy Ross}}&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This presents a problem when you need to concatenate two or more numeric strings (which is often done with the same operator as addition). If the {{code|+}} operator sees two numeric strings, it will add them as numbers, thus {{code|&amp;quot;67&amp;quot; + &amp;quot;75&amp;quot; {{=}}{{=}} 142}} (resulting in a number), when one might want the string &amp;quot;35&amp;quot;. Andy had to introduce a new operator to do concatenation, like the {{code|.}} operator in PHP, and that was the tilde ({{code|~}}). Here's some examples showing the difference:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;88&amp;quot; + &amp;quot;88&amp;quot; == 176; # number&lt;br /&gt;
88 + &amp;quot;88&amp;quot; == &amp;quot;88&amp;quot; + 88; # same&lt;br /&gt;
&amp;quot;88&amp;quot; ~ &amp;quot;88&amp;quot; == &amp;quot;8888&amp;quot;; # string&lt;br /&gt;
88 ~ 88 == &amp;quot;8888&amp;quot;; # string as well&lt;br /&gt;
&amp;quot;88&amp;quot; ~ 88 == 88 ~ &amp;quot;88&amp;quot;; # same&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Readers familiar with C/C++ will be familiar with the &amp;quot;ternary&amp;quot; operator for control-flow within an expression:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# (condition) ? condition_true_expr1 : condition_false_expr2&lt;br /&gt;
x = reverse ? -x : x; # if (reverse) x = -x else x = x&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This is an expression that evaluates the first expression if the condition is true, or if it is false it evaluates the second expression. In most languages, this is an alternative to the if statement, which cannot be used as a value since it is a statement (in Nasal an if/else block is actually an expression, with the else value defaulting to nil if there is no else, so it is possible but rather ugly). The Python equivalent of the ternary-operator is: {{code|expr1 if (condition) else expr2}}.&lt;br /&gt;
&lt;br /&gt;
Nasal also includes the boolean [http://en.wikipedia.org/wiki/Short-circuit_evaluation short-circuit operators] &amp;quot;{{code|or}}&amp;quot; and &amp;quot;{{code|and}}&amp;quot; as keywords not symbols (not {{code|{{!}}{{!}}}} and {{code|&amp;amp;&amp;amp;}}), like in Python. Unary negation is still {{code|!}} like C/C++ (Python, however, does it as &amp;quot;{{code|not}}&amp;quot;). One of the uses for these is as a reduction of if statements:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1); # if (condition) setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)&lt;br /&gt;
condition or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1); # if (!condition) setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1) -- negated case of above&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! if{}else{} does ''not'' (quite) work in this way:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;quot;{{code|or}}&amp;quot; is of higher precedence than &amp;quot;{{code|and}}&amp;quot;, so that is equivalent to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
(condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Doesn't it seem silly to be including the return of {{code|setprop()}} in the value of the left expression, which then can influence the execution of the second piece of code? In particular:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hash = {};&lt;br /&gt;
!contains(hash, &amp;quot;loopid&amp;quot;) and hash.loopid = 0 or hash.loopid += 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Which evaluates like this:&lt;br /&gt;
# hash is empty, so contains(hash, &amp;quot;loopid&amp;quot;) is false, and !contains(...) is thus true, so&lt;br /&gt;
# the right-hand side of {{code|and}} is tried, which is assignment to 0, and since the value of assignment is the right-hand side, it produces 0 aka false.&lt;br /&gt;
# since the result of false and false is false (which is the left side of the {{code|or}}), the right side of the {{code|or}} is tried (!) as per short-circuit rules.&lt;br /&gt;
# that means hash.loopid += 1 is evaluated – wait, didn't we want to ''not'' evaluate this?&lt;br /&gt;
&lt;br /&gt;
This counter-example proves that using &amp;quot;{{code|... and ... or ...}}&amp;quot; isn't quite the same thing as using &amp;quot;{{code|if (...) ... else ...}}&amp;quot; expression (which is better done using the ternary operator, &amp;quot;{{code|... ? ... : ...}}), which can be a dangerous bug, so the rule is: '''don't use this'''.&lt;br /&gt;
&lt;br /&gt;
== Slicing and indexing ==&lt;br /&gt;
{{Note|As of 27 May 2014, the syntax {{code|expr[]}} is no longer valid and considered an error. It is neither a slice nor an index expression, although it utilized postfix brackets.}}&lt;br /&gt;
In Nasal, vectors can be sliced (i.e. a new vector is constructed from indexes of an existing vector) and strings, hashes, and vectors can be indexed/subscripted. For an overview of slicing see [[Nasal Variables#Vector slicing|vector slicing]].&lt;br /&gt;
&lt;br /&gt;
Indexing works in different ways for the different types. For strings indexing returns a value equal to the value of the character at the position. For hashes it looks up the key in the hash directly, ignoring the parents vector, and returns nil if it is not found; this treats numbers and strings as different types of keys. For vectors, the value at the index of the array is retrieved, if it is valid. Some examples:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var vec = [0,1,2,3];&lt;br /&gt;
vec[0] == 0; vec[1] == 1;&lt;br /&gt;
vec[-1] == 3; # last element&lt;br /&gt;
vec[-2] == 2; # next-from-last element&lt;br /&gt;
&lt;br /&gt;
var hash = {&lt;br /&gt;
    -1: 0,&lt;br /&gt;
    &amp;quot;-1&amp;quot;: 1,&lt;br /&gt;
    hello: &amp;quot;hi&amp;quot;,&lt;br /&gt;
    parents: [{ find_me_here: 42 }]&lt;br /&gt;
};&lt;br /&gt;
hash[-1] == 0; # look up the number -1 in the hash&lt;br /&gt;
hash[&amp;quot;-1&amp;quot;] == 1; # look up the string (!) &amp;quot;-1&amp;quot; in the hash&lt;br /&gt;
hash[-1~&amp;quot;&amp;quot;] == 1; # same thing -- makes a string&lt;br /&gt;
hash.hello == &amp;quot;hi&amp;quot;; # find the member hello in the hash&lt;br /&gt;
hash[&amp;quot;hello&amp;quot;] == &amp;quot;hi&amp;quot;; # approximately the same, but using an index expression&lt;br /&gt;
hash.find_me_here == 42; # find the member find_me_here in the hash, or actually its parent&lt;br /&gt;
hash[&amp;quot;find_me_here&amp;quot;] == nil; # but it cannot be found with an index expression, because its parent isn't searched&lt;br /&gt;
hash.parents[0][&amp;quot;find_me_here&amp;quot;] == 42; # but we can always look for the specific parent's member&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Some insights on the workings of various common operations.&lt;br /&gt;
&lt;br /&gt;
=== Equality ===&lt;br /&gt;
&lt;br /&gt;
Here are the rules for checking equality:&lt;br /&gt;
* If both are scalars:&lt;br /&gt;
** If both are numeric: check if they are numerically equal (converting to numbers first).&lt;br /&gt;
** Else: check if they are equal as strings.&lt;br /&gt;
* Else compare id's (items only equal themselves, e.g. {{code|nil {{=}}{{=}} nil}} while {{code|[] !{{=}} []}} because they are different vectors with different id's).&lt;br /&gt;
&lt;br /&gt;
=== Boolean evaluation ===&lt;br /&gt;
&lt;br /&gt;
Rules for checking if a value is &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot;:&lt;br /&gt;
* If nil: return false&lt;br /&gt;
* If numeric:&lt;br /&gt;
** If 0: return false&lt;br /&gt;
** Else: return true&lt;br /&gt;
* Else: error &amp;quot;non-scalar in boolean context&amp;quot; (applies to hashes, functions, vectors, and ghosts)&lt;br /&gt;
&lt;br /&gt;
== Table ==&lt;br /&gt;
Here's a summary of operators, in no particular order:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symbol !! Operates on... !! Evaluates to...&lt;br /&gt;
|-&lt;br /&gt;
| {{code|+}} and {{code|-}} and {{code|/}} and {{code|*}} || Numeric scalars || A number&lt;br /&gt;
|-&lt;br /&gt;
| {{code|~}} || Scalars || A string&lt;br /&gt;
|-&lt;br /&gt;
| {{code|?:}} || Three &amp;quot;simple&amp;quot; expressions: condition, expr1, and expr2 || expr1 if the condition is true, else expr2&lt;br /&gt;
|-&lt;br /&gt;
| {{code|or}} || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''true''', else the second&lt;br /&gt;
|-&lt;br /&gt;
| {{code|and}} || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''false''', else the second&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Code&amp;diff=71951</id>
		<title>Template:Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Code&amp;diff=71951"/>
		<updated>2014-05-27T20:03:12Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tt&amp;gt;{{{1}}}&amp;lt;/tt&amp;gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Goal ==&lt;br /&gt;
Provide a unified way to embed code inline into a paragraph and investigate possible styling.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt;/nowiki&amp;gt;'''code'''&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;SHORT CODE EXPR&amp;lt;nowiki&amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;{{code|&amp;quot;a&amp;quot; + &amp;quot;b&amp;quot;}}&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;{{code|&amp;quot;a&amp;quot; + &amp;quot;b&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Related templates ==&lt;br /&gt;
* {{tl|i18n month}}&lt;br /&gt;
* {{tl|time}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Formatting templates]]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71950</id>
		<title>Nasal Operators</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71950"/>
		<updated>2014-05-27T20:01:33Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: try and use Template:code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
Nasal has support for various operators, both mathematical (add, subtract, multiply, and divide) and programming-specific (assignment, concatenation, control-flow, etc.). Most operators are in [http://en.wikipedia.org/wiki/Infix_notation infix notation] – that is, the operator is in the middle of its operands as in &amp;quot;{{code|3 + 5}}&amp;quot;. As mentioned, Nasal supports the four basic math operators as {{code|+}}, {{code|-}}, {{code|*}}, and {{code|/}}  (power is ''not'' available as {{code|**}} (Python) or {{code|^}} (Visual basic), but rather is done in the '''math''' namespace as: {{code|math.pow(}}''base'', ''exponent''{{code|)}}). For other math ones, assignment is just a single equals sign ({{code|=}}, as in {{code|var pi = 3.14}}) and equality comparison is double-equals ({{code|==}}, as in {{code|3 == 3}}). Relative comparisons such as less-than ({{code|&amp;amp;lt;}}), greater-than ({{code|&amp;amp;gt;}}), less-than-or-equal-to ({{code|&amp;amp;lt;=}}), and greater-than-or-equal-to ({{code|&amp;amp;gt;=}}) also can be used (see [[Howto:Add a new binary operator to Nasal]] for an example of adding another comparison operator: the Perl &amp;quot;spaceship&amp;quot; operator, {{code|&amp;lt;=&amp;gt;}}). When operating on two variables using these operators (excepting assignment), Nasal uses a notion of &amp;quot;scalars&amp;quot; if applicable. Instead of the mathematical notion of scalars as non-vectors, a scalar in programming is defined as a number ''or'' numeric string – essentially duplicity of datatypes available to represent a number. This allows a string to also represent a number, which makes, e.g., parsing a number out of a file or string very easy, since the programmer doesn't have to think about the conversion. According to Andy (the creator of Nasal):&lt;br /&gt;
&lt;br /&gt;
{{cquote| Like perl, and unlike everything else, nasal combines numbers and strings into a single &amp;quot;scalar&amp;quot; datatype. No conversion needs to happen in user code, which simplifies common string handling tasks. &amp;lt;ref&amp;gt;{{cite web |url=http://plausible.org/nasal/doc.html |title= Nasal – Not another scripting language.|author=Andy Ross|date=2007}}&amp;lt;/ref&amp;gt;|Andy Ross}}&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This presents a problem when you need to concatenate two or more numeric strings (which is often done with the same operator as addition). If the {{code|+}} operator sees two numeric strings, it will add them as numbers, thus {{code|&amp;quot;67&amp;quot; + &amp;quot;75&amp;quot; == 142}} (resulting in a number), when one might want the string &amp;quot;35&amp;quot;. Andy had to introduce a new operator to do concatenation, like the {{code|.}} operator in PHP, and that was the tilde ({{code|~}}). Here's some examples showing the difference:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;88&amp;quot; + &amp;quot;88&amp;quot; == 176; # number&lt;br /&gt;
88 + &amp;quot;88&amp;quot; == &amp;quot;88&amp;quot; + 88; # same&lt;br /&gt;
&amp;quot;88&amp;quot; ~ &amp;quot;88&amp;quot; == &amp;quot;8888&amp;quot;; # string&lt;br /&gt;
88 ~ 88 == &amp;quot;8888&amp;quot;; # string as well&lt;br /&gt;
&amp;quot;88&amp;quot; ~ 88 == 88 ~ &amp;quot;88&amp;quot;; # same&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Readers familiar with C/C++ will be familiar with the &amp;quot;ternary&amp;quot; operator for control-flow within an expression:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# (condition) ? condition_true_expr1 : condition_false_expr2&lt;br /&gt;
x = reverse ? -x : x; # if (reverse) x = -x else x = x&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This is an expression that evaluates the first expression if the condition is true, or if it is false it evaluates the second expression. In most languages, this is an alternative to the if statement, which cannot be used as a value since it is a statement (in Nasal an if/else block is actually an expression, with the else value defaulting to nil if there is no else, so it is possible but rather ugly). The Python equivalent of the ternary-operator is: {{code|expr1 if (condition) else expr2}}.&lt;br /&gt;
&lt;br /&gt;
Nasal also includes the boolean [http://en.wikipedia.org/wiki/Short-circuit_evaluation short-circuit operators] &amp;quot;{{code|or}}&amp;quot; and &amp;quot;{{code|and}}&amp;quot; as keywords not symbols (not {{code|||}} and {{code|&amp;amp;&amp;amp;}}), like in Python. Unary negation is still {{code|!}} like C/C++ (Python, however, does it as &amp;quot;{{code|not}}&amp;quot;). One of the uses for these is as a reduction of if statements:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1); # if (condition) setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)&lt;br /&gt;
condition or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1); # if (!condition) setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1) -- negated case of above&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! if{}else{} does ''not'' (quite) work in this way:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;quot;{{code|or}}&amp;quot; is of higher precedence than &amp;quot;{{code|and}}&amp;quot;, so that is equivalent to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
(condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Doesn't it seem silly to be including the return of {{code|setprop()}} in the value of the left expression, which then can influence the execution of the second piece of code? In particular:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hash = {};&lt;br /&gt;
!contains(hash, &amp;quot;loopid&amp;quot;) and hash.loopid = 0 or hash.loopid += 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Which evaluates like this:&lt;br /&gt;
# hash is empty, so contains(hash, &amp;quot;loopid&amp;quot;) is false, and !contains(...) is thus true, so&lt;br /&gt;
# the right-hand side of {{code|and}} is tried, which is assignment to 0, and since the value of assignment is the right-hand side, it produces 0 aka false.&lt;br /&gt;
# since the result of false and false is false (which is the left side of the {{code|or}}), the right side of the {{code|or}} is tried (!) as per short-circuit rules.&lt;br /&gt;
# that means hash.loopid += 1 is evaluated – wait, didn't we want to ''not'' evaluate this?&lt;br /&gt;
&lt;br /&gt;
This counter-example proves that using &amp;quot;{{code|... and ... or ...}}&amp;quot; isn't quite the same thing as using &amp;quot;{{code|if (...) ... else ...}}&amp;quot; expression (which is better done using the ternary operator, &amp;quot;{{code|... ? ... : ...}}), which can be a dangerous bug, so the rule is: '''don't use this'''.&lt;br /&gt;
&lt;br /&gt;
== Slicing and indexing ==&lt;br /&gt;
{{Note|As of 27 May 2014, the syntax {{code|expr[]}} is no longer valid and considered an error. It is neither a slice nor an index expression, although it utilized postfix brackets.}}&lt;br /&gt;
In Nasal, vectors can be sliced (i.e. a new vector is constructed from indexes of an existing vector) and strings, hashes, and vectors can be indexed/subscripted. For an overview of slicing see [[Nasal Variables#Vector slicing|vector slicing]].&lt;br /&gt;
&lt;br /&gt;
Indexing works in different ways for the different types. For strings indexing returns a value equal to the value of the character at the position. For hashes it looks up the key in the hash directly, ignoring the parents vector, and returns nil if it is not found; this treats numbers and strings as different types of keys. For vectors, the value at the index of the array is retrieved, if it is valid. Some examples:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var vec = [0,1,2,3];&lt;br /&gt;
vec[0] == 0; vec[1] == 1;&lt;br /&gt;
vec[-1] == 3; # last element&lt;br /&gt;
vec[-2] == 2; # next-from-last element&lt;br /&gt;
&lt;br /&gt;
var hash = {&lt;br /&gt;
    -1: 0,&lt;br /&gt;
    &amp;quot;-1&amp;quot;: 1,&lt;br /&gt;
    hello: &amp;quot;hi&amp;quot;,&lt;br /&gt;
    parents: [{ find_me_here: 42 }]&lt;br /&gt;
};&lt;br /&gt;
hash[-1] == 0; # look up the number -1 in the hash&lt;br /&gt;
hash[&amp;quot;-1&amp;quot;] == 1; # look up the string (!) &amp;quot;-1&amp;quot; in the hash&lt;br /&gt;
hash[-1~&amp;quot;&amp;quot;] == 1; # same thing -- makes a string&lt;br /&gt;
hash.hello == &amp;quot;hi&amp;quot;; # find the member hello in the hash&lt;br /&gt;
hash[&amp;quot;hello&amp;quot;] == &amp;quot;hi&amp;quot;; # approximately the same, but using an index expression&lt;br /&gt;
hash.find_me_here == 42; # find the member find_me_here in the hash, or actually its parent&lt;br /&gt;
hash[&amp;quot;find_me_here&amp;quot;] == nil; # but it cannot be found with an index expression, because its parent isn't searched&lt;br /&gt;
hash.parents[0][&amp;quot;find_me_here&amp;quot;] == 42; # but we can always look for the specific parent's member&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Some insights on the workings of various common operations.&lt;br /&gt;
&lt;br /&gt;
=== Equality ===&lt;br /&gt;
&lt;br /&gt;
Here are the rules for checking equality:&lt;br /&gt;
* If both are scalars:&lt;br /&gt;
** If both are numeric: check if they are numerically equal (converting to numbers first).&lt;br /&gt;
** Else: check if they are equal as strings.&lt;br /&gt;
* Else compare id's (items only equal themselves, e.g. {{code|nil == nil}} while {{code|[] != []}} because they are different vectors with different id's).&lt;br /&gt;
&lt;br /&gt;
=== Boolean evaluation ===&lt;br /&gt;
&lt;br /&gt;
Rules for checking if a value is &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot;:&lt;br /&gt;
* If nil: return false&lt;br /&gt;
* If numeric:&lt;br /&gt;
** If 0: return false&lt;br /&gt;
** Else: return true&lt;br /&gt;
* Else: error &amp;quot;non-scalar in boolean context&amp;quot; (applies to hashes, functions, vectors, and ghosts)&lt;br /&gt;
&lt;br /&gt;
== Table ==&lt;br /&gt;
Here's a summary of operators, in no particular order:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symbol !! Operates on... !! Evaluates to...&lt;br /&gt;
|-&lt;br /&gt;
| {{code|+}} and {{code|-}} and {{code|/}} and {{code|*}} || Numeric scalars || A number&lt;br /&gt;
|-&lt;br /&gt;
| {{code|~}} || Scalars || A string&lt;br /&gt;
|-&lt;br /&gt;
| {{code|?:}} || Three &amp;quot;simple&amp;quot; expressions: condition, expr1, and expr2 || expr1 if the condition is true, else expr2&lt;br /&gt;
|-&lt;br /&gt;
| {{code|or}} || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''true''', else the second&lt;br /&gt;
|-&lt;br /&gt;
| {{code|and}} || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''false''', else the second&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Code&amp;diff=71949</id>
		<title>Template:Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Code&amp;diff=71949"/>
		<updated>2014-05-27T19:59:26Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: Created page with &amp;quot;&amp;lt;tt&amp;gt;{{{1|No code provided!}}}&amp;lt;/tt&amp;gt;&amp;lt;noinclude&amp;gt;{{Informative template|1= __NOTOC__ == Goal == Provide a unified way to embed code inline into a paragraph and investigate possibl...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tt&amp;gt;{{{1|No code provided!}}}&amp;lt;/tt&amp;gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Goal ==&lt;br /&gt;
Provide a unified way to embed code inline into a paragraph and investigate possible styling.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt;/nowiki&amp;gt;'''code'''&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;SHORT CODE EXPR&amp;lt;nowiki&amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Related templates ==&lt;br /&gt;
* {{tl|i18n month}}&lt;br /&gt;
* {{tl|time}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Formatting templates]]&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71945</id>
		<title>Nasal Operators</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71945"/>
		<updated>2014-05-27T19:35:23Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Slicing and indexing */ one more example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
Nasal has support for various operators, both mathematical (add, subtract, multiply, and divide) and programming-specific (assignment, concatenation, control-flow, etc.). Most operators are in [http://en.wikipedia.org/wiki/Infix_notation infix notation] – that is, the operator is in the middle of its operands as in &amp;quot;&amp;lt;tt&amp;gt;3 + 5&amp;lt;/tt&amp;gt;&amp;quot;. As mentioned, Nasal supports the four basic math operators as &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;  (power is ''not'' available as &amp;lt;tt&amp;gt;**&amp;lt;/tt&amp;gt; (Python) or &amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt; (Visual basic), but rather is done in the '''math''' namespace as: &amp;lt;tt&amp;gt;math.pow(&amp;lt;/tt&amp;gt;''base'', ''exponent''&amp;lt;tt&amp;gt;)&amp;lt;/tt&amp;gt;). For other math ones, assignment is just a single equals sign (&amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt;, as in &amp;lt;tt&amp;gt;var pi = 3.14&amp;lt;/tt&amp;gt;) and equality comparison is double-equals (&amp;lt;tt&amp;gt;==&amp;lt;/tt&amp;gt;, as in &amp;lt;tt&amp;gt;3 == 3&amp;lt;/tt&amp;gt;). Relative comparisons such as less-than (&amp;lt;tt&amp;gt;&amp;amp;lt;&amp;lt;/tt&amp;gt;), greater-than (&amp;lt;tt&amp;gt;&amp;amp;gt;&amp;lt;/tt&amp;gt;), less-than-or-equal-to (&amp;lt;tt&amp;gt;&amp;amp;lt;=&amp;lt;/tt&amp;gt;), and greater-than-or-equal-to (&amp;lt;tt&amp;gt;&amp;amp;gt;=&amp;lt;/tt&amp;gt;) also can be used (see [[Howto:Add a new binary operator to Nasal]] for an example of adding another comparison operator: the Perl &amp;quot;spaceship&amp;quot; operator, &amp;lt;tt&amp;gt;&amp;lt;=&amp;gt;&amp;lt;/tt&amp;gt;). When operating on two variables using these operators (excepting assignment), Nasal uses a notion of &amp;quot;scalars&amp;quot; if applicable. Instead of the mathematical notion of scalars as non-vectors, a scalar in programming is defined as a number ''or'' numeric string – essentially duplicity of datatypes available to represent a number. This allows a string to also represent a number, which makes, e.g., parsing a number out of a file or string very easy, since the programmer doesn't have to think about the conversion. According to Andy (the creator of Nasal):&lt;br /&gt;
&lt;br /&gt;
{{cquote| Like perl, and unlike everything else, nasal combines numbers and strings into a single &amp;quot;scalar&amp;quot; datatype. No conversion needs to happen in user code, which simplifies common string handling tasks. &amp;lt;ref&amp;gt;{{cite web |url=http://plausible.org/nasal/doc.html |title= Nasal – Not another scripting language.|author=Andy Ross|date=2007}}&amp;lt;/ref&amp;gt;|Andy Ross}}&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This presents a problem when you need to concatenate two or more numeric strings (which is often done with the same operator as addition). If the &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; operator sees two numeric strings, it will add them as numbers, thus &amp;lt;tt&amp;gt;&amp;quot;67&amp;quot; + &amp;quot;75&amp;quot; == 142&amp;lt;/tt&amp;gt; (resulting in a number), when one might want the string &amp;quot;35&amp;quot;. Andy had to introduce a new operator to do concatenation, like the &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; operator in PHP, and that was the tilde (&amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt;). Here's some examples showing the difference:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;88&amp;quot; + &amp;quot;88&amp;quot; == 176; # number&lt;br /&gt;
88 + &amp;quot;88&amp;quot; == &amp;quot;88&amp;quot; + 88; # same&lt;br /&gt;
&amp;quot;88&amp;quot; ~ &amp;quot;88&amp;quot; == &amp;quot;8888&amp;quot;; # string&lt;br /&gt;
88 ~ 88 == &amp;quot;8888&amp;quot;; # string as well&lt;br /&gt;
&amp;quot;88&amp;quot; ~ 88 == 88 ~ &amp;quot;88&amp;quot;; # same&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Readers familiar with C/C++ will be familiar with the &amp;quot;ternary&amp;quot; operator for control-flow within an expression:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# (condition) ? condition_true_expr1 : condition_false_expr2&lt;br /&gt;
x = reverse ? -x : x; # if (reverse) x = -x else x = x&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This is an expression that evaluates the first expression if the condition is true, or if it is false it evaluates the second expression. In most languages, this is an alternative to the if statement, which cannot be used as a value since it is a statement (in Nasal an if/else block is actually an expression, with the else value defaulting to nil if there is no else, so it is possible but rather ugly). The Python equivalent of the ternary-operator is: &amp;lt;tt&amp;gt;expr1 if (condition) else expr2&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Nasal also includes the boolean [http://en.wikipedia.org/wiki/Short-circuit_evaluation short-circuit operators] &amp;quot;&amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;&amp;quot; and &amp;quot;&amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt;&amp;quot; as keywords not symbols (not &amp;lt;tt&amp;gt;||&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt;), like in Python. Unary negation is still &amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt; like C/C++ (Python, however, does it as &amp;quot;&amp;lt;tt&amp;gt;not&amp;lt;/tt&amp;gt;&amp;quot;). One of the uses for these is as a reduction of if statements:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1); # if (condition) setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)&lt;br /&gt;
condition or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1); # if (!condition) setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1) -- negated case of above&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! if{}else{} does ''not'' (quite) work in this way:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;quot;&amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;&amp;quot; is of higher precedence than &amp;quot;&amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt;&amp;quot;, so that is equivalent to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
(condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Doesn't it seem silly to be including the return of &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; in the value of the left expression, which then can influence the execution of the second piece of code? In particular:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hash = {};&lt;br /&gt;
!contains(hash, &amp;quot;loopid&amp;quot;) and hash.loopid = 0 or hash.loopid += 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Which evaluates like this:&lt;br /&gt;
# hash is empty, so contains(hash, &amp;quot;loopid&amp;quot;) is false, and !contains(...) is thus true, so&lt;br /&gt;
# the right-hand side of &amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt; is tried, which is assignment to 0, and since the value of assignment is the right-hand side, it produces 0 aka false.&lt;br /&gt;
# since the result of false and false is false (which is the left side of the &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;), the right side of the &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt; is tried (!) as per short-circuit rules.&lt;br /&gt;
# that means hash.loopid += 1 is evaluated – wait, didn't we want to ''not'' evaluate this?&lt;br /&gt;
&lt;br /&gt;
This counter-example proves that using &amp;quot;&amp;lt;tt&amp;gt;... and ... or ...&amp;lt;/tt&amp;gt;&amp;quot; isn't quite the same thing as using &amp;quot;&amp;lt;tt&amp;gt;if (...) ... else ...&amp;lt;/tt&amp;gt;&amp;quot; expression (which is better done using the ternary operator, &amp;quot;&amp;lt;tt&amp;gt;... ? ... : ...&amp;lt;/tt&amp;gt;), which can be a dangerous bug, so the rule is: '''don't use this'''.&lt;br /&gt;
&lt;br /&gt;
== Slicing and indexing ==&lt;br /&gt;
{{Note|As of 27 May 2014, the syntax &amp;lt;tt&amp;gt;expr[]&amp;lt;/tt&amp;gt; is no longer valid and considered an error. It is neither a slice nor an index expression, although it utilized postfix brackets.}}&lt;br /&gt;
In Nasal, vectors can be sliced (i.e. a new vector is constructed from indexes of an existing vector) and strings, hashes, and vectors can be indexed/subscripted. For an overview of slicing see [[Nasal Variables#Vector slicing|vector slicing]].&lt;br /&gt;
&lt;br /&gt;
Indexing works in different ways for the different types. For strings indexing returns a value equal to the value of the character at the position. For hashes it looks up the key in the hash directly, ignoring the parents vector, and returns nil if it is not found; this treats numbers and strings as different types of keys. For vectors, the value at the index of the array is retrieved, if it is valid. Some examples:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var vec = [0,1,2,3];&lt;br /&gt;
vec[0] == 0; vec[1] == 1;&lt;br /&gt;
vec[-1] == 3; # last element&lt;br /&gt;
vec[-2] == 2; # next-from-last element&lt;br /&gt;
&lt;br /&gt;
var hash = {&lt;br /&gt;
    -1: 0,&lt;br /&gt;
    &amp;quot;-1&amp;quot;: 1,&lt;br /&gt;
    hello: &amp;quot;hi&amp;quot;,&lt;br /&gt;
    parents: [{ find_me_here: 42 }]&lt;br /&gt;
};&lt;br /&gt;
hash[-1] == 0; # look up the number -1 in the hash&lt;br /&gt;
hash[&amp;quot;-1&amp;quot;] == 1; # look up the string (!) &amp;quot;-1&amp;quot; in the hash&lt;br /&gt;
hash[-1~&amp;quot;&amp;quot;] == 1; # same thing -- makes a string&lt;br /&gt;
hash.hello == &amp;quot;hi&amp;quot;; # find the member hello in the hash&lt;br /&gt;
hash[&amp;quot;hello&amp;quot;] == &amp;quot;hi&amp;quot;; # approximately the same, but using an index expression&lt;br /&gt;
hash.find_me_here == 42; # find the member find_me_here in the hash, or actually its parent&lt;br /&gt;
hash[&amp;quot;find_me_here&amp;quot;] == nil; # but it cannot be found with an index expression, because its parent isn't searched&lt;br /&gt;
hash.parents[0][&amp;quot;find_me_here&amp;quot;] == 42; # but we can always look for the specific parent's member&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Some insights on the workings of various common operations.&lt;br /&gt;
&lt;br /&gt;
=== Equality ===&lt;br /&gt;
&lt;br /&gt;
Here are the rules for checking equality:&lt;br /&gt;
* If both are scalars:&lt;br /&gt;
** If both are numeric: check if they are numerically equal (converting to numbers first).&lt;br /&gt;
** Else: check if they are equal as strings.&lt;br /&gt;
* Else compare id's (items only equal themselves, e.g. &amp;lt;tt&amp;gt;nil == nil&amp;lt;/tt&amp;gt; while &amp;lt;tt&amp;gt;[] != []&amp;lt;/tt&amp;gt; because they are different vectors with different id's).&lt;br /&gt;
&lt;br /&gt;
=== Boolean evaluation ===&lt;br /&gt;
&lt;br /&gt;
Rules for checking if a value is &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot;:&lt;br /&gt;
* If nil: return false&lt;br /&gt;
* If numeric:&lt;br /&gt;
** If 0: return false&lt;br /&gt;
** Else: return true&lt;br /&gt;
* Else: error &amp;quot;non-scalar in boolean context&amp;quot; (applies to hashes, functions, vectors, and ghosts)&lt;br /&gt;
&lt;br /&gt;
== Table ==&lt;br /&gt;
Here's a summary of operators, in no particular order:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symbol !! Operates on... !! Evaluates to...&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt; || Numeric scalars || A number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt; || Scalars || A string&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;?:&amp;lt;/tt&amp;gt; || Three &amp;quot;simple&amp;quot; expressions: condition, expr1, and expr2 || expr1 if the condition is true, else expr2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt; || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''true''', else the second&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt; || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''false''', else the second&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71944</id>
		<title>Nasal Operators</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_Operators&amp;diff=71944"/>
		<updated>2014-05-27T19:34:29Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
Nasal has support for various operators, both mathematical (add, subtract, multiply, and divide) and programming-specific (assignment, concatenation, control-flow, etc.). Most operators are in [http://en.wikipedia.org/wiki/Infix_notation infix notation] – that is, the operator is in the middle of its operands as in &amp;quot;&amp;lt;tt&amp;gt;3 + 5&amp;lt;/tt&amp;gt;&amp;quot;. As mentioned, Nasal supports the four basic math operators as &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;  (power is ''not'' available as &amp;lt;tt&amp;gt;**&amp;lt;/tt&amp;gt; (Python) or &amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt; (Visual basic), but rather is done in the '''math''' namespace as: &amp;lt;tt&amp;gt;math.pow(&amp;lt;/tt&amp;gt;''base'', ''exponent''&amp;lt;tt&amp;gt;)&amp;lt;/tt&amp;gt;). For other math ones, assignment is just a single equals sign (&amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt;, as in &amp;lt;tt&amp;gt;var pi = 3.14&amp;lt;/tt&amp;gt;) and equality comparison is double-equals (&amp;lt;tt&amp;gt;==&amp;lt;/tt&amp;gt;, as in &amp;lt;tt&amp;gt;3 == 3&amp;lt;/tt&amp;gt;). Relative comparisons such as less-than (&amp;lt;tt&amp;gt;&amp;amp;lt;&amp;lt;/tt&amp;gt;), greater-than (&amp;lt;tt&amp;gt;&amp;amp;gt;&amp;lt;/tt&amp;gt;), less-than-or-equal-to (&amp;lt;tt&amp;gt;&amp;amp;lt;=&amp;lt;/tt&amp;gt;), and greater-than-or-equal-to (&amp;lt;tt&amp;gt;&amp;amp;gt;=&amp;lt;/tt&amp;gt;) also can be used (see [[Howto:Add a new binary operator to Nasal]] for an example of adding another comparison operator: the Perl &amp;quot;spaceship&amp;quot; operator, &amp;lt;tt&amp;gt;&amp;lt;=&amp;gt;&amp;lt;/tt&amp;gt;). When operating on two variables using these operators (excepting assignment), Nasal uses a notion of &amp;quot;scalars&amp;quot; if applicable. Instead of the mathematical notion of scalars as non-vectors, a scalar in programming is defined as a number ''or'' numeric string – essentially duplicity of datatypes available to represent a number. This allows a string to also represent a number, which makes, e.g., parsing a number out of a file or string very easy, since the programmer doesn't have to think about the conversion. According to Andy (the creator of Nasal):&lt;br /&gt;
&lt;br /&gt;
{{cquote| Like perl, and unlike everything else, nasal combines numbers and strings into a single &amp;quot;scalar&amp;quot; datatype. No conversion needs to happen in user code, which simplifies common string handling tasks. &amp;lt;ref&amp;gt;{{cite web |url=http://plausible.org/nasal/doc.html |title= Nasal – Not another scripting language.|author=Andy Ross|date=2007}}&amp;lt;/ref&amp;gt;|Andy Ross}}&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This presents a problem when you need to concatenate two or more numeric strings (which is often done with the same operator as addition). If the &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; operator sees two numeric strings, it will add them as numbers, thus &amp;lt;tt&amp;gt;&amp;quot;67&amp;quot; + &amp;quot;75&amp;quot; == 142&amp;lt;/tt&amp;gt; (resulting in a number), when one might want the string &amp;quot;35&amp;quot;. Andy had to introduce a new operator to do concatenation, like the &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; operator in PHP, and that was the tilde (&amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt;). Here's some examples showing the difference:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;88&amp;quot; + &amp;quot;88&amp;quot; == 176; # number&lt;br /&gt;
88 + &amp;quot;88&amp;quot; == &amp;quot;88&amp;quot; + 88; # same&lt;br /&gt;
&amp;quot;88&amp;quot; ~ &amp;quot;88&amp;quot; == &amp;quot;8888&amp;quot;; # string&lt;br /&gt;
88 ~ 88 == &amp;quot;8888&amp;quot;; # string as well&lt;br /&gt;
&amp;quot;88&amp;quot; ~ 88 == 88 ~ &amp;quot;88&amp;quot;; # same&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Conditionals ==&lt;br /&gt;
&lt;br /&gt;
Readers familiar with C/C++ will be familiar with the &amp;quot;ternary&amp;quot; operator for control-flow within an expression:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# (condition) ? condition_true_expr1 : condition_false_expr2&lt;br /&gt;
x = reverse ? -x : x; # if (reverse) x = -x else x = x&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This is an expression that evaluates the first expression if the condition is true, or if it is false it evaluates the second expression. In most languages, this is an alternative to the if statement, which cannot be used as a value since it is a statement (in Nasal an if/else block is actually an expression, with the else value defaulting to nil if there is no else, so it is possible but rather ugly). The Python equivalent of the ternary-operator is: &amp;lt;tt&amp;gt;expr1 if (condition) else expr2&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Nasal also includes the boolean [http://en.wikipedia.org/wiki/Short-circuit_evaluation short-circuit operators] &amp;quot;&amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;&amp;quot; and &amp;quot;&amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt;&amp;quot; as keywords not symbols (not &amp;lt;tt&amp;gt;||&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt;), like in Python. Unary negation is still &amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt; like C/C++ (Python, however, does it as &amp;quot;&amp;lt;tt&amp;gt;not&amp;lt;/tt&amp;gt;&amp;quot;). One of the uses for these is as a reduction of if statements:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1); # if (condition) setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)&lt;br /&gt;
condition or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1); # if (!condition) setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1) -- negated case of above&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beware! if{}else{} does ''not'' (quite) work in this way:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;quot;&amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;&amp;quot; is of higher precedence than &amp;quot;&amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt;&amp;quot;, so that is equivalent to:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
(condition and setprop(&amp;quot;/sim/gui/loaded&amp;quot;, 1)) or setprop(&amp;quot;/sim/gui/exited&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Doesn't it seem silly to be including the return of &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; in the value of the left expression, which then can influence the execution of the second piece of code? In particular:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hash = {};&lt;br /&gt;
!contains(hash, &amp;quot;loopid&amp;quot;) and hash.loopid = 0 or hash.loopid += 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Which evaluates like this:&lt;br /&gt;
# hash is empty, so contains(hash, &amp;quot;loopid&amp;quot;) is false, and !contains(...) is thus true, so&lt;br /&gt;
# the right-hand side of &amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt; is tried, which is assignment to 0, and since the value of assignment is the right-hand side, it produces 0 aka false.&lt;br /&gt;
# since the result of false and false is false (which is the left side of the &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;), the right side of the &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt; is tried (!) as per short-circuit rules.&lt;br /&gt;
# that means hash.loopid += 1 is evaluated – wait, didn't we want to ''not'' evaluate this?&lt;br /&gt;
&lt;br /&gt;
This counter-example proves that using &amp;quot;&amp;lt;tt&amp;gt;... and ... or ...&amp;lt;/tt&amp;gt;&amp;quot; isn't quite the same thing as using &amp;quot;&amp;lt;tt&amp;gt;if (...) ... else ...&amp;lt;/tt&amp;gt;&amp;quot; expression (which is better done using the ternary operator, &amp;quot;&amp;lt;tt&amp;gt;... ? ... : ...&amp;lt;/tt&amp;gt;), which can be a dangerous bug, so the rule is: '''don't use this'''.&lt;br /&gt;
&lt;br /&gt;
== Slicing and indexing ==&lt;br /&gt;
{{Note|As of 27 May 2014, the syntax &amp;lt;tt&amp;gt;expr[]&amp;lt;/tt&amp;gt; is no longer valid and considered an error. It is neither a slice nor an index expression, although it utilized postfix brackets.}}&lt;br /&gt;
In Nasal, vectors can be sliced (i.e. a new vector is constructed from indexes of an existing vector) and strings, hashes, and vectors can be indexed/subscripted. For an overview of slicing see [[Nasal Variables#Vector slicing|vector slicing]].&lt;br /&gt;
&lt;br /&gt;
Indexing works in different ways for the different types. For strings indexing returns a value equal to the value of the character at the position. For hashes it looks up the key in the hash directly, ignoring the parents vector, and returns nil if it is not found; this treats numbers and strings as different types of keys. For vectors, the value at the index of the array is retrieved, if it is valid. Some examples:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var vec = [0,1,2,3];&lt;br /&gt;
vec[0] == 0; vec[1] == 1;&lt;br /&gt;
vec[-1] == 3; # last element&lt;br /&gt;
vec[-2] == 2; # next-from-last element&lt;br /&gt;
&lt;br /&gt;
var hash = {&lt;br /&gt;
    -1: 0,&lt;br /&gt;
    &amp;quot;-1&amp;quot;: 1,&lt;br /&gt;
    hello: &amp;quot;hi&amp;quot;,&lt;br /&gt;
    parents: [{ find_me_here: 42 }]&lt;br /&gt;
};&lt;br /&gt;
hash[-1] == 0; # look up the number -1 in the hash&lt;br /&gt;
hash[&amp;quot;-1&amp;quot;] == 1; # look up the string (!) &amp;quot;-1&amp;quot; in the hash&lt;br /&gt;
hash[-1~&amp;quot;&amp;quot;] == 1; # same thing -- makes a string&lt;br /&gt;
hash.hello == &amp;quot;hi&amp;quot;; # find the member hello in the hash&lt;br /&gt;
hash[&amp;quot;hello&amp;quot;] == &amp;quot;hi&amp;quot;; # approximately the same, but using an index expression&lt;br /&gt;
hash.find_me_here == 42; # find the member find_me_here in the hash, or actually its parent&lt;br /&gt;
hash[&amp;quot;find_me_here&amp;quot;] == nil; # but it cannot be found with an index expression, because its parent isn't searched&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
Some insights on the workings of various common operations.&lt;br /&gt;
&lt;br /&gt;
=== Equality ===&lt;br /&gt;
&lt;br /&gt;
Here are the rules for checking equality:&lt;br /&gt;
* If both are scalars:&lt;br /&gt;
** If both are numeric: check if they are numerically equal (converting to numbers first).&lt;br /&gt;
** Else: check if they are equal as strings.&lt;br /&gt;
* Else compare id's (items only equal themselves, e.g. &amp;lt;tt&amp;gt;nil == nil&amp;lt;/tt&amp;gt; while &amp;lt;tt&amp;gt;[] != []&amp;lt;/tt&amp;gt; because they are different vectors with different id's).&lt;br /&gt;
&lt;br /&gt;
=== Boolean evaluation ===&lt;br /&gt;
&lt;br /&gt;
Rules for checking if a value is &amp;quot;true&amp;quot; or &amp;quot;false&amp;quot;:&lt;br /&gt;
* If nil: return false&lt;br /&gt;
* If numeric:&lt;br /&gt;
** If 0: return false&lt;br /&gt;
** Else: return true&lt;br /&gt;
* Else: error &amp;quot;non-scalar in boolean context&amp;quot; (applies to hashes, functions, vectors, and ghosts)&lt;br /&gt;
&lt;br /&gt;
== Table ==&lt;br /&gt;
Here's a summary of operators, in no particular order:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Symbol !! Operates on... !! Evaluates to...&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;*&amp;lt;/tt&amp;gt; || Numeric scalars || A number&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt; || Scalars || A string&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;?:&amp;lt;/tt&amp;gt; || Three &amp;quot;simple&amp;quot; expressions: condition, expr1, and expr2 || expr1 if the condition is true, else expr2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt; || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''true''', else the second&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt; || Two &amp;quot;simple&amp;quot; expressions || The first expression, if it evaluates to '''false''', else the second&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto_talk:Mix_scenery_versions&amp;diff=71831</id>
		<title>Howto talk:Mix scenery versions</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto_talk:Mix_scenery_versions&amp;diff=71831"/>
		<updated>2014-05-25T05:40:56Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Scenery v2.12? Or is it the scenery for FG 2.12 (that is, v1)? ==&lt;br /&gt;
&lt;br /&gt;
I was reviewing this, are we sure that the info at [[Howto:Mix scenery versions#Use the FlightGear world map]] is correct? I thought that it still contained the old scenery (v. 1)&lt;br /&gt;
--[[User:Bigstones|Bigstones]] ([[User talk:Bigstones|talk]]) 23:33, 24 May 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
: Yeah, old scenery (v1) -- that's the only thing I've heard. [[User:Philosopher|—Philosopher]] ([[User talk:Philosopher|talk]]) 05:40, 25 May 2014 (UTC)&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Optimization_findings&amp;diff=71775</id>
		<title>User:Philosopher/Optimization findings</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Optimization_findings&amp;diff=71775"/>
		<updated>2014-05-23T21:05:19Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* GC Hints */ more realistic examples, with actual GC-able objects...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Nasal Internals}}&lt;br /&gt;
&lt;br /&gt;
Here's some findings WRT optimizations. Note that these were from a test run with the B-1B, which is particularly heavy Nasal wise, see the second heading. Also note that these were profiled with a meta-Nasal script – Nasal profiling itself might have influenced some of the findings (the sim usually slows down, say, a factor of 4-6), but it should be relatively correct. To profile these yourself, clone &amp;amp; compile the &amp;quot;extended-nasal&amp;quot; branches of [https://gitorious.org/~philosopher/fg/philosophers-simgear] [https://gitorious.org/~philosopher/fg/philosophers-flightgear] [https://gitorious.org/~philosopher/fg/philosophers-fgdata].&lt;br /&gt;
&lt;br /&gt;
== props.Node.getNode() ==&lt;br /&gt;
&lt;br /&gt;
props.Node.getNode is evil. Well, as evil as it can be, here's some raw stats:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
props.wrapNode():&lt;br /&gt;
Global name: props.wrapNode()&lt;br /&gt;
Declared in /Users/philosopher/Documents/FlightGear/fgdata/Nasal/props.nas&lt;br /&gt;
Times called: 12797&lt;br /&gt;
Call time stats:&lt;br /&gt;
  min: 0.000036/3.600121e-05&lt;br /&gt;
  max: 0.062680/6.268001e-02&lt;br /&gt;
  average: 0.000074/7.401553e-05&lt;br /&gt;
Used local variables: None&lt;br /&gt;
Unused local variables: None&lt;br /&gt;
Most called from: /Users/philosopher/Documents/FlightGear/fgdata/Nasal/props.nas&lt;br /&gt;
&lt;br /&gt;
props.Node.getNode():&lt;br /&gt;
Global name: props.Node.getNode()&lt;br /&gt;
Declared in /Users/philosopher/Documents/FlightGear/fgdata/Nasal/props.nas&lt;br /&gt;
Times called: 10272&lt;br /&gt;
Call time stats:&lt;br /&gt;
  min: 0.000182/1.819134e-04&lt;br /&gt;
  max: 0.070453/7.045293e-02&lt;br /&gt;
  average: 0.001123/1.122783e-03&lt;br /&gt;
Used local variables: None&lt;br /&gt;
Unused local variables: None&lt;br /&gt;
Most called from: /Users/philosopher/Documents/FlightGear/fgdata/Aircraft/Generic/aar.nas&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That's a lot of calls to props.wrapNode (it was the most called function in this particular run) and it creates a new Nasal object each and every time – that's 12797 Nasal objects from a short test run! (At least, I believe it was short...) And each time one does getNode, that creates a new object. So using &amp;quot;immediate&amp;quot; .setValue/.getValue (those with the relative path) is going to be better in some circumstances. The best solution, I believe, is to use C++Bind for these (which of course is where we're eventually headed anyways...). The good news for now is that these functions are usually closer to the minimum value versus the maximum value (in particular, wrapNode averages out to about twice it's minimum time taken and getNode is a little less than an order of ten times it's minimum).&lt;br /&gt;
&lt;br /&gt;
== Aircraft/Generic/aar.nas ==&lt;br /&gt;
&lt;br /&gt;
'''The worst module ever'''. To quote from my analyzer script: &amp;quot;Longest function called (if called more than three times): fuel.update_loop (max time taken: 0.6208341, called 51 times)&amp;quot;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
Global name: fuel.update_loop()&lt;br /&gt;
Declared in /Users/philosopher/Documents/FlightGear/fgdata/Aircraft/Generic/aar.nas at line 216&lt;br /&gt;
Times called: 51&lt;br /&gt;
Call time stats:&lt;br /&gt;
  min: 0.106532/1.065321e-01&lt;br /&gt;
  max: 0.620834/6.208341e-01&lt;br /&gt;
  average: 0.312339/3.123395e-01&lt;br /&gt;
Used local variables: {'lbs', 'ppg', 'selected_tanks', 'consumed', 'cap', 'ac', 'out_of_fuel', 'gals', 'mp', 'fuel_per_tank', 'fuel', 'e', 'refueling', 't'}&lt;br /&gt;
Unused local variables: {'tankers'}&lt;br /&gt;
Most called from: /Users/philosopher/Documents/FlightGear/fgdata/Aircraft/Generic/aar.nas&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That's just awful, taking up a half-second max and barely managing a tenth of a second ?? This needs to be improved. (It looks like it recreates variables each time unnecessarily.)&lt;br /&gt;
&lt;br /&gt;
== Garbage Collector ==&lt;br /&gt;
Actually, I think it's pretty efficient if it has to sort through ''that'':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
**** Nasal garbage collection statistics: objects: 43883, references: 105527&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(wink)&lt;br /&gt;
&lt;br /&gt;
: to determine the potential benefits of the generational approach to GC, just add a counter to the naRef struct to count the number of GC survivals per object and increment it upon mark()ing - which should give you the percentage of &amp;quot;old&amp;quot; objects vs. &amp;quot;new&amp;quot; objects (nursery/young generation). The general assumption is that the majority of objects are in the nursery generation (gen0) and will be discarded quickly, while older objects (those having survived multiple GC passes) are assumed to stay around longer, in a larger generation (usually called &amp;quot;eden&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== GC Pressure ==&lt;br /&gt;
Objective: Come up with heuristics to define GC pressure as a useful metric, e.g.:&lt;br /&gt;
* function triggers GC (normally, ANY function can trigger the GC for unrelated objects, just because the GC runs out of free memory, so we need to do tracking)&lt;br /&gt;
* function allocates new objects&lt;br /&gt;
* function causes memory pools to be resized&lt;br /&gt;
* objects allocated by the function (temporaries) are GC'ed during or after the invocation of the func&lt;br /&gt;
* percentage of mark()ed and reap()ed objects per function&lt;br /&gt;
* repeatedly called functions (via timers or listeners) can be sampled by comparing runtime profiles of different runs&lt;br /&gt;
* new objects vs. additional references &lt;br /&gt;
* shadowed symbols&lt;br /&gt;
&lt;br /&gt;
== GC Hints ==&lt;br /&gt;
Nasal being a dynamic language, we could reduce the amount of necessary GC work by giving hints to the GC, either through dedicated APIs (extension functions) or by using a custom syntax for variables that have a certain lifetime (which would also help with generational GC), e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
var canvas = {};&lt;br /&gt;
GC.promote_to_generation(GC.eden, canvas);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A syntax/keyword-based approach would seem more intuitive, but would only take place at runtime, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
var:permanent nodes = []; # a permanent variable&lt;br /&gt;
var:temp i = []; # a temporary variable&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We could use lookup tables to register callbacks for different '''var:''' storage specifiers. Python and Lua provide explicit hooks into the GC, to affect and customize GC behavior.&lt;br /&gt;
&lt;br /&gt;
== Random observations ==&lt;br /&gt;
Resizing the window seems to be particularly Nasal-heavy (i.e. takes a long time with introspection).&lt;br /&gt;
: I assume that's because of a bunch of Nasal scripts having listeners registered to the x/y coordinates of the window ? Or is it something else ?&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Howto:Write_Optimized_Nasal_Code&amp;diff=71774</id>
		<title>User:Philosopher/Howto:Write Optimized Nasal Code</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher/Howto:Write_Optimized_Nasal_Code&amp;diff=71774"/>
		<updated>2014-05-23T20:07:05Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: ... how was I using PHP highlighting here?? ;-&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
&lt;br /&gt;
Paying attention to the code your writing can help speed it up and make it higher quality. This tutorial will teach programming good-practices and how to write more efficient code.&lt;br /&gt;
&lt;br /&gt;
There are two main types of efficiency to think about: algorithmic and GC (garbage collector) efficiency. Like all programming languages, one can write more and less efficient algorithms to fix the same problem, and in particular Nasal does '''not''' have an optimizer, so the coder (you) have to fix these yourself. Since Nasal is a scripting language, it has automatic garbage collecting through a mark/sweep collector which has been shown to be an expensive part of running Nasal in a runtime environment. There are things that can be done about this, in particular writing code that better heeds this limitation. I will start with this issue.&lt;br /&gt;
&lt;br /&gt;
== Garbage Collector-conscious optimizations ==&lt;br /&gt;
Except for numbers, every data type in Nasal has to be stored in an allocated C structure (struct naCode, naFunc, naCCode, naHash, naVec, and naStr) which is pointed to when a reference is needed. Each &amp;quot;variable&amp;quot; that one interacts with when writing a program is essentially a reference to one of these if the variable is not a number. To find the ones that are not valid, the mark/sweep garbage collector has to trace all references that are deemed valid and trace those children too; the starting point for the snowballing is essentially anything that is accessible from a function on the call stack or from the global namespace (though of course listeners and such also have to protect their storage). Excepting scalars, every object references other objects within their internal structure; when the object is declared as &amp;quot;reachable&amp;quot; during the mark phase, the GC also has to declare any references in the object as &amp;quot;reachable&amp;quot; as well (since they are obviously crucial to the working of their parent object and need to exist with their parent). For hashes this means all of the key/value pairs; for vectors all of the values; and for function wrappers (naFunc) the code (naCode) and its namespace (naHash) and other closures (naFunc) or the Nasal wrapper for a C function pointer (naCCode) (besides any other member references in any of those latter datatypes, like the filename for a naCode).&lt;br /&gt;
&lt;br /&gt;
There are a couple ways that a new object is created, which potentially requires calling the GC before the object is allocated. These are:&lt;br /&gt;
# String/vector concatenation with the &amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt; operator.&lt;br /&gt;
# Any [...] or {...} expression to create a vector or hash.&lt;br /&gt;
# Any func {...} expression, since a new wrapper (naFunc) needs to be generated for the underlying code (naCode).&lt;br /&gt;
# A call to a function written in Nasal will need to create a namespace for the function call (unless it is specified as part of call()). This creates a new object that will need to be GC'ed later&lt;br /&gt;
# Most extension functions, which often will create &amp;amp; return new objects (those using any naNew*() API), like substr, subvec, and caller, but usually not append (if sufficiently sized, i.e. not needing to resize() - since it modifies an existing object) or systime (because it returns a number).&lt;br /&gt;
&lt;br /&gt;
These constructs that create new objects are definitely fine to have in your code, but the question to ask with each one is &amp;quot;if this garbage-creating expression is evaluated often, can I move this to an outer scope?&amp;quot;. In other words: can you make the object once and still have the same functionality instead of making multiple copies? An example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# BAD: creates multiple object in each iteration of the loop&lt;br /&gt;
for (var i=0; i&amp;lt;10; i+=1)&lt;br /&gt;
    foreach (var j; [1,2,3,4,5]) # creates new object at the start of this foreach loop&lt;br /&gt;
        print(j); # uses it as read-only and thus doesn't require a new object each time&lt;br /&gt;
# GOOD: creates one object that is used for every iteration of the loop&lt;br /&gt;
# without being part of the loop body, i.e. the list variable in the outer scope&lt;br /&gt;
# doesn't need to be GC'ed here&lt;br /&gt;
var list=[1,2,3,4,5];&lt;br /&gt;
for (var i=0; i&amp;lt;10; i+=1)&lt;br /&gt;
    foreach (var j; list) # references the same object each time&lt;br /&gt;
        print(j); # uses it as read-only&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now if we were to mutate the vector, by assigning to one of its elements or by changing its size, we would want a different object each time (otherwise the mutations would keep building on top of each other). Note that in cases where we can do this, it not only serves as a GC optimization but also as a algorithmic optimization if we do this with hashes, since we avoid several hash sets to initialize the new hash by substituting a single hash get to find the variable.&lt;br /&gt;
&lt;br /&gt;
* Use append(vec, a) instead of vec ~= [a].&lt;br /&gt;
&lt;br /&gt;
In general, move object creation out of loops/functions, to a higher level scope, so that they don't add unnecessary garbage to the program - this applies in particular to those that are frequently used in callbacks invoked through timers and/or listeners. Also, instead of using anonymous objects in repeatedly called code, (vectors, hashes, functions) - lift their scope to a higher level, give them a symbolic name and reference them, so instead of this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var l = settimer( func {&lt;br /&gt;
    var x = [1,2,3];&lt;br /&gt;
}, 0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var x = [1,2,3];&lt;br /&gt;
&lt;br /&gt;
var foo = func {&lt;br /&gt;
    x;&lt;br /&gt;
};&lt;br /&gt;
var l = settimer( foo, 0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a good idea to set up your own environment (hash/namespace) for invocation-specific state, so that you can reuse/cache objects, rather than allocating/freeing them every time your callback is invoked.&lt;br /&gt;
&lt;br /&gt;
== Algorithmic optimizations ==&lt;br /&gt;
Here's a list of general things to keep in mind (in no particular order):&lt;br /&gt;
* Use foreach/forindex where possible.&lt;br /&gt;
* '''Don't''' create temporary variables&amp;lt;!-- , use the stash instead --&amp;gt;.&lt;br /&gt;
* Avoid multiple calls to a function if they will return the same thing&amp;lt;!-- (and please use the save/restore syntax to avoid creating temporary variables)--&amp;gt;.&lt;br /&gt;
* If you set a variable and make use of it only once, then directly embed the right-hand side of the assignment.&lt;br /&gt;
* In general, move the assignment of variables to the first place you use them, and if that is the only place you use that variable, then remove assignment of the variable entirely.&lt;br /&gt;
&lt;br /&gt;
If you think some of these rules lead to complete illegibility, then you can either ignore it (at the expense of optimization) or write two versions of the same code, one optimized and one legible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- •—–-~-–—• --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=71738</id>
		<title>User:TheTom</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=71738"/>
		<updated>2014-05-21T18:16:18Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* General */ add issue link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:FlightGear Core developers]]&lt;br /&gt;
[[Category:Developer Plans]]&lt;br /&gt;
&lt;br /&gt;
{{User&lt;br /&gt;
|name = Thomas (TheTom)&lt;br /&gt;
|location = Austria}}&lt;br /&gt;
&lt;br /&gt;
== Development plan ==&lt;br /&gt;
&lt;br /&gt;
=== GUI / render ===&lt;br /&gt;
&lt;br /&gt;
* Canvas based GUI {{Pending}}&lt;br /&gt;
** Create dialogs {{Done}} and widgets {{Pending}} from Nasal&lt;br /&gt;
** Handle keyboard input {{Not done}}&lt;br /&gt;
** Parse current gui and menu xml files {{Not done}}&lt;br /&gt;
* Canvas based HUD {{Pending}}&lt;br /&gt;
** Nasal API/framwork {{Pending}}&lt;br /&gt;
** Parse HUD xml files {{Not done}}&lt;br /&gt;
** Use Canvas GUI for 2D HUD {{Not done}}&lt;br /&gt;
** object placements for 3D HUD? {{Pending}}&lt;br /&gt;
*** Take care of projection/moving head {{Pending}}&lt;br /&gt;
* Canvas (API/General)&lt;br /&gt;
** Rotate map children according to map heading {{Pending}}&lt;br /&gt;
&lt;br /&gt;
=== Animation ===&lt;br /&gt;
&lt;br /&gt;
* Improved/advanced animations&lt;br /&gt;
** [[Tracking animation]] {{Done}}&lt;br /&gt;
* Blender animation/basic fdm exporter {{Pending}}&lt;br /&gt;
&lt;br /&gt;
=== Simulation / systems ===&lt;br /&gt;
&lt;br /&gt;
* Generic sytem building blocks {{Pending}}&lt;br /&gt;
** Allow to use conditions/expressions/property-rules/etc. to simulate any type of system (eg. electric, hydraulic,...) and especially take care to be able to build reusable building blocks.&lt;br /&gt;
** Unify/cleanup expression parser {{Not done}}&lt;br /&gt;
** Generic APU {{Pending}}&lt;br /&gt;
** Generic electrical system {{Pending}}&lt;br /&gt;
* Generic VDGS {{Pending}}&lt;br /&gt;
* MCDU/FMS/AMU framework {{Pending}}&lt;br /&gt;
* Blender system exporter {{Not done}}&lt;br /&gt;
&lt;br /&gt;
=== Aircraft / Scenery ===&lt;br /&gt;
&lt;br /&gt;
* [[Lockheed Martin C-130J Super Hercules]] {{Pending}}&lt;br /&gt;
* [http://www.flightgear.org/forums/viewtopic.php?f=5&amp;amp;t=18475 Flughafen Graz-Thalerhof (LOWG)] {{Pending}}&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
&lt;br /&gt;
* Respect XDG directories (and environment variables) {{issue|1468}} {{Not done}}&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Changelog_3.2&amp;diff=71641</id>
		<title>Changelog 3.2</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Changelog_3.2&amp;diff=71641"/>
		<updated>2014-05-19T03:28:38Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: /* Major enhancements in this release */ just a few commits I saw - need to add Gitorious links/more details&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{draft|changelog|This changelog is currently being written for the FlightGear 3.2 release. To see what is being worked on, check out [[Changelog 3.2]].&lt;br /&gt;
Feel free to help! If you are aware of any FlightGear related changes, please add them to the changelog.&amp;lt;br/&amp;gt;It's a good idea to check [[:Category:Changes_after_3.00|the newsletters since the last release]], and the git commit history.&lt;br /&gt;
To view the changelog for the most recent release, please see [[Changelog 3.0]]. &lt;br /&gt;
We also encourage people to help by translating the changelog and appreciate all contributions, however please keep in mind that this changelog is not yet final!&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Upcoming FlightGear Changelog==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
The FlightGear development team is delighted to announce the v3.2 release of FlightGear, the free, open-source flight simulator.  This new version contains many exciting new features, enhancements and bugfixes.  Highlights in this release include integration of the FGCom voice communications client within the simulator, improved terrain rendering, faster scenery loading, and improved usability.  This release also coincides with the release of FlightGear World Scenery 2.0 - massively improved scenery data covering the entirety of the planet and incorporating OpenStreetMap roads and detailed terrain information from a variety of sources.  &lt;br /&gt;
&lt;br /&gt;
Founded in 1997, FlightGear is developed by a worldwide group of volunteers, brought together by a shared ambition to create &lt;br /&gt;
the most realistic flight simulator possible that is free to use, modify and distribute. FlightGear is used all over the world &lt;br /&gt;
by desktop flight simulator enthusiasts, for research in universities and for interactive exhibits in museums.&lt;br /&gt;
&lt;br /&gt;
FlightGear features more than 400 aircraft, a worldwide scenery database, a multi-player environment, detailed sky modelling, a flexible and open aircraft modelling system, varied networking options, multiple display support, a powerful scripting language and an open architecture. Best of all, being open-source, the simulator is owned by the community and everyone is encouraged to contribute. &lt;br /&gt;
&lt;br /&gt;
Download FlightGear v3.2 for free from [http://www.flightgear.org FlightGear.org]&lt;br /&gt;
&lt;br /&gt;
FlightGear - Fly Free!&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Major enhancements in this release ===&lt;br /&gt;
&lt;br /&gt;
'''Surface Light Effects &amp;amp; OpenSceneGraph 3.2'''&lt;br /&gt;
&lt;br /&gt;
Stuart committed a change that brings surface lights, including VASI/PAPI/taxi/runway etc. into the xml-defined Effects  framework.  Kudos to Tim Moore for his original Effects work - it made it very straightforward to enhance with support for point sprites and a custom texture generator required.&lt;br /&gt;
&lt;br /&gt;
The relevant effect is data/Effects/surface-lights.eff.  It should allow development of ALS and Rembrandt variants.&lt;br /&gt;
&lt;br /&gt;
Stuart also replaced some OSG color/normal binding calls that were removed  in OSG3.2.0, apparently because they were slow.  So, if your&lt;br /&gt;
build fails, please check you've got a recent OSG build installed.&lt;br /&gt;
&lt;br /&gt;
'''Core'''&lt;br /&gt;
* [[Reset &amp;amp; re-init]] is merged and now enabled&lt;br /&gt;
* A segfault related to scripted Nasal fgcommands (like used in joystick and other bindings) has been fixed {{Issue|1397}}&lt;br /&gt;
* yasim versioning support for maintenance fixes (TorstenD)&lt;br /&gt;
* FLITE TTS support&lt;br /&gt;
* Windows dependencies have been updated&lt;br /&gt;
&lt;br /&gt;
'''Aircraft Modeling'''&lt;br /&gt;
* galvedro's work: [[A Failure Management Framework for FlightGear]]&lt;br /&gt;
* extra 500&lt;br /&gt;
* Tu-154B2 version 3.1&lt;br /&gt;
* additional aircraft have started adopting Gijs' [[NavDisplay]]&lt;br /&gt;
&lt;br /&gt;
'''JSBSim'''&lt;br /&gt;
* ground effects (see newsletter 02/2014)&lt;br /&gt;
&lt;br /&gt;
'''Environment Rendering'''&lt;br /&gt;
* EarthView: Orbital Rendering (Thorsten) [http://sourceforge.net/p/flightgear/mailman/message/32262904/]&lt;br /&gt;
&lt;br /&gt;
'''Performance'''&lt;br /&gt;
* F-JJTH and Stuart have started working on using osg::Simplifier [https://gitorious.org/fg/simgear/commit/3429e0072103a8c90d8e456f1f6b711099851225]: http://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/CAP3ntysifK34TxANKUj1s4Of_dJRg7dvJ74Gbko4zXVFHdV-YQ%40mail.gmail.com/#msg32016452&lt;br /&gt;
&lt;br /&gt;
'''Misc/Uncategorized'''&lt;br /&gt;
* AIModels use PagedLOD&lt;br /&gt;
* Optimise NavCache airport query&lt;br /&gt;
* osg::Switch for masking scenery rendering&lt;br /&gt;
* Torsten's metar work, newradio, mongoose httpd&lt;br /&gt;
* HTTP: improve handling of connection errors&lt;br /&gt;
* [[FGCamera]] (external addon, not yet reviewed/committed as of 03/2014)&lt;br /&gt;
* Windows installer has been reworked&lt;br /&gt;
* Windows installer creates 3 news directories pre-configured in FGRun:&lt;br /&gt;
** {user}\Documents\FlightGear\Aircraft&lt;br /&gt;
** {user}\Documents\FlightGear\TerraSync&lt;br /&gt;
** {user}\Documents\FlightGear\Custom Scenery&lt;br /&gt;
&lt;br /&gt;
''' Usability '''&lt;br /&gt;
* Windows users are now able to use scrollwheel in dialog&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Internationalization '''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''' Scenery '''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Canvas System'''&lt;br /&gt;
&lt;br /&gt;
FlightGear's fully scriptable 2D rendering system now includes improved APIs for creating maps and navigation displays amongst many other improvements. People no longer need to have programming experience to add a working ND to their aircraft, it can  now  be all done by copying and pasting 30 lines of text and customizing a few properties. The so called MapStructure back-end handles efficient updating of all ND layers transparently.&lt;br /&gt;
&lt;br /&gt;
* Tom has pushed an update to git (simgear) which removes a lot of unneeded OpenGL state changes for Canvas paths. Depending on the GPU/driver this can lead to quite a noticeable performance improvement. For example, he was able to get from ~120ms down to ~45ms [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=16984&amp;amp;p=204730#p204730].&lt;br /&gt;
* Hooray is working on adding shader support to Canvas {{Progressbar|30}}&lt;br /&gt;
* Gijs is currently working on additional projections as part of {{Issue|550}}&lt;br /&gt;
* The [[MapStructure]] back-end used by the [[NavDisplay]] now supports symbol instancing, so that performance is improved&lt;br /&gt;
* MapStructure-based layers can now be customized and styled&lt;br /&gt;
* Tom added support for button/modifiers (mouse handling) [http://wiki.flightgear.org/index.php?title=Canvas_Event_Handling&amp;amp;curid=10777&amp;amp;diff=68569&amp;amp;oldid=68422]&lt;br /&gt;
* CanvasImage now supports the ''http://'' protocol for dynamically retrieving raster images. See the renamed [[Canvas_Image#src|src attribute]] (''file'' is now deprecated).&lt;br /&gt;
* As part of the ongoing effort on [[Unifying the 2D rendering backend via canvas]], we have started re-implementing the integrated [[Map]] dialog using Nasal &amp;amp; Canvas instead of C++ {{Progressbar|80}}&lt;br /&gt;
* Custom event handlers can now be registered.&lt;br /&gt;
&lt;br /&gt;
'''Nasal Scripting'''&lt;br /&gt;
&lt;br /&gt;
* getprop()/setprop() arguments (those that form a path) can now be numeric to specify a index, so:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
getprop(&amp;quot;canvas/by-index&amp;quot;, &amp;quot;texture&amp;quot;, 1, &amp;quot;name&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
: is now the same as:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
getprop(&amp;quot;canvas/by-index/texture[1]/name&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
: (see [https://gitorious.org/fg/flightgear/commit/5eee5e42ae4f5cf56283b3bf5a3be46efc2b51c4 merge request 54] and [https://gitorious.org/fg/flightgear/commit/34ed79e5f88ffdfc5e651a1fe3e639cb8f4d3353 actual commit])&lt;br /&gt;
* A new fully-interactive Nasal GUI console based on [[Canvas]] has been added: [[Interactive Nasal Console]]&lt;br /&gt;
* the hard-coded '''flight path history''' subsystem which samples aircraft position, which was previously only accessible to C++ code, has now been exposed to scripting space by Tom so that people can easily access the system and reuse the data for their own purpoes (e.g. for creating an instructor console). The first use-case will involve the new [[Canvas]] based [[Map]] dialog which will be 100% scripted by then.  &lt;br /&gt;
: Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hist = aircraft.history(); debug.dump(hist.pathForHistory(50));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* cppbind: Nasal ghosts can now support arbitrary setters/getters for when members are not mapped to a C++ member/method.&lt;br /&gt;
 &lt;br /&gt;
'''Documentation'''&lt;br /&gt;
&lt;br /&gt;
'''Highlighted new and improved aircraft'''&lt;br /&gt;
&lt;br /&gt;
Tuned autopilot and improved instrument stack for the Cessna337G Skymaster.&lt;br /&gt;
&lt;br /&gt;
'''Other'''&lt;br /&gt;
&lt;br /&gt;
'''Bug fixes'''&lt;br /&gt;
&lt;br /&gt;
* See [http://code.google.com/p/flightgear-bugs/issues/list?can=1&amp;amp;q=Milestone%3D3.2 our bugtracker] for an extensive, yet incomplete, list of the bugs fixed in this release.&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear changelogs]]&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:Philosopher&amp;diff=71443</id>
		<title>User:Philosopher</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:Philosopher&amp;diff=71443"/>
		<updated>2014-05-16T20:16:50Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: better document this issue report while I have it...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Sub-pages:''' (mostly stubs ATM)&lt;br /&gt;
* [[User:Philosopher/Advanced Input Programming|Advanced Input Programming]]&lt;br /&gt;
* [[User:Philosopher/Howto:Write Optimized Nasal Code|Howto Write Optimized Nasal Code]]&lt;br /&gt;
* [[User:Philosopher/Nasal introspection|Nasal introspection!]]&lt;br /&gt;
* [[User:Philosopher/Optimization findings|Optimization findings]] (from [[User:Philosopher/Nasal introspection|Nasal introspection]])&lt;br /&gt;
&lt;br /&gt;
Currently working on improving Nasal internals and documenting them. Has the '''best''' joystick bindings (for a cheap joystick :P) at [http://flightgear.org/forums/viewtopic.php?t=17263 this topic].&lt;br /&gt;
&lt;br /&gt;
Likes reading through C/C++ code for fun, and understanding, documenting, and improving it – though I'm far from an expert in either and my hat is continually off to Andy, Thomas, and James (and everyone else) for their wonderful code. Oddly enough, I find Nasal code to be harder to read, probably due to the fact that C/C++ and very structured languages and Nasal is not (it almost needs DbC at times!).&lt;br /&gt;
&lt;br /&gt;
Favorite languages:&lt;br /&gt;
* Nasal (of course)&lt;br /&gt;
* Python (was my first language; I like most things about it except its duck typing – which works well until I actually need typing)&lt;br /&gt;
* C &amp;amp; C++ (different beasts; I like C++'s classes and ::iterators in particular)&lt;br /&gt;
* Languages yet to be discovered: I hope to find more that I like!&lt;br /&gt;
&lt;br /&gt;
Things to be doing:&lt;br /&gt;
* [[Improving the Joystick GUI]]: porting to Canvas, tweaking things, and integration with back-end when ready.&lt;br /&gt;
* Joystick-Philosopher (bindings for Cyborg-X): improve the control_function library.&lt;br /&gt;
* Nasal improvement for 3.0 (LaTeX document, making patches and applying patches to SimGear).&lt;br /&gt;
* Nasal browser: need a mechanism to add/delete/edit entries, need better scrolling code.&lt;br /&gt;
* Canvas Map: working on [[MapStructure]].nas, to replace old map.nas &amp;amp;c.&lt;br /&gt;
&lt;br /&gt;
Projects on the wiki:&lt;br /&gt;
* [[Interactive Nasal Console]]&lt;br /&gt;
* [[MapStructure]]&lt;br /&gt;
* [[User:Philosopher/Nasal introspection|Nasal Introspection]]&lt;br /&gt;
&lt;br /&gt;
Good ideas:&lt;br /&gt;
* Expose the catapult locations to the property tree, for JSBSim 'craft and Nasal tutorials.&lt;br /&gt;
* [http://flightgear.org/forums/viewtopic.php?f=18&amp;amp;t=19666 Changing behavior of SGPropertyNodes without tying] (something like {{issue|336}}).&lt;br /&gt;
* (In conjunction with Hooray) Have Nasal load itself: besides for one file (either Nasal/globals.nas or something in [[$FG_ROOT]]), ''all'' Nasal should be loaded from Nasal.  (Including &amp;lt;tt&amp;gt;--prop:/nasal/module_name/script&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--prop:/nasal/module_name/file&amp;lt;/tt&amp;gt;.) See [http://flightgear.org/forums/viewtopic.php?f=30&amp;amp;t=21083] &amp;amp; [http://forum.flightgear.org/viewtopic.php?f=30&amp;amp;t=21083] {{Progressbar|50}}.&lt;br /&gt;
&lt;br /&gt;
Nasal thoughts area:&lt;br /&gt;
* I would like to include small improvements that enhance my quality of life in SimGear: string slicing, hash iteration using foreach/forindex, save/restore aka stash? (latter to be discussed)&lt;br /&gt;
* Hooray and I talk about more extension functions to allow looking into internals; I need to review all of these, gather them up, add to them, etc., and hope they can be included somewhere (Hooray was saying maybe just the standalone Nasal in SimGear, not FlightGear's runtime).&lt;br /&gt;
** Sub-idea: if we only include the extensions in standalone and we have optimizer/post-compiler scripts ready, then make a script to be run with standalone that optimizes any or all Nasal files and outputs an optimized version (*.nas.optimized) or even just the bytecode (*.nas.opcode, textual file ofc) and have that be the preferred loading method (if the text is older than the optimized version).&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Implementing_new_features_for_FlightGear&amp;diff=71438</id>
		<title>Implementing new features for FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Implementing_new_features_for_FlightGear&amp;diff=71438"/>
		<updated>2014-05-16T18:08:57Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: some formatting tweaks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
&lt;br /&gt;
We've been seeing an increasing number of discussions on the forum started by people who are obviously eager to become potential contributors, either by adding new features to FlightGear, or by improving other aspects of FlightGear as a whole (community, infrastructure, usability, end-user support, accessibility, funding etc). Unfortunately, this has caused some friction over time, because people were expecting their involvement to work differently, especially those primarily making suggestions and providing feedback through discussions are obviously getting fed up with the community of contributors not responding directly to such feedback. &lt;br /&gt;
&lt;br /&gt;
Now, we do appreciate any community involvement obviously, but people who are serious about actually bringing certain changes to FlightGear will find that just making suggestions will typically not work too well, and that just participating in lengthy community discussions is usually fruitless. We've had some extremely heated discussions over the years, some debating interesting ideas - and many ending up being dozens of pages in size, containing hundreds of postings. Often, these contain lots of good ideas and suggestions, but sooner or later these suggestions become emotional and are no longer constructive - yet, we're dealing with them constantly, which is taking up resources, i.e. time and energy.&lt;br /&gt;
In an open source project like FlightGear, which is entirely volunteer driven, time is the most precious resource we have to contribute. It is like a &amp;quot;currency&amp;quot; for the project, and whenever something (or someone) is taking up lots of time without anything materializing, this is draining resources from other areas, no matter if it's end-user support or development in some shape or form.&lt;br /&gt;
&lt;br /&gt;
We are now trying to document how &amp;quot;bootstrapping&amp;quot; a feature or project works ''conceptually'', i.e. implementing new features for Flightgear - to provide a perspective that enables people to better understand how to bring changes to FlightGear without having to do all the work on their own. Note that this doesn't mean that this is the only way to accomplish something, but this is a tested and proven way - which we didn't come up with, but which is just a convention that happens to &amp;quot;just work&amp;quot;, which is an important aspect for a non-organized project like FlightGear, where development itself also primarily &amp;quot;just happens&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Currently, this article is entirely based on a write-up that Thorsten contributed based on having worked on a variety of novel, and unprecedented, FlightGear features over the years which initially also didn't receive much support at all, and which also caused lengthy discussions (or even flame wars) on the forum and the devel list, including features like [[Advanced weather]], [[Atmospheric light scattering]], [[Procedural Texturing]] and most recently the [[FlightGear Newsletter April 2014|EarthView]] orbital rendering engine. &lt;br /&gt;
These are just a few examples to put some context around the advice given here. Also note that the people who contributed to this particular write-up are not core developers per se, we are also primarily middleware/base package contributors. And when we started out a few years ago (and several thousand postings back), we were also highly critical about [[How the FlightGear project works|the way the project works]], and all its shortcomings. And now, we're often the ones being &amp;quot;yelled&amp;quot; at on the forums when dealing with newcomers, even though that's exactly how we started out. &lt;br /&gt;
Yet, fast forward 5+ years later, we are still trying to contribute in meaningful ways to the project, despite some (or even many) of these problems still persisting even today. So this is an attempt to provide a '''lessons learnt''' intro based on newcomers trying to become contributors, and trying to turn their ideas into features that actually end up in FlightGear, without having to be expert programmers necessarily, or even programmers at all.&lt;br /&gt;
&lt;br /&gt;
== What is this about? ==&lt;br /&gt;
&lt;br /&gt;
Like many FG users, you probably reach a point when you think 'Wouldn't it be nice if we had feature XY?' From this point, there are various options available:&lt;br /&gt;
&lt;br /&gt;
* You mention it in the forum: &amp;lt;br/&amp;gt; A vast body of observation suggests that the likely outcome of this is that several users will answer and tell you that it is a good idea, a few long-term contributers will chime in and point out possible difficulties, and it will end there.&lt;br /&gt;
* You make a formal feature request on the issue tracker: &amp;lt;br/&amp;gt; The most likely outcome are a few comments and then the request will be assigned a low priority and not much else will happen.&lt;br /&gt;
* You make it your own project to get feature XY implemented: &amp;lt;br/&amp;gt; This doesn't necessarily mean that you have to do everything yourself, but it means that you must actively manage what is happening rather than be content to put an idea out in writing and relax. If you're willing to do this, this guide is for you, please read on.&lt;br /&gt;
&lt;br /&gt;
== Some (unpleasant) truths up front ==&lt;br /&gt;
First, to avoid disappointments, it is important to understand how FG as an OpenSource all-volunteer project works - if you start with your project without understanding these essentials, it is bound to fail.&lt;br /&gt;
&lt;br /&gt;
# Flightgear relies on having a contributor base, but not on a user base: &amp;lt;br/&amp;gt; Unlike a commercial project which needs customers to survive, FG does not. As a result, FG development is not focused on the end user. Developers tend to work on features they would like to see, scenery contributors work on areas of the world they are interested in - the project works on the basis of people devoting their spare time to creating the simulator they want to have. This means that arguments along 'If feature XY will be implemented, many more users will join the community.' or 'If feature XY is not implemented, many users will use FSX instead.' will leave developers unimpressed, but arguments like 'If feature XY is implemented, it allows new contributors to improve the simulator in that way.' will be regarded as more interesting.&lt;br /&gt;
# Developers are free to do what they want: &amp;lt;br/&amp;gt; This should be pretty obvious given the nature as an all-volunteer project, but in reality it is not, so it's worth pointing out: FG developers work for the project in their free time, they have work and family obligations just like other people, and they have every right to not work on FG or to not code a feature even if a majority of users or developers thinks it is very important. The implication is that if you like anyone to help you, you need to convince him to do it voluntarily.&lt;br /&gt;
# Flightgear development tends to be inclusive: &amp;lt;br/&amp;gt; There is strong concern throughout the development community about making FG impossible to use for some hardware setups or dropping existing features, and all such changes tend to be discussed in length (over months or even years). Usually new features are therefore implemented in an optional way. If the feature you have in mind will mean abandoning support for an existing feature, you will have a hard time getting support even if it has clear benefits (the devel community did for instance not support the use of compressed dds textures despite their obvious benefits in terms of loading time and GPU memory consumption for the reason that they can't be run by Linux-users with non-proprietary graphics drivers).&lt;br /&gt;
&lt;br /&gt;
== Test the waters ==&lt;br /&gt;
&lt;br /&gt;
If you want your idea to be part of Flightgear in the end and not a fork or an addon, test the waters early on. Working for a year on some project which won't be committed in the end is frustrating for both sides. Use the forum or the mailing list to talk to people, get a feeling for how the response is, just don't leave it there. &lt;br /&gt;
&lt;br /&gt;
Some events that have occurred in the past, and what to learn from them:&lt;br /&gt;
&lt;br /&gt;
* Beautiful airport scenery (and certain aircraft/cockpits) could not be committed, because it was textured using material from a source that has free textures with a no commercial use clause. This however is incompatible with FGs GPL license which permits also commercial use. Lesson: If you use any material other than your own work, check the license early!&lt;br /&gt;
&lt;br /&gt;
* A large collection of Swiss airport scenery could not be committed because it was structured in the wrong way - scenery data has to be submitted in a certain format to the scenery database, other data to the FGData repository. Lesson: Study the structure of FG - don't expect that the whole structure of the project will change for you, it is what it is for good reasons, even if you don't know them, others do. &lt;br /&gt;
&lt;br /&gt;
* The bombable addon providing support for air combat could not be committed because the devel community feels strongly that FG should remain a civilian aviation simulator. Lesson: Test the waters, see what the response to an idea from developers who can commit are. They will decide, regardless of what users say.&lt;br /&gt;
&lt;br /&gt;
== Gather information ==&lt;br /&gt;
&lt;br /&gt;
Regardless if you want to proceed on your own, or if you want to find people to help you - you need information. If you want to see a new visual effect implemented, at minimum you need to find out who inside the FG project can help you, even better is to have an idea what options FG provides, how the effect framework works, how effects are configured etc. The Wiki is your friend, but usually if you show some interest, people in the forum will post helpful links. If you want to be taken seriously later, work through the information and make sure you know what you're talking about.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Make a proposal ==&lt;br /&gt;
&lt;br /&gt;
Now it's time to approach the people who can help you. Remember - they're volunteers. So you need to get them interested. &lt;br /&gt;
&lt;br /&gt;
Do...&lt;br /&gt;
&lt;br /&gt;
* ... point out how your idea will make FG a better simulation.&lt;br /&gt;
* ... make a point out of what you would be willing to do if only XY were available.&lt;br /&gt;
* ... be as concrete as possible, point out what precisely you would like to see changed.&lt;br /&gt;
* ... demonstrate that you have looked at the relevant information and know what you're talking about&lt;br /&gt;
&lt;br /&gt;
Don't...&lt;br /&gt;
&lt;br /&gt;
* ... demand anything from anyone.&lt;br /&gt;
* ... be rude or angry if people are critical - it's part of the process.&lt;br /&gt;
* ... point out how bad FG is going to be or how it will fail if your idea is not implemented. &lt;br /&gt;
* ... say you can't do anything, because you don't understand C++ - the human mind can learn&lt;br /&gt;
&lt;br /&gt;
Compare 'Wouldn't it be cool if we had better-looking cities like X-Plane?' with 'Would it be possible to make the random building shader configurable such that it loads a pre-defined set of 3d models and assembles them in naturally looking groups by a placement mask of this and that format? I would then take care of the buildings and textures, but I'd need some help with the code. Here's a picture of how FG could look like.' - which of the two proposals would you support?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Even good proposals have a fair chance of failing to get any support. The reason is that experience has shown that the majority of people who say that they would do X if only feature XY is implemented do in fact not do X afterwards. Which is to say, before starting to join a project, developers want to be reasonably sure that their work will not be in vain because you lose interest and walk away. The magic words here are 'track record' and 'proof of concept', you can help improve you signal/noise ratio significantly by ensuring that you follow up on your commitments and do the necessary behind-the-scenes networking to implement a new feature or project. It is this combination of having a track record, &amp;quot;credit&amp;quot; and a good signal/noise ratio that will ultimately give you certain ''leverage'' when interacting with other contributors.&lt;br /&gt;
Overall, time spent contributing to the project really '''is''' our &amp;quot;currency-it shows dedication and discipline and it demonstrates to potential collaboratos that you are serious about your commitments, and that teaming up with you is not a waste of their time. If properly done, such networking can be a great multiplier/lever.&lt;br /&gt;
&lt;br /&gt;
If you already have a history of bringing projects to a conclusion, people are far, far more likely to support you. If you have not, because you're just starting out, the best thing you can do is a proof of concept. Perhaps something should really be in C++ for performance reasons - but you can make a simple proof of concept in Nasal scripting space. Once people see that you're actually investing time and work rather than talk, and once they can see what you want to do, you're again more likely to get support.&lt;br /&gt;
&lt;br /&gt;
== Be persistent ==&lt;br /&gt;
If you fail to get help you need, think about why. There may be fair reasons for it - your priority may not be everyone else's priority, or some criticism may not be mean but actually valid, or your contribution isn't apparent enough - go back and try to revise the proposal. If you can't get help in some area, perhaps there's a workaround which is less perfect? Nasal often is a viable alternative to C++, and subsystems can always be converted later. Trying to get things perfect up-front is likely to get you nowhere, because making things perfect is very hard - starting with something 'good enough' and improving it is more likely to succeed. If your project is truly good, it will get support on the way. Investigate your idea critically, but if you truly believe in your idea, stay with it and make it work in some form.&lt;br /&gt;
&lt;br /&gt;
As an example, in the beginning the idea of using Nasal to implement a full weather system was not taken seriously by anyone in the development community. Once written in a very inefficient but working way, the system however did get lots of help from developers on the C++ side and is now known as Advanced Weather, one of the most sophisticated weather systems which exist in a flight simulation.&lt;br /&gt;
&lt;br /&gt;
== Honor your commitments ==&lt;br /&gt;
&lt;br /&gt;
This should go without saying but: Keep your end of the bargain. Seriously. If you got someone to do a month of work for you because you proposed it would enable you to do XY and you in fact don't do XY later, that's pretty much it - no one will ever lift a finger for you from that point.&lt;br /&gt;
&lt;br /&gt;
== Release early, document your efforts ==&lt;br /&gt;
&lt;br /&gt;
Use the forum and/or the wiki as a platform to show people what you are doing and how you are progressing. People need to be aware of things before they can help you, and you may get useful pointers just at the expense of posting your current vexing problem in the forum. It is also always a good idea to do a forum/devel list search to check the archives for related discussions that took place in the past, this should give you a good idea on discussed approaches, but also people involved in these discussions (and if they're still around or not).&lt;br /&gt;
&lt;br /&gt;
While the forum and the devel mailing list are great places for discussions, there are sometimes topics that have been discussed at great lengths, this includes topics like multiplayer improvements or even combat support for example. &lt;br /&gt;
&lt;br /&gt;
For such popular discussions, there are often 5-10 threads per year on the list/forum with typically dozens of responses. Another popular debate is better multi-threading support, but also scenery improvements.&lt;br /&gt;
&lt;br /&gt;
Accordingly, given the popularity of these topics, there are typically hundreds (or even thousands!) of postings and statements that have been made over the years. &lt;br /&gt;
&lt;br /&gt;
Often, with little -if anything- materializing from such debates directly, no matter how good the discussed ideas were. Postings may contain good suggestions, useful feedback, but also lots of controversial arguments. &lt;br /&gt;
And more often than not, the general truth is that people -especially newcomers- are unlikely to do a forum/devel list search in order to dig out some discussion that took place many years ago, just to learn about a project, its status, the ideas and the people that were involved.&lt;br /&gt;
&lt;br /&gt;
Thus, it is up to you to see how much momentum there really is, or if a certain topic tends to be a &amp;quot;time-waster&amp;quot;, i.e. taking up lots of time to deal with, with very little materializing in terms of features - sometimes, those are long-standing features, such as being able to reset/re-init the simulator, or even save/load flights and switch aircraft at run-time. These are popular feature requests and there are dozens of discussions related to these, so it is usually not a good idea to start yet another debate - this is where a less-conversational platform (like the wiki) can be a great tool, so that ideas, proposals, community support and project status can be documented over time. &lt;br /&gt;
&lt;br /&gt;
'''Time''' really being the keyword here - some topics are not about a single isolated feature that can simply be implemented by some random developer, those are often large-scale architectural changes, or even proposals to change the project's philosophy ([[Release Plan]]) or some of its infrastructure (e.g. the [[FlightGear Build Server]]). Thus, these topics are often not about people disagreeing that something needs to be done, but the suggestion really is a long-term item, that needs to be tackled over time - typically many months, often several years. &lt;br /&gt;
&lt;br /&gt;
Here, using the wiki to present your ideas, and document related discussions, proposals and supporters, can be a great tool to aid building up momentum over time. We've had a number of efforts that got discussed for years before they finally got implemented. This included for example the PLIB/OSG migration, and the HLA effort is another example for this. Typically, complex ideas may very well have a shelf life of several months - often, 12-18 months. The [[Canvas]] system only took shape 18 months after it had been discussion on the FlightGear wiki for example.&lt;br /&gt;
&lt;br /&gt;
Thus, sometimes good ideas may take time to materialize - and whenever timing doesn't seem to work, it's a good idea to let time work for you, by creating a corresponding wiki article to document something, and maintaining it over time.&lt;br /&gt;
&lt;br /&gt;
Make your efforts available for testing early - let people play with it and get ideas from it. Only a well-working project should go directly to the FG repositories, but there's plenty of ways to distribute your efforts before that. When it's ready and tested, make a merge request on GIT, talk to a person who has commit rights and is able to test your work, and enjoy your feature being part of the next release.&lt;br /&gt;
&lt;br /&gt;
If you made it to this point, you may perhaps appreciate much better why the devel community is how it is!&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Implementing_new_features_for_FlightGear&amp;diff=71435</id>
		<title>Implementing new features for FlightGear</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Implementing_new_features_for_FlightGear&amp;diff=71435"/>
		<updated>2014-05-16T17:59:58Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: remove Template:Note because it doesn't quite fit&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
&lt;br /&gt;
We've been seeing an increasing number of discussions on the forum started by people who are obviously eager to become potential contributors. Unfortunately, this has caused some friction over time, because people were expecting their involvement to work differently, especially those primarily making suggestions and providing feedback through discussions are obviously getting fed up with the community of contributors not responding directly to such feedback. &lt;br /&gt;
&lt;br /&gt;
Now, we do appreciate any community involvement obviously, but people who are serious about actually bringing certain changes to FlightGear will find that just making suggestions will typically not work too well, and that just participating in lengthy community discussions is usually fruitless. We've had some extremely heated discussions over the years, some debating interesting ideas - and many ending up being dozens of pages in size, containing hundreds of postings. Often, these contain lots of good ideas and suggestions, but sooner or later these suggestions become emotional and are no longer constructive - yet, we're dealing with them constantly, which is taking up resources, i.e. time and energy.&lt;br /&gt;
In an open source project like FlightGear, which is entirely volunteer driven, time is the most precious resource we have to contribute. It is like a &amp;quot;currency&amp;quot; for the project, and whenever something (or someone) is taking up lots of time without anything materializing, this is draining resources from other areas, no matter if it's end-user support or development in some shape or form.&lt;br /&gt;
&lt;br /&gt;
We are now trying to document how &amp;quot;bootstrapping&amp;quot; a feature or project works ''conceptually'', i.e. implementing new features for Flightgear - to provide a perspective that enables people to better understand how to bring changes to FlightGear without having to do all the work on their own. Note that this doesn't mean that this is the only way to accomplish something, but this is a tested and proven way - which we didn't come up with, but which is just a convention that happens to &amp;quot;just work&amp;quot;, which is an important aspect for a non-organized project like FlightGear, where development itself also primarily &amp;quot;just happens&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Currently, this article is entirely based on a write-up that Thorsten contributed based on having worked on a variety of novel, and unprecedented, FlightGear features over the years which initially also didn't receive much support at all, and which also caused lengthy discussions (or even flame wars) on the forum and the devel list, including features like [[Advanced weather]], [[Atmospheric light scattering]], [[Procedural Texturing]] and most recently the [[FlightGear Newsletter April 2014|EarthView]] orbital rendering engine. &lt;br /&gt;
These are just a few examples to put some context around the advice given here. Also note that the people who contributed to this particular write-up are not core developers per se, we are also primarily middleware/base package contributors. And when we started out a few years ago (and several thousand postings back), we were also highly critical about [[How the FlightGear project works|the way the project works]], and all its shortcomings. And now, we're often the ones being &amp;quot;yelled&amp;quot; at on the forums when dealing with newcomers, even though that's exactly how we started out. &lt;br /&gt;
Yet, fast forward 5+ years later, we are still trying to contribute in meaningful ways to the project, despite some (or even many) of these problems still persisting even today. So this is an attempt to provide a '''lessons learnt''' intro based on newcomers trying to become contributors, and trying to turn their ideas into features that actually end up in FlightGear, without having to be expert programmers necessarily, or even programmers at all.&lt;br /&gt;
&lt;br /&gt;
== What is this about? ==&lt;br /&gt;
&lt;br /&gt;
Like many FG users, you probably reach a point when you think 'Wouldn't it be nice if we had feature XY?' From this point, there are various options available:&lt;br /&gt;
&lt;br /&gt;
* You mention it in the forum:&lt;br /&gt;
&lt;br /&gt;
A vast body of observation suggests that the likely outcome of this is that several users will answer and tell you that it is a good idea, a few long-term contributers will chime in and point out possible difficulties, and it will end there.&lt;br /&gt;
&lt;br /&gt;
* You make a formal feature request on the issue tracker:&lt;br /&gt;
&lt;br /&gt;
The most likely outcome are a few comments and then the request will be assigned a low priority and not much else will happen.&lt;br /&gt;
&lt;br /&gt;
* You make it your own project to get feature XY implemented:&lt;br /&gt;
&lt;br /&gt;
This doesn't necessarily mean that you have to do everything yourself, but it means that you must actively manage what is happening rather than be content to put an idea out in writing and relax. If you're willing to do this, this guide is for you, please read on.&lt;br /&gt;
&lt;br /&gt;
== Some (unpleasant) truths up front ==&lt;br /&gt;
First, to avoid disappointments, it is important to understand how FG as an OpenSource all-volunteer project works - if you start with your project without understanding these essentials, it is bound to fail.&lt;br /&gt;
&lt;br /&gt;
# Flightgear relies on having a contributor base, but not on a user base&lt;br /&gt;
&lt;br /&gt;
Unlike a commercial project which needs customers to survive, FG does not. As a result, FG development is not focused on the end user. Developers tend to work on features they would like to see, scenery contributors work on areas of the world they are interested in - the project works on the basis of people devoting their spare time to creating the simulator they want to have. This means that arguments along 'If feature XY will be implemented, many more users will join the community.' or 'If feature XY is not implemented, many users will use FSX instead.' will leave developers unimpressed, but arguments like 'If feature XY is implemented, it allows new contributors to improve the simulator in that way.' will be regarded as more interesting.&lt;br /&gt;
&lt;br /&gt;
# Developers are free to do what they want&lt;br /&gt;
&lt;br /&gt;
This should be pretty obvious given the nature as an all-volunteer project, but in reality it is not, so it's worth pointing out: FG developers work for the project in their free time, they have work and family obligations just like other people, and they have every right to not work on FG or to not code a feature even if a majority of users or developers thinks it is very important. The implication is that if you like anyone to help you, you need to convince him to do it voluntarily.&lt;br /&gt;
&lt;br /&gt;
# Flightgear development tends to be inclusive&lt;br /&gt;
&lt;br /&gt;
There is strong concern throughout the development community about making FG impossible to use for some hardware setups or dropping existing features, and all such changes tend to be discussed in length (over months or even years). Usually new features are therefore implemented in an optional way. If the feature you have in mind will mean abandoning support for an existing feature, you will have a hard time getting support even if it has clear benefits (the devel community did for instance not support the use of compressed dds textures despite their obvious benefits in terms of loading time and GPU memory consumption for the reason that they can't be run by Linux-users with non-proprietary graphics drivers).&lt;br /&gt;
&lt;br /&gt;
== Test the waters ==&lt;br /&gt;
&lt;br /&gt;
If you want your idea to be part of Flightgear in the end and not a fork or an addon, test the waters early on. Working for a year on some project which won't be committed in the end is frustrating for both sides. Use the forum or the mailing list to talk to people, get a feeling for how the response is, just don't leave it there. &lt;br /&gt;
&lt;br /&gt;
Some events that have occurred in the past, and what to learn from them:&lt;br /&gt;
&lt;br /&gt;
* Beautiful airport scenery (and certain aircraft/cockpits) could not be committed, because it was textured using material from a source that has free textures with a no commercial use clause. This however is incompatible with FGs GPL license which permits also commercial use. Lesson: If you use any material other than your own work, check the license early!&lt;br /&gt;
&lt;br /&gt;
* A large collection of Swiss airport scenery could not be committed because it was structured in the wrong way - scenery data has to be submitted in a certain format to the scenery database, other data to the FGData repository. Lesson: Study the structure of FG - don't expect that the whole structure of the project will change for you, it is what it is for good reasons, even if you don't know them, others do. &lt;br /&gt;
&lt;br /&gt;
* The bombable addon providing support for air combat could not be committed because the devel community feels strongly that FG should remain a civilian aviation simulator. Lesson: Test the waters, see what the response to an idea from developers who can commit are. They will decide, regardless of what users say.&lt;br /&gt;
&lt;br /&gt;
== Gather information ==&lt;br /&gt;
&lt;br /&gt;
Regardless if you want to proceed on your own, or if you want to find people to help you - you need information. If you want to see a new visual effect implemented, at minimum you need to find out who inside the FG project can help you, even better is to have an idea what options FG provides, how the effect framework works, how effects are configured etc. The Wiki is your friend, but usually if you show some interest, people in the forum will post helpful links. If you want to be taken seriously later, work through the information and make sure you know what you're talking about.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Make a proposal ==&lt;br /&gt;
&lt;br /&gt;
Now it's time to approach the people who can help you. Remember - they're volunteers. So you need to get them interested. &lt;br /&gt;
&lt;br /&gt;
Do...&lt;br /&gt;
&lt;br /&gt;
... point out how your idea will make FG a better simulation.&lt;br /&gt;
... make a point out of what you would be willing to do if only XY were available.&lt;br /&gt;
... be as concrete as possible, point out what precisely you would like to see changed.&lt;br /&gt;
... demonstrate that you have looked at the relevant information and know what you're talking about&lt;br /&gt;
&lt;br /&gt;
Don't...&lt;br /&gt;
&lt;br /&gt;
... demand anything from anyone.&lt;br /&gt;
... be rude or angry if people are critical - it's part of the process.&lt;br /&gt;
... point out how bad FG is going to be or how it will fail if your idea is not implemented. &lt;br /&gt;
... say you can't do anything, because you don't understand C++ - the human mind can learn&lt;br /&gt;
Compare 'Wouldn't it be cool if we had better-looking cities like X-Plane?' with 'Would it be possible to make the random building shader configurable such that it loads a pre-defined set of 3d models and assembles them in naturally looking groups by a placement mask of this and that format? I would then take care of the buildings and textures, but I'd need some help with the code. Here's a picture of how FG could look like.' - which of the two proposals would you support?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Even good proposals have a fair chance of failing to get any support. The reason is that experience has shown that the majority of people who say that they would do X if only feature XY is implemented do in fact not do X afterwards. Which is to say, before starting to join a project, developers want to be reasonably sure that their work will not be in vain because you lose interest and walk away. The magic words here are 'track record' and 'proof of concept'.&lt;br /&gt;
&lt;br /&gt;
If you already have a history of bringing projects to a conclusion, people are far, far more likely to support you. If you have not, because you're just starting out, the best thing you can do is a proof of concept. Perhaps something should really be in C++ for performance reasons - but you can make a simple proof of concept in Nasal scripting space. Once people see that you're actually investing time and work rather than talk, and once they can see what you want to do, you're again more likely to get support.&lt;br /&gt;
&lt;br /&gt;
== Be persistent ==&lt;br /&gt;
If you fail to get help you need, think about why. There may be fair reasons for it - your priority may not be everyone else's priority, or some criticism may not be mean but actually valid, or your contribution isn't apparent enough - go back and try to revise the proposal. If you can't get help in some area, perhaps there's a workaround which is less perfect? Nasal often is a viable alternative to C++, and subsystems can always be converted later. Trying to get things perfect up-front is likely to get you nowhere, because making things perfect is very hard - starting with something 'good enough' and improving it is more likely to succeed. If your project is truly good, it will get support on the way. Investigate your idea critically, but if you truly believe in your idea, stay with it and make it work in some form.&lt;br /&gt;
&lt;br /&gt;
As an example, in the beginning the idea of using Nasal to implement a full weather system was not taken seriously by anyone in the development community. Once written in a very inefficient but working way, the system however did get lots of help from developers on the C++ side and is now known as Advanced Weather, one of the most sophisticated weather systems which exist in a flight simulation.&lt;br /&gt;
&lt;br /&gt;
== Honor your commitments ==&lt;br /&gt;
&lt;br /&gt;
This should go without saying but: Keep your end of the bargain. Seriously. If you got someone to do a month of work for you because you proposed it would enable you to do XY and you in fact don't do XY later, that's pretty much it - no one will ever lift a finger for you from that point.&lt;br /&gt;
&lt;br /&gt;
== Release early, document your efforts ==&lt;br /&gt;
&lt;br /&gt;
Use the forum and/or the wiki as a platform to show people what you are doing and how you are progressing. People need to be aware of things before they can help you, and you may get useful pointers just at the expense of posting your current vexing problem in the forum. It is also always a good idea to do a forum/devel list search to check the archives for related discussions that took place in the past, this should give you a good idea on discussed approaches, but also people involved in these discussions (and if they're still around or not).&lt;br /&gt;
&lt;br /&gt;
While the forum and the devel mailing list are great places for discussions, there are sometimes topics that have been discussed at great lengths, this includes topics like multiplayer improvements or even combat support for example. &lt;br /&gt;
&lt;br /&gt;
For such popular discussions, there are often 5-10 threads per year on the list/forum with typically dozens of responses. Another popular debate is better multi-threading support, but also scenery improvements.&lt;br /&gt;
&lt;br /&gt;
Accordingly, given the popularity of these topics, there are typically hundreds (or even thousands!) of postings and statements that have been made over the years. &lt;br /&gt;
&lt;br /&gt;
Often, with little -if anything- materializing from such debates directly, no matter how good the discussed ideas were. Postings may contain good suggestions, useful feedback, but also lots of controversial arguments. &lt;br /&gt;
And more often than not, the general truth is that people -especially newcomers- are unlikely to do a forum/devel list search in order to dig out some discussion that took place many years ago, just to learn about a project, its status, the ideas and the people that were involved.&lt;br /&gt;
&lt;br /&gt;
Thus, it is up to you to see how much momentum there really is, or if a certain topic tends to be a &amp;quot;time-waster&amp;quot;, i.e. taking up lots of time to deal with, with very little materializing in terms of features - sometimes, those are long-standing features, such as being able to reset/re-init the simulator, or even save/load flights and switch aircraft at run-time. These are popular feature requests and there are dozens of discussions related to these, so it is usually not a good idea to start yet another debate - this is where a less-conversational platform (like the wiki) can be a great tool, so that ideas, proposals, community support and project status can be documented over time. &lt;br /&gt;
&lt;br /&gt;
'''Time''' really being the keyword here - some topics are not about a single isolated feature that can simply be implemented by some random developer, those are often large-scale architectural changes, or even proposals to change the project's philosophy ([[Release Plan]]) or some of its infrastructure (e.g. the [[FlightGear Build Server]]). Thus, these topics are often not about people disagreeing that something needs to be done, but the suggestion really is a long-term item, that needs to be tackled over time - typically many months, often several years. &lt;br /&gt;
&lt;br /&gt;
Here, using the wiki to present your ideas, and document related discussions, proposals and supporters, can be a great tool to aid building up momentum over time. We've had a number of efforts that got discussed for years before they finally got implemented. This included for example the PLIB/OSG migration, and the HLA effort is another example for this. Typically, complex ideas may very well have a shelf life of several months - often, 12-18 months. The [[Canvas]] system only took shape 18 months after it had been discussion on the FlightGear wiki for example.&lt;br /&gt;
&lt;br /&gt;
Thus, sometimes good ideas may take time to materialize - and whenever timing doesn't seem to work, it's a good idea to let time work for you, by creating a corresponding wiki article to document something, and maintaining it over time.&lt;br /&gt;
&lt;br /&gt;
Make your efforts available for testing early - let people play with it and get ideas from it. Only a well-working project should go directly to the FG repositories, but there's plenty of ways to distribute your efforts before that. When it's ready and tested, make a merge request on GIT, talk to a person who has commit rights and is able to test your work, and enjoy your feature being part of the next release.&lt;br /&gt;
&lt;br /&gt;
If you made it to this point, you may perhaps appreciate much better why the devel community is how it is!&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=71433</id>
		<title>Template:Note</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=71433"/>
		<updated>2014-05-16T17:55:40Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: remove float:center...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;noprint&amp;quot; style=&amp;quot;margin:1em 5% 1em 5%; border: 1px solid #AAAAAA; border-left: 10px solid #1E90FF; width: 50%; background-color: #F5F5F5; padding: 2px;&amp;quot;&amp;gt;&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding-left:5px;&amp;quot;| '''&amp;lt;span class=&amp;quot;smallcaps&amp;quot; style=&amp;quot;font-variant:small-caps;&amp;quot;&amp;gt;Note&amp;lt;/span&amp;gt;:''' {{{1}}}&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;{{Informative template |1=&lt;br /&gt;
== Goal ==&lt;br /&gt;
Provide an uniform note style.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{note|The actual text comes here.}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=71431</id>
		<title>Template:Note</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=71431"/>
		<updated>2014-05-16T17:52:35Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: restore margin setting?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;noprint&amp;quot; style=&amp;quot;margin:1em 5% 1em 5%; float:center; border: 1px solid #AAAAAA; border-left: 10px solid #1E90FF; width: 50%; background-color: #F5F5F5; padding: 2px;&amp;quot;&amp;gt;&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding-left:5px;&amp;quot;| '''&amp;lt;span class=&amp;quot;smallcaps&amp;quot; style=&amp;quot;font-variant:small-caps;&amp;quot;&amp;gt;Note&amp;lt;/span&amp;gt;:''' {{{1}}}&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;{{Informative template |1=&lt;br /&gt;
== Goal ==&lt;br /&gt;
Provide an uniform note style.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{note|The actual text comes here.}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=71430</id>
		<title>Template:Note</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=71430"/>
		<updated>2014-05-16T17:49:37Z</updated>

		<summary type="html">&lt;p&gt;Philosopher: wasn't fond of the style here... so copied the div from Template:notice and added small caps to NOTE - does it look good?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;noprint&amp;quot; style=&amp;quot;margin-left: auto; margin-right:auto; float:center; border: 1px solid #AAAAAA; border-left: 10px solid #1E90FF; width: 50%; background-color: #F5F5F5; padding: 2px;&amp;quot;&amp;gt;&lt;br /&gt;
{| cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding-left:5px;&amp;quot;| '''&amp;lt;span class=&amp;quot;smallcaps&amp;quot; style=&amp;quot;font-variant:small-caps;&amp;quot;&amp;gt;Note&amp;lt;/span&amp;gt;:''' {{{1}}}&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;{{Informative template |1=&lt;br /&gt;
== Goal ==&lt;br /&gt;
Provide an uniform note style.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{note|The actual text comes here.}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox templates]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Philosopher</name></author>
	</entry>
</feed>