<?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=TheTom</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=TheTom"/>
	<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/Special:Contributions/TheTom"/>
	<updated>2026-04-09T10:42:39Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_event_handling&amp;diff=114446</id>
		<title>Canvas event handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_event_handling&amp;diff=114446"/>
		<updated>2018-02-15T23:13:02Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Add keyboard events&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{infobox subsystem&lt;br /&gt;
|name        = Canvas Event Handling&lt;br /&gt;
|started     = 11/2012 (Available since [[Changelog 2.10|FlightGear 2.10]])&lt;br /&gt;
|description = DOM like event handling&lt;br /&gt;
|developers  = {{usr|TheTom}}&lt;br /&gt;
|folders = &lt;br /&gt;
* {{flightgear file|src/Canvas/gui_mgr.hxx}}&lt;br /&gt;
* {{simgear file|simgear/canvas}}&lt;br /&gt;
}}&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
The Canvas event handling system closely follows the W3C [http://www.w3.org/TR/DOM-Level-3-Events/ DOM Event Model]. If you have already used events in JavaScript and HTML most concepts of the Canvas event system should be already familiar to you. The most notable difference is the missing capture phase, but it is usually not used anyhow.&lt;br /&gt;
&lt;br /&gt;
Listeners - simple Nasal functions - can be attached to every element inside the Canvas and the Canvas itself. Once a certain action - like moving the mouse or pressing a button - occurs the associated listeners are called. We can use this for example to detect whether the mouse has moved over an element or if a certain element has been clicked. For this you should understand how [[Using_Nasal_functions#Function_closures|closures work]].&lt;br /&gt;
&lt;br /&gt;
= Listen for events =&lt;br /&gt;
&lt;br /&gt;
To receive events callback function can be added to elements on a Canvas as well as to the Canvas itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
canvas.addEventListener(&amp;quot;&amp;lt;type&amp;gt;&amp;quot;, &amp;lt;func&amp;gt;);&lt;br /&gt;
canvas_element.addEventListener(&amp;quot;&amp;lt;type&amp;gt;&amp;quot;, &amp;lt;func&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For each placement of a Canvas handling events can be enabled or disabled. A Canvas placed in a PUI (old GUI) widget or as standalone GUI window receives events by default, whereas Canvases placed onto the aircraft model or in the scenery do not receive any events by default.&lt;br /&gt;
&lt;br /&gt;
{{Note|When using the old [[Howto:Adding_a_canvas_to_a_GUI_dialog|PUI/XML GUI]] with a '''&amp;lt;nowiki&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/nowiki&amp;gt;'''-widget placement, PUI does not trigger any mouseover/hover (mousemove) events. Mouse clicks/wheel/drag are working as expected. For all other placements like on standalone Canvas windows and [[Howto:Add_a_2D_canvas_instrument_to_your_aircraft|3D models]] there is no such limitation. If you find that your code doesn't work as expected, make sure to verify that your layers (canvas groups) use matching z-index ordering, or overlapping symbols may prevent event handlers from being triggered/called.}}&lt;br /&gt;
&lt;br /&gt;
For standalone GUI windows setting '''capture-events''' to ''0'' or ''1'' enables or disables handling of events respectively. For a Canvas placed onto a 3d model, setting ''capture-events'' inside the placement can be used to activate event handling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var dlg = canvas.Window.new([152,74]);&lt;br /&gt;
&lt;br /&gt;
# Disable event handling for this window. Events will pass through&lt;br /&gt;
# and can reach any window or also object covered by the window.&lt;br /&gt;
dlg.setBool(&amp;quot;capture-events&amp;quot;, 0);&lt;br /&gt;
&lt;br /&gt;
# Place the canvas onto the PFD and enable receiving events&lt;br /&gt;
my_canvas.addPlacement({&amp;quot;node&amp;quot;: &amp;quot;PFD-Screen&amp;quot;, &amp;quot;capture-events&amp;quot;: 1});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Event flow =&lt;br /&gt;
&lt;br /&gt;
Events always are targeted at a specific element inside the Canvas. Before any event handler is called the propagation path for the event is determined. It consists of the event target itself and all its ancestor elements (Groups) up to and including the Canvas. Afterwards - during the ''Target Phase'' - all listeners registered on the event target are called. Finally - during the ''Bubbling Phase'' - the event bubbles up the tree, following the propagation path determined in the first step, and all listeners attached to the according elements are called.&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas Eventflow.png|thumb|540px|center|Event flow of Canvas Events similar to W3C DOM Event flow &amp;lt;ref name=&amp;quot;dom-event-flow&amp;quot;&amp;gt;DOM Level 3 event flow. http://www.w3.org/TR/DOM-Level-3-Events/#event-flow&amp;lt;/ref&amp;gt;.]]&lt;br /&gt;
&lt;br /&gt;
= Event classes =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var Event = {&lt;br /&gt;
  # Name of event type [read-only]&lt;br /&gt;
  type: &amp;lt;typename&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Target element [read-only]&lt;br /&gt;
  target: &amp;lt;target-element&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Element the currently called listener is attached to [read-only]&lt;br /&gt;
  currentTarget: &amp;lt;target-element&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Stop further propagation of event (stop&lt;br /&gt;
  # bubbling up to its parents)&lt;br /&gt;
  stopPropagation: func()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
# Since FG 3.1.0&lt;br /&gt;
var DeviceEvent = {&lt;br /&gt;
  parents: [Event],&lt;br /&gt;
&lt;br /&gt;
  # State of all keyboard modifiers at the time the event has&lt;br /&gt;
  # been triggered [read-only]&lt;br /&gt;
  modifiers: &amp;lt;modifier-mask&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  ctrlKey: &amp;lt;was-ctrl-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  shiftKey: &amp;lt;was-shift-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  altKey: &amp;lt;was-alt-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  metaKey: &amp;lt;was-meta-down&amp;gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Since FG 3.1.0&lt;br /&gt;
var KeyboardEvent = {&lt;br /&gt;
  parents: [DeviceEvent],&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  key: &amp;lt;key-string&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Location of the key on the keyboard [read-only]&lt;br /&gt;
  #&lt;br /&gt;
  # https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboard-key-location&lt;br /&gt;
  #&lt;br /&gt;
  #  0 standard location&lt;br /&gt;
  #  1 left&lt;br /&gt;
  #  2 right&lt;br /&gt;
  #  3 numpad&lt;br /&gt;
  location: &amp;lt;key-location&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  repeat: &amp;lt;is-repeat&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  charCode: &amp;lt;code&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  keyCode: &amp;lt;code&amp;gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var MouseEvent = {&lt;br /&gt;
  # [FG &amp;gt;= 3.1.0]&lt;br /&gt;
  parents: [DeviceEvent],&lt;br /&gt;
&lt;br /&gt;
  # [FG &amp;lt; 3.1.0]&lt;br /&gt;
  parents: [Event],&lt;br /&gt;
&lt;br /&gt;
  # Position in screen coordinates [read-only]&lt;br /&gt;
  screenX: &amp;lt;screen-x&amp;gt;,&lt;br /&gt;
  screenY: &amp;lt;screen-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Position in window/canvas coordinates [read-only]&lt;br /&gt;
  clientX: &amp;lt;client-x&amp;gt;,&lt;br /&gt;
  clientY: &amp;lt;client-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Position in local/element coordinates [read-only]&lt;br /&gt;
  localX: &amp;lt;local-x&amp;gt;,&lt;br /&gt;
  localY: &amp;lt;local-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Distance to position of previous event [read-only]&lt;br /&gt;
  deltaX: &amp;lt;delta-x&amp;gt;,&lt;br /&gt;
  deltaY: &amp;lt;delta-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Current click count (number of clicks within a certain&lt;br /&gt;
  # time limit. max. 3) [read-only]&lt;br /&gt;
  click_count: &amp;lt;click-count&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Button which triggered this event [read-only, FG &amp;gt;= 3.1.0]&lt;br /&gt;
  #&lt;br /&gt;
  #  0: primary button (usually the left button)&lt;br /&gt;
  #  1: auxiliary button (usually the middle button/mouse wheel)&lt;br /&gt;
  #  2: secondary button (usually the right button)&lt;br /&gt;
  button: &amp;lt;button&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # State of all mouse buttons at the time the event has been&lt;br /&gt;
  # triggered [read-only, FG &amp;gt;= 3.1.0]&lt;br /&gt;
  buttons: &amp;lt;active-button-mask&amp;gt;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Middle-mouse button emulation ==&lt;br /&gt;
&lt;br /&gt;
2-button mice can be setup to emulate a middle-mouse button click by pressing the left and right button simultaneously. On Ubuntu you can use [https://apps.ubuntu.com/cat/applications/gpointing-device-settings gpointing-device-settings] to enable &amp;quot;middle button emulation&amp;quot;&lt;br /&gt;
&amp;lt;ref&amp;gt;https://wiki.ubuntu.com/X/Quirks#A2-button_Mice&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref&amp;gt;http://askubuntu.com/questions/140828/how-can-i-paste-text-by-pressing-the-left-and-right-mouse-buttons-at-the-same-ti&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Event types =&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Description !! DOM equivalent event !! Bubbles &amp;lt;ref name=&amp;quot;dom-event-flow&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| ''mousedown'' || Mouse button pressed || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mousedown mousedown] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseup'' || Mouse button released || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseup mouseup] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''click'' || ''mousedown'' + ''mouseup'' have been triggered for this element without moving more than a certain maximum distance || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-click click] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''dblclick'' || Two ''click'' events have been triggered for this element without moving more than a certain maximum distance and time limit || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-dblclick dblclick] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''drag'' || The mouse has been moved with a button down. After dragging has started above an element, all consecutive ''drag'' events are sent to this element even if the mouse leaves its area || || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''wheel'' || Mouse wheel rotated (see deltaY for direction) || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-wheel wheel] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mousemove'' || Mouse has moved while beeing inside the area of the target element. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mousemove mousemove] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseover'' || Mouse has entered a child or the element itself. ''mouseover'' is also triggered if the mouse moves from one child element to another.  || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseover mouseover] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseout'' || Mouse has left a child or the element itself. ''mouseout'' is also triggered if the mouse moves from one child element to another. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseout mouseout] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseenter'' || Mouse has entered a child or the element itself. In contrary to ''mouseover'', ''mouseenter'' is not triggered if the mouse moves from one child element to another, but only the first time the element or one of its children is entered. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseenter mouseenter] || {{cross}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseleave'' || Mouse has left the element and all of its children. In contrary to ''mouseout'', ''mouseleave'' is not triggered if the mouse moves from one child element to another, but only if the mouse moves outside the element and all its children. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseleave mouseleave] || {{cross}}&lt;br /&gt;
|-&lt;br /&gt;
| ''keydown'' || A key was pressed down. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-keydown keydown] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''keyup'' || A key was released. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-keyup keyup] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''keypress'' || A key creating a printable character was pressed. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-keypress keypress] || {{tick}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Example Code =&lt;br /&gt;
(Note that this example makes use of advanced Nasal concepts, such as anonymous functions, method chaining and lots of embedded/inline code):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Canvas GUI demo&lt;br /&gt;
#&lt;br /&gt;
#  Shows an icon in the top-right corner which upon click opens a simple window&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
var dlg = canvas.Window.new([32,32]);&lt;br /&gt;
dlg.setInt(&amp;quot;tf/t[1]&amp;quot;, 4)&lt;br /&gt;
   .setInt(&amp;quot;right&amp;quot;, 4);&lt;br /&gt;
var my_canvas = dlg.createCanvas()&lt;br /&gt;
                   .set(&amp;quot;background&amp;quot;, &amp;quot;rgba(0,0,0,0)&amp;quot;);&lt;br /&gt;
var root = my_canvas.createGroup();&lt;br /&gt;
canvas.parsesvg(root, &amp;quot;gui/dialogs/images/icon-aircraft.svg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
my_canvas.addEventListener(&amp;quot;click&amp;quot;, func&lt;br /&gt;
{&lt;br /&gt;
  var dlg = canvas.Window.new([400,300], &amp;quot;dialog&amp;quot;);&lt;br /&gt;
  var my_canvas = dlg.createCanvas()&lt;br /&gt;
                     .set(&amp;quot;background&amp;quot;, &amp;quot;#f2f1f0&amp;quot;);&lt;br /&gt;
  var root = my_canvas.createGroup();&lt;br /&gt;
  root.addEventListener(&amp;quot;click&amp;quot;, func(e) {&lt;br /&gt;
    printf( &amp;quot;click: screen(%.1f|%.1f) client(%.1f|%.1f) click count = %d&amp;quot;,&lt;br /&gt;
            e.screenX, e.screenY,&lt;br /&gt;
            e.clientX, e.clientY,&lt;br /&gt;
            e.click_count );&lt;br /&gt;
  });&lt;br /&gt;
  root.addEventListener(&amp;quot;dblclick&amp;quot;, func(e) {&lt;br /&gt;
    printf( &amp;quot;dblclick: screen(%.1f|%.1f) client(%.1f|%.1f)&amp;quot;,&lt;br /&gt;
            e.screenX, e.screenY,&lt;br /&gt;
            e.clientX, e.clientY );&lt;br /&gt;
  });&lt;br /&gt;
  root.addEventListener(&amp;quot;wheel&amp;quot;, func(e) {&lt;br /&gt;
    printf( &amp;quot;wheel: screen(%.1f|%.1f) client(%.1f|%.1f) delta = %.1f&amp;quot;,&lt;br /&gt;
            e.screenX, e.screenY,&lt;br /&gt;
            e.clientX, e.clientY,&lt;br /&gt;
            e.deltaY );&lt;br /&gt;
  });&lt;br /&gt;
  var text =&lt;br /&gt;
    root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
        .setText( &amp;quot;This could be used for building an 'Aircraft Help' dialog.\n&amp;quot;&lt;br /&gt;
                ~ &amp;quot;You can also #use it to play around with the new Canvas system :). β&amp;quot; )&lt;br /&gt;
        .setTranslation(10, 30)&lt;br /&gt;
        .set(&amp;quot;alignment&amp;quot;, &amp;quot;left-top&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;character-size&amp;quot;, 14)&lt;br /&gt;
        .set(&amp;quot;font&amp;quot;, &amp;quot;LiberationFonts/LiberationSans-Regular.ttf&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;max-width&amp;quot;, 380)&lt;br /&gt;
        .set(&amp;quot;fill&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
  var text_move =&lt;br /&gt;
    root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
        .setText(&amp;quot;Mouse moved over text...&amp;quot;)&lt;br /&gt;
        .setTranslation(20, 200)&lt;br /&gt;
        .set(&amp;quot;alignment&amp;quot;, &amp;quot;left-center&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;character-size&amp;quot;, 15)&lt;br /&gt;
        .set(&amp;quot;font&amp;quot;, &amp;quot;LiberationFonts/LiberationSans-Bold.ttf&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;fill&amp;quot;, &amp;quot;#ff0000&amp;quot;)&lt;br /&gt;
        .hide();&lt;br /&gt;
  var visible_count = 0;&lt;br /&gt;
  text.addEventListener(&amp;quot;mouseover&amp;quot;, func text_move.show());&lt;br /&gt;
  text.addEventListener(&amp;quot;mouseout&amp;quot;, func text_move.hide());&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Canvas GUI]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=114445</id>
		<title>Template:Canvas Navigation</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=114445"/>
		<updated>2018-02-15T22:25:04Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
== Usage ==&lt;br /&gt;
Add the template to the top of the article text.&lt;br /&gt;
 {{obr}}'''Canvas Navigation'''{{cbr}}&lt;br /&gt;
&lt;br /&gt;
Adding the template to an page in the main namespace, the article namespace, or the howto namespace will add [[:Category:Canvas]] to the page.  In addition [[:Category:Howto]] will be added to articles in the howto namespace, and [[:Category:Core development projects]] will be added to articles in the main namespace.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Navigation templates]]&lt;br /&gt;
[[Category:Canvas]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;{{forum|71|Canvas}}&lt;br /&gt;
{{sidebar with collapsible headers&lt;br /&gt;
| name	= Canvas Navigation&lt;br /&gt;
| title = Canvas - the FlightGear 2D drawing API&lt;br /&gt;
| contentstyle = text-align: left;&lt;br /&gt;
| state = collapsed&lt;br /&gt;
&lt;br /&gt;
| content1 = &lt;br /&gt;
* [[Canvas]] - Main Page&lt;br /&gt;
* [[Canvas News]] - for the latest developments&lt;br /&gt;
* [[Canvas Efforts]] - projects using the Canvas system&lt;br /&gt;
* [[Canvas FAQs]] - frequently asked questions&lt;br /&gt;
* [[Canvas - Getting started]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
(as of 07/2015 this hasn't been updated ...)&lt;br /&gt;
* [[Canvas-hackers]] (team clone)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
* [[Canvas Development]] (core)&lt;br /&gt;
* [[Canvas Troubleshooting]] (core)&lt;br /&gt;
* [[Canvas Sandbox]] (core)&lt;br /&gt;
* [[Canvas Scenery Overlays]] (RFC)&lt;br /&gt;
* [[Howto:Processing legacy PUI dialogs using Canvas|PUI2Canvas]] (PUI/XML Parser)&lt;br /&gt;
* [[Canvas GUI]]&lt;br /&gt;
* [[Canvas Widgets]]&lt;br /&gt;
* [[Canvas Maps]]&lt;br /&gt;
* [[Canvas Snippets]]&lt;br /&gt;
&lt;br /&gt;
| heading2 = Frameworks&lt;br /&gt;
| content2 = &lt;br /&gt;
{{Canvas Frameworks|mode=navbar}}&lt;br /&gt;
* [[Canvas Glass Cockpit Efforts]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[How the Canvas subsystem works]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| heading3 = Tutorials&lt;br /&gt;
| content3 =&lt;br /&gt;
* [[Howto:Getting started with Canvas]]&lt;br /&gt;
* [[Howto: Canvas Troubleshooting]]&lt;br /&gt;
* [[Howto:Adding a canvas to a GUI dialog]] (PUI!)&lt;br /&gt;
* [[Howto:Creating a Canvas GUI dialog file]] (New)&lt;br /&gt;
* [[Howto:Dynamic Liveries via Canvas]] (new)&lt;br /&gt;
* [[Howto:Creating a Canvas GUI Widget]]&lt;br /&gt;
* [[Howto:Add a 2D canvas instrument to your aircraft]]&lt;br /&gt;
* [[Howto:Parsing 2D Instruments using the Canvas]]&lt;br /&gt;
* [[Howto:Creating fullscreen Canvas applications]]&lt;br /&gt;
* [[Howto:Use SVG inside a Canvas]]&lt;br /&gt;
* [[Howto:Extend the Canvas SVG module]]&lt;br /&gt;
* [[Howto:Serializing a Canvas to SVG]]&lt;br /&gt;
* [[Howto:Canvas applications as Nasal submodules]]&lt;br /&gt;
* [[Howto:Using raster images and nested canvases]]&lt;br /&gt;
&amp;lt;!-- * [[Howto:Creating Canvas Widgets in Nasal]] --&amp;gt;&lt;br /&gt;
* [[Howto:Creating a Canvas graph widget]]&lt;br /&gt;
* [[Canvas HUD]]&lt;br /&gt;
| heading4 = Reference&lt;br /&gt;
| content4 =&lt;br /&gt;
* [[Canvas Element]]&lt;br /&gt;
** [[Canvas Group|Group]]&lt;br /&gt;
** [[Canvas Image|Image]]&lt;br /&gt;
** [[Canvas Map|Map]]&lt;br /&gt;
** [[Canvas Path|Path]]&lt;br /&gt;
** [[Canvas Text|Text]]&lt;br /&gt;
* [[Canvas Nasal API]]&lt;br /&gt;
** [[Canvas MessageBox|MessageBox]]&lt;br /&gt;
** [[Canvas Layout System|Layout System]]&lt;br /&gt;
* [[Canvas GUI API]]&lt;br /&gt;
* [[Canvas Event Handling|Event Handling]]&lt;br /&gt;
| heading5 = Related&lt;br /&gt;
| content5 =&lt;br /&gt;
* [[Canvas Properties]]&lt;br /&gt;
* [[Unifying the 2D rendering backend via canvas]]&lt;br /&gt;
* [[Howto:Create a 2D drawing API for FlightGear]]&lt;br /&gt;
* [[Howto:Use a Camera View in an Instrument]]&lt;br /&gt;
* [[Howto:Extending Canvas to support rendering 3D models]]&lt;br /&gt;
&lt;br /&gt;
| heading6 = To be ported&lt;br /&gt;
| content6 = &lt;br /&gt;
* [[Navigation display]] {{Progressbar|70}}&lt;br /&gt;
* [[Map]] {{Progressbar|80}}&lt;br /&gt;
* [[FGCanvas]] {{Progressbar|20}}&lt;br /&gt;
* [[Canvas Nasal/JavaScript Subset]]&lt;br /&gt;
&lt;br /&gt;
| heading7 = Deprecated by Canvas&lt;br /&gt;
| content7 =&lt;br /&gt;
* [[Complex Glass Cockpit Avionics]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;includeonly&amp;gt;{{main other|[[Category:Canvas]][[Category:Core development projects]]}}&lt;br /&gt;
{{howto other|[[Category:Canvas]][[Category:Howto]]}}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_Image&amp;diff=114204</id>
		<title>Canvas Image</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_Image&amp;diff=114204"/>
		<updated>2018-02-01T07:45:39Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Fix url&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas Elements]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
= Properties =&lt;br /&gt;
&lt;br /&gt;
Additionally to the properties supported by every [[Canvas Element]], Canvas Images support the following properties:&lt;br /&gt;
&lt;br /&gt;
== src ==&lt;br /&gt;
&lt;br /&gt;
* '''Version''': FlightGear &amp;gt;= 3.1&lt;br /&gt;
* '''Format''': [&amp;lt;protocol&amp;gt;://]&amp;lt;path&amp;gt; (Supported protocols: canvas://, &amp;lt;nowiki&amp;gt;http://&amp;lt;/nowiki&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Use file inside default search paths&lt;br /&gt;
img.set(&amp;quot;src&amp;quot;, &amp;quot;gui/dialogs/images/exit.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# Show canvas with index 3&lt;br /&gt;
img.set(&amp;quot;src&amp;quot;, &amp;quot;canvas://by-index/texture[3]&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# Download and show FlightGear logo&lt;br /&gt;
img.set(&amp;quot;src&amp;quot;, &amp;quot;http://wiki.flightgear.org/skins/common/images/icons-fg-135.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# Show canvas available as object&lt;br /&gt;
img.set(&amp;quot;src&amp;quot;, my_canvas.getPath());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== x/y ==&lt;br /&gt;
== size ==&lt;br /&gt;
&lt;br /&gt;
== fill ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;lt;color&amp;gt; (#rrggbb, rbg(r,g,b), rgba(r,g,b,a) [r,g,b -&amp;gt; 0-255; a -&amp;gt; 0.0-1.0])&lt;br /&gt;
* '''Default''': #ffffff (white)&lt;br /&gt;
&lt;br /&gt;
Image background color. Each pixel is modulated with the background color. If the image shall be displayed unchanged use white as background color.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# White with alpha of 0.5 (=half transparent)&lt;br /&gt;
img.set(&amp;quot;fill&amp;quot;, &amp;quot;rgba(255,255,255,0.5)&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# red completely opaque&lt;br /&gt;
img.set(&amp;quot;fill&amp;quot;, &amp;quot;#ff0000&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== slice ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': [&amp;lt;number&amp;gt;%?]{1,4} fill?&lt;br /&gt;
* '''Default''': (empty) (disabled)&lt;br /&gt;
&lt;br /&gt;
Image slicing (or scale-9, 9-slice) is a technique for dividing an image into nine regions. While scaling such an image the four corner regions will be shown undistorted, whereas the other regions are scaled to fit into the remaining parts. See the CSS3 [https://www.w3.org/TR/css-backgrounds-3/#the-border-image-slice border-image-slice] property for more information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Top/bottom offset 10%, left/right offset 5%, fill center&lt;br /&gt;
img.set(&amp;quot;slice&amp;quot;, &amp;quot;10% 5% fill&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# All offsets 8 pixels, only draw border and do not fill center&lt;br /&gt;
img.set(&amp;quot;slice&amp;quot;, &amp;quot;8&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# Disable slicing&lt;br /&gt;
img.set(&amp;quot;slice&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== outset ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': [&amp;lt;number&amp;gt;%?]{1,4}&lt;br /&gt;
* '''Default''': (empty) (disabled)&lt;br /&gt;
&lt;br /&gt;
Let the image extend outside its specified size. The areas extending outside the original dimensions are just drawn but not included in the bounding box, and therefore ignored for event handling and distance/margin calculations. This could be used, for example, to draw a shadow around an element which is ignored for handling events.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Top outset 10%, left/right outset 5%, bottom outset 10 pixels&lt;br /&gt;
img.set(&amp;quot;outset&amp;quot;, &amp;quot;10% 5% 10&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# All offsets 8 pixels&lt;br /&gt;
img.set(&amp;quot;outset&amp;quot;, &amp;quot;8&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# Disable outset&lt;br /&gt;
img.set(&amp;quot;outset&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== file (deprecated) ==&lt;br /&gt;
&lt;br /&gt;
* '''Version''': FlightGear &amp;lt;= 3.0&lt;br /&gt;
&lt;br /&gt;
Same as ''src''. Use ''src'' with FlightGear &amp;gt;= 3.1.&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_Path&amp;diff=114143</id>
		<title>Canvas Path</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_Path&amp;diff=114143"/>
		<updated>2018-01-29T18:24:48Z</updated>

		<summary type="html">&lt;p&gt;TheTom: New and missing properties.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas Elements]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
= Properties =&lt;br /&gt;
&lt;br /&gt;
Additionally to the properties supported by every [[Canvas Element]], Canvas Paths support the following properties:&lt;br /&gt;
&lt;br /&gt;
== fill ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;none&amp;quot; | &amp;lt;color&amp;gt; (#rrggbb, rbg(r,g,b), rgba(r,g,b,a) [r,g,b -&amp;gt; 0-255; a -&amp;gt; 0.0-1.0])&lt;br /&gt;
* '''Default''': &amp;quot;none&amp;quot; (do not fill path)&lt;br /&gt;
&lt;br /&gt;
Color to fill the path.&lt;br /&gt;
&lt;br /&gt;
== fill-opacity ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;lt;number&amp;gt; (any real number between 0.0 and 1.0)&lt;br /&gt;
* '''Default''': 1.0 (not transparent)&lt;br /&gt;
&lt;br /&gt;
Factor to multiply the alpha channel of the ''fill'' color.&lt;br /&gt;
&lt;br /&gt;
== fill-rule ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;pseudo-nonzero&amp;quot; | &amp;quot;evenodd&amp;quot;&lt;br /&gt;
* '''Default''': &amp;quot;evenodd&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== stroke ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;none&amp;quot; | &amp;lt;color&amp;gt; (#rrggbb, rbg(r,g,b), rgba(r,g,b,a) [r,g,b -&amp;gt; 0-255; a -&amp;gt; 0.0-1.0])&lt;br /&gt;
* '''Default''': &amp;quot;none&amp;quot; (do not draw path)&lt;br /&gt;
&lt;br /&gt;
Color to draw the path.&lt;br /&gt;
&lt;br /&gt;
== stroke-opacity ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;lt;number&amp;gt; (any real number between 0.0 and 1.0)&lt;br /&gt;
* '''Default''': 1.0 (not transparent)&lt;br /&gt;
&lt;br /&gt;
Factor to multiply the alpha channel of the ''stroke'' color.&lt;br /&gt;
&lt;br /&gt;
== stroke-width ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;lt;number&amp;gt; (any real number)&lt;br /&gt;
* '''Default''': 1.0&lt;br /&gt;
&lt;br /&gt;
Specify the width (in pixels) of the stroke used to draw the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# 5 pixel wide, red stroke&lt;br /&gt;
path.set(&amp;quot;stroke&amp;quot;, &amp;quot;red&amp;quot;)&lt;br /&gt;
    .set(&amp;quot;stroke-width&amp;quot;, 5);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== stroke-dasharray ==&lt;br /&gt;
&lt;br /&gt;
Line stipple (see [http://www.w3.org/TR/SVG/painting.html#StrokeDasharrayProperty SVG stroke-dasharray])&lt;br /&gt;
&lt;br /&gt;
== stroke-linecap ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;round&amp;quot; | &amp;quot;square&amp;quot; | &amp;quot;butt&amp;quot;&lt;br /&gt;
* '''Default''': &amp;quot;butt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Line end (see [http://www.w3.org/TR/SVG/painting.html#StrokeLinecapProperty SVG stroke-linecap])&lt;br /&gt;
&lt;br /&gt;
== stroke-linejoin ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;round&amp;quot; | &amp;quot;bevel&amp;quot; | &amp;quot;miter&amp;quot;&lt;br /&gt;
* '''Default''': &amp;quot;miter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Line corner (see [http://www.w3.org/TR/SVG/painting.html#StrokeLinejoinProperty SVG stroke-linejoin])&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=83776</id>
		<title>Canvas snippets</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=83776"/>
		<updated>2015-04-30T14:24:21Z</updated>

		<summary type="html">&lt;p&gt;TheTom: /* A simple tile map */ Tilesize&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{-}}&lt;br /&gt;
This article is meant to be a collection of self-contained code snippets for doing Nasal/Canvas coding without having to spend too much time working through APIs, documentation and existing code - the idea is to provide snippets that contain comments and explicit assumptions, so that these snippets can be easily adapted by people without necessarily having to be very familiar with Nasal/Canvas coding. In the long term, we're hoping to grow a library of useful code snippets to cover most use-cases, while also covering more complex scenarios, e.g. using Canvas-specific helper frameworks like [[Canvas MapStructure]], the [[NavDisplay]] or the recent CDU work.&lt;br /&gt;
&lt;br /&gt;
Canvas itself is designed to be front-end agnostic, meaning that it doesn't matter where a Canvas is used/displayed - this is accomplished by so called &amp;quot;placements&amp;quot;, which determine where a Canvas texture shown. Thus, the back-end logic can remain the same usually, so that GUI dialogs may show avionics, but also so that avionics may show GUI widgets, which also applies to HUDs, liveries and even placements within the FlightGear scenery.&lt;br /&gt;
&lt;br /&gt;
We encourage people to use the snippets listed below to get started with Nasal/Canvas coding, but also to provide feedback on extending/improving this article to make it even more accessible and useful. Equally, if you're aware of any Canvas-related efforts that may contain useful code snippets, please do feel free to add those snippets here. Even people who don't have any interest in coding itself are encouraged to get involved by helping test the snippets listed below, for which you only need to the [[Nasal Console]], and while you're at it, please also help provide/update screen shots for each code snippet.&lt;br /&gt;
&lt;br /&gt;
Contributions added to this article should ideally satisfy some requirements:&lt;br /&gt;
* be entirely self-contained&lt;br /&gt;
* contain good/clear comments&lt;br /&gt;
* have pointers/references to related code/use-cases&lt;br /&gt;
* make assumptions explicit&lt;br /&gt;
* contain screen shots for each example&lt;br /&gt;
* avoid overloaded symbol names to ensure that examples can be merged and adapted easily&lt;br /&gt;
* dependencies (svg files, images/textures etc) should always be chosen such that snippets always work using $FG_ROOT&lt;br /&gt;
* hard-coded assumptions (e.g. texture dimensions in terms of width/height etc) should be encapsulated using variables&lt;br /&gt;
 &lt;br /&gt;
{{Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Creating a standalone Canvas ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[Special:UploadWizard|Upload requested]] || &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;
var (width, height) = (512,512);&lt;br /&gt;
# Create a standalone Canvas (not attached to any GUI dialog/aircraft etc) &lt;br /&gt;
var myCanvas = canvas.new({&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Livery Test&amp;quot;,   # The name is optional but allow for easier identification&lt;br /&gt;
  &amp;quot;size&amp;quot;: [width, height], # Size of the underlying texture (should be a power of 2, required) [Resolution]&lt;br /&gt;
  &amp;quot;view&amp;quot;: [width, height],  # Virtual resolution (Defines the coordinate system of the canvas [Dimensions]&lt;br /&gt;
                        # which will be stretched the size of the texture, required)&lt;br /&gt;
  &amp;quot;mipmapping&amp;quot;: 1       # Enable mipmapping (optional)&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
# set background color&lt;br /&gt;
myCanvas.set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&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;
&lt;br /&gt;
# OPTIONAL: Create a Canvas dialog window to hold the canvas and show that it's working&lt;br /&gt;
# the Canvas is now standalone, i.e. continues to live once the dialog is closed!&lt;br /&gt;
var window = canvas.Window.new([width,height],&amp;quot;dialog&amp;quot;);&lt;br /&gt;
window.setCanvas(myCanvas);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Creating Tooltips ==&lt;br /&gt;
== Creating Popups ==&lt;br /&gt;
== Creating a Canvas GUI Window ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-dialog.png|left|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;.]] || {{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;
{{Canvas Snippets Boilerplate}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Raster Images ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas Snippets-raster image.png|thumb|Canvas snippet demonstrating how to load a raster image]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# path is relative to $FG_ROOT (base package)&lt;br /&gt;
var path = &amp;quot;Textures/Splash1.png&amp;quot;;&lt;br /&gt;
# create an image child for the texture&lt;br /&gt;
var child = root.createChild(&amp;quot;image&amp;quot;)&lt;br /&gt;
    .setFile(path)&lt;br /&gt;
    .setTranslation(100, 10)&lt;br /&gt;
    .setSize(130, 130);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Raster Images downloaded on demand ==&lt;br /&gt;
&lt;br /&gt;
The '''path''' could also just as well be a URL, i.e. a raster image retrieved via http - for example, the following snippet is entirely self-contained and can be pasted into the [[Nasal Console]] and directly executed &amp;quot;as is&amp;quot;: &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-raster-images-via-url.png|thumb|screen shot demonstrating how Nasal and Canvas can be used to display raster images downloaded on demand]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# create a new window, dimensions are 400 x 200, using the dialog decoration (i.e. titlebar)&lt;br /&gt;
var window = canvas.Window.new([400,200],&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().set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
# Using specific css colors would also be possible:&lt;br /&gt;
# myCanvas.set(&amp;quot;background&amp;quot;, &amp;quot;#ffaac0&amp;quot;);&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;
&lt;br /&gt;
&lt;br /&gt;
# path now a URL&lt;br /&gt;
var url = &amp;quot;http://www.worldwidetelescope.org/docs/Images/MapOfEarth.jpg&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
# create an image child for the texture&lt;br /&gt;
var child=root.createChild(&amp;quot;image&amp;quot;)&lt;br /&gt;
    .setFile( url ) &lt;br /&gt;
    .setTranslation(45,22) # centered, in relation to dialog coordinates&lt;br /&gt;
    .setSize(310,155); # image dimensions&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding OpenVG Paths ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Openvg-via-canvas.png|thumb|screen shot showing a simple Canvas GUI dialog demonstrating how to use OpenVG-path drawing via Nasal and Canvas]] &lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&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;
var graph = root.createChild(&amp;quot;group&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
var x_axis = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;x-axis&amp;quot;)&lt;br /&gt;
.moveTo(10, height/2)&lt;br /&gt;
.lineTo(width-10, height/2)&lt;br /&gt;
.setColor(1,0,0)&lt;br /&gt;
.setStrokeLineWidth(3);&lt;br /&gt;
&lt;br /&gt;
var y_axis = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;y-axis&amp;quot;)&lt;br /&gt;
.moveTo(10, 10)&lt;br /&gt;
.lineTo(10, height-10)&lt;br /&gt;
.setColor(0,0,1)&lt;br /&gt;
.setStrokeLineWidth(2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-openvg-quadTo.png|thumb|screen shot showing a simple Canvas GUI dialog demonstrating how to use OpenVG-path drawing via Nasal and Canvas (Canvas/OpenVG quadTo API for drawing curves)]] &lt;br /&gt;
| {{Note|This assumes that you are appending this to the snippet shown above.}}&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;
&lt;br /&gt;
var points = [	60,height-20, &lt;br /&gt;
		230,height-100,&lt;br /&gt;
		];&lt;br /&gt;
&lt;br /&gt;
var track = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;track&amp;quot;)&lt;br /&gt;
.moveTo(10, height/2)&lt;br /&gt;
.quadTo( points )&lt;br /&gt;
.setColor(0,1,0)&lt;br /&gt;
.setStrokeLineWidth(4);&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;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-openvg-cubicTo.png|thumb|screen shot showing a simple Canvas GUI dialog demonstrating how to use OpenVG-path drawing via Nasal and Canvas (Canvas/OpenVG cubicTo API for drawing curves)]] &lt;br /&gt;
| {{Note|This assumes that you are appending this to the snippet shown above.}}&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;
var points = [	60,height-20, &lt;br /&gt;
		120,height-120,&lt;br /&gt;
		230,height-100,&lt;br /&gt;
		];&lt;br /&gt;
&lt;br /&gt;
var track = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;track&amp;quot;)&lt;br /&gt;
.moveTo(10, height/2)&lt;br /&gt;
.cubicTo( points )&lt;br /&gt;
.setColor(0,1,0)&lt;br /&gt;
.setStrokeLineWidth(4);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Vector Images ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-svg-support.png|thumb|screen shot demonstrating how the scripted Nasal-based SVG parser can be used to dynamically turn SVG files into OpenVG instructions understood by Canvas]] &lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
# change the background color &lt;br /&gt;
myCanvas.set(&amp;quot;background&amp;quot;, &amp;quot;#ffaac0&amp;quot;);&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;
&lt;br /&gt;
var filename = &amp;quot;/Nasal/canvas/map/Images/boeingAirplane.svg&amp;quot;;&lt;br /&gt;
var svg_symbol = root.createChild('group');&lt;br /&gt;
canvas.parsesvg(svg_symbol, filename);&lt;br /&gt;
&lt;br /&gt;
svg_symbol.setTranslation(width/2,height/2);&lt;br /&gt;
&lt;br /&gt;
#svg_symbol.setScale(0.2);&lt;br /&gt;
#svg_symbol.setRotation(radians)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Using the SymbolCache ==&lt;br /&gt;
Whenever a symbol may need to be shown/instanced multiple times (possibly using different styling), it makes sense to use caching - otherwise, identical symbols would be treated as separate OpenVG groups, all of which would need to be rasterized/rendedered separately (i.e. 100 identical symbols would be updated/rendered one by one). &lt;br /&gt;
&lt;br /&gt;
Typically, a map may display multiple instances of an otherwise identical symbol (think VOR, NDB, DME etc) - equally, a multiplayer map may showing multiple aircraft symbols at the same time. In these cases, it makes sense to use the SymbolCache framework, which will render symbols into a separate Canvas texture and provide a texture map that can be treated as a lookup map, which even supports styling for otherwise identical symbols. To learn more, please refer to [[Canvas MapStructure#The_SymbolCache|SymbolCache]]&lt;br /&gt;
... &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-SymbolCache-Instancing.png|thumb|Screen shot showing a Canvas based GUI dialog that is using the SymbolCache for instancing multiple symbols (including support for styling)]] &lt;br /&gt;
| {{Caution|This is currently untested code}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# this is the function that draws a symbol using OpenVG paths&lt;br /&gt;
# it accepts a group to draw to and returns the rendered group &lt;br /&gt;
# to the caller&lt;br /&gt;
var drawVOR = func(group) {&lt;br /&gt;
    return group.createChild(&amp;quot;path&amp;quot;)&lt;br /&gt;
        .moveTo(-15,0)&lt;br /&gt;
        .lineTo(-7.5,12.5)&lt;br /&gt;
        .lineTo(7.5,12.5)&lt;br /&gt;
        .lineTo(15,0)&lt;br /&gt;
        .lineTo(7.5,-12.5)&lt;br /&gt;
        .lineTo(-7.5,-12.5)&lt;br /&gt;
        .close()&lt;br /&gt;
        .setStrokeLineWidth(line_width) # style-able&lt;br /&gt;
        .setColor(color); # style-able&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var style = { # styling related attributes (as per the draw* function above)&lt;br /&gt;
    line_width: 3,&lt;br /&gt;
    scale_factor: 1,&lt;br /&gt;
    color: [1,0,0],&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
# create a new cache entry for the styled symbol&lt;br /&gt;
var myCachedSymbol = canvas.StyleableCacheable.new(&lt;br /&gt;
    name:'myVOR', draw_func: drawVOR,&lt;br /&gt;
    cache: canvas.SymbolCache32x32, # the cache to be used&lt;br /&gt;
    draw_mode: canvas.SymbolCache.DRAW_CENTERED,&lt;br /&gt;
    relevant_keys: ['line_width', 'color'], # styling related attributes&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
var target = root.createChild('group');&lt;br /&gt;
&lt;br /&gt;
var x=0;&lt;br /&gt;
var y=height/2;&lt;br /&gt;
&lt;br /&gt;
var xoffset=50;&lt;br /&gt;
&lt;br /&gt;
# render 5 instances symbols using the style specified above&lt;br /&gt;
for (var i=0;i&amp;lt;5;i+=1) {&lt;br /&gt;
# look up the raster image for the symbol&lt;br /&gt;
# render it using the passed style and adjust scaling&lt;br /&gt;
var instanced = myCachedSymbol.render(target, style)&lt;br /&gt;
  .setScale(style.scale_factor)&lt;br /&gt;
  .setTranslation(x+=xoffset,y);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The example shown above uses a fixed symbol/icon cache that is set up while booting Flightgear - sometimes, we may need cache for different purposes. So, let's assume, we need a new/custom cache with a different resolution for each entry in the cache (e.g. 256x256), we can easily accomplish that by setting up a new cache like this: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var mySymbolCache256x256 = canvas.SymbolCache.new(1024,256);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding Text Elements ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:CanvasText-Hello-World.png|thumb|Screen shot showing the CanvasText example contributed by Necolatis]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var myText = root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
      .setText(&amp;quot;Hello world!&amp;quot;)&lt;br /&gt;
      .setFontSize(20, 0.9)          # font size (in texels) and font aspect ratio&lt;br /&gt;
      .setColor(1,0,0,1)             # red, fully opaque&lt;br /&gt;
      .setAlignment(&amp;quot;center-center&amp;quot;) # how the text is aligned to where you place it&lt;br /&gt;
      .setTranslation(160, 80);     # where to place the text&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding GUI Labels ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-Layout-Label-example-by-Necolatis.png|thumb|Canvas demo: Layouts and Labels (by Necolatis)]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. It also assumes you have a Layout item setup and called '''myLayoutItem'''.}}&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
var label = canvas.gui.widgets.Label.new(root, canvas.style, {wordWrap: 0}); # wordwrap: 0 will disable wordwrapping, to enable it use 1 instead&lt;br /&gt;
label.setText(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
myLayout.addItem(label);&lt;br /&gt;
&lt;br /&gt;
var label2 = canvas.gui.widgets.Label.new(root, canvas.style, {wordWrap: 0}); # wordwrap: 0 will disable wordwrapping, to enable it use 1 instead&lt;br /&gt;
label2.setText(&amp;quot;Hello FlightGear&amp;quot;);&lt;br /&gt;
myLayout.addItem(label2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding GUI Buttons (Layouts)==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-demo-layouts-and-buttons-by-Necolatis.png|thumb|Canvas snippet: buttons and layouts (by Necolatis)]] &lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. It also assumes you have a Layout item setup and called '''myLayoutItem'''.}}&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
# click button&lt;br /&gt;
&lt;br /&gt;
var button = canvas.gui.widgets.Button.new(root, canvas.style, {})&lt;br /&gt;
	.setText(&amp;quot;Click on me&amp;quot;)&lt;br /&gt;
	.setFixedSize(75, 25);&lt;br /&gt;
&lt;br /&gt;
button.listen(&amp;quot;clicked&amp;quot;, func {&lt;br /&gt;
        # add code here to react on click on button.&lt;br /&gt;
print(&amp;quot;Button clicked !&amp;quot;);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
myLayout.addItem(button);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-toggle-button-snippet-by-Necolatis.png|thumb|Canvas toggle button demo by Necolatis]]&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
var button = canvas.gui.widgets.Button.new(root, canvas.style, {})&lt;br /&gt;
        .setText(&amp;quot;Toggle me&amp;quot;)&lt;br /&gt;
        .setCheckable(1) # this indicates that is should be a toggle button&lt;br /&gt;
        .setChecked(0) # depressed by default&lt;br /&gt;
        .setFixedSize(75, 25);&lt;br /&gt;
&lt;br /&gt;
button.listen(&amp;quot;toggled&amp;quot;, func (e) {&lt;br /&gt;
        if( e.detail.checked ) {&lt;br /&gt;
            # add code here to react on button being depressed.&lt;br /&gt;
        } else {&lt;br /&gt;
            # add code here to react on button not being depressed.&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
myLayout.addItem(button);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Canvas Input Dialog ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Snippets-canvas-input-dialog.png|thumb|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;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Layouts ==&lt;br /&gt;
&lt;br /&gt;
== Using Styling ==&lt;br /&gt;
== Adding a HUD ==&lt;br /&gt;
== Adding a 2D Instrument ==&lt;br /&gt;
== Adding a 2D Panel ==&lt;br /&gt;
== Adding a PFD ==&lt;br /&gt;
&lt;br /&gt;
== Adding a Failure Mgmt Widget ==&lt;br /&gt;
{{Note|This kind of widget will typically be useful for dialogs requiring a method for managing aircraft specific system failures (e.g. an instructor console).}}&lt;br /&gt;
&lt;br /&gt;
== Adding a MapStructure map to a Canvas  ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-mapstructure-dialog.png|thumb|[[MapStructure]] layers shown in a Canvas GUI dialog]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var TestMap = root.createChild(&amp;quot;map&amp;quot;);&lt;br /&gt;
TestMap.setController(&amp;quot;Aircraft position&amp;quot;);&lt;br /&gt;
TestMap.setRange(25); &lt;br /&gt;
 &lt;br /&gt;
TestMap.setTranslation(    myCanvas.get(&amp;quot;view[0]&amp;quot;)/2,&lt;br /&gt;
                           myCanvas.get(&amp;quot;view[1]&amp;quot;)/2&lt;br /&gt;
                        );&lt;br /&gt;
var r = func(name,vis=1,zindex=nil) return caller(0)[0];&lt;br /&gt;
&lt;br /&gt;
foreach(var type; [r('APT'), r('VOR') ] )&lt;br /&gt;
 TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: type.zindex,);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Customizing MapStructure Styling  ==&lt;br /&gt;
{{WIP}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-mapstructure-dialog.png|thumb|[[MapStructure]] layers shown in a Canvas GUI dialog]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Using MapStructure and Overlays ==&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |Support for overlays using geo-referenced raster images isn't too well-developed currently, so would need to work with a few hard-coded assumptions (e.g. being specific to a certain raster image and map layout) - but maybe TheTom can provide a few more ideas on how to proceed from here - otherwise, the Map is normally not aware of any non-Map items, i.e. as long as the overlay is added &amp;quot;outside&amp;quot; the Map, it isn't even aware of the raster image - and when it is added as a map element, it would probably be rotated. So there's still some work needed here. But generally, this should work well enough even in its current form (the screen shot is purely based on the Canvas Snippets article, i.e. it just displays a Canvas GUI dialog, adds the downloaded raster image and then adds the MapStructure APS layer - without the Map being aware of the overlay/geo-referencing that is needed currently).&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=238316#p238316&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Using Canvas for visualizing orbital flights (cont'd PM)&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;Fri Apr 10&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-overlay-with-mapstructure.png|thumb|Using the [[MapStructure]] framework in conjunction with raster images as overlays]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== A simple tile map ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas - Tile map demo.png|thumb|A simple, canvas based tile map which is centered around the aircraft.]]&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;
var (width,height) = (768,512);&lt;br /&gt;
var tile_size = 256;&lt;br /&gt;
&lt;br /&gt;
var window = canvas.Window.new([width, height],&amp;quot;dialog&amp;quot;)&lt;br /&gt;
                   .set('title', &amp;quot;Tile map demo&amp;quot;);&lt;br /&gt;
var g = window.getCanvas(1)&lt;br /&gt;
              .createGroup();&lt;br /&gt;
&lt;br /&gt;
# Simple user interface (Buttons for zoom and label for displaying it)&lt;br /&gt;
var zoom = 10;&lt;br /&gt;
var type = &amp;quot;map&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
var ui_root = window.getCanvas().createGroup();&lt;br /&gt;
var vbox = canvas.VBoxLayout.new();&lt;br /&gt;
window.setLayout(vbox);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var button_in = canvas.gui.widgets.Button.new(ui_root, canvas.style, {})&lt;br /&gt;
                                  .setText(&amp;quot;+&amp;quot;)&lt;br /&gt;
                                  .listen(&amp;quot;clicked&amp;quot;, func changeZoom(1));&lt;br /&gt;
var button_out = canvas.gui.widgets.Button.new(ui_root, canvas.style, {})&lt;br /&gt;
                                  .setText(&amp;quot;-&amp;quot;)&lt;br /&gt;
                                  .listen(&amp;quot;clicked&amp;quot;, func changeZoom(-1));&lt;br /&gt;
button_in.setSizeHint([32, 32]);&lt;br /&gt;
button_out.setSizeHint([32, 32]);&lt;br /&gt;
&lt;br /&gt;
var label_zoom = canvas.gui.widgets.Label.new(ui_root, canvas.style, {});&lt;br /&gt;
&lt;br /&gt;
var button_box = canvas.HBoxLayout.new();&lt;br /&gt;
button_box.addItem(button_in);&lt;br /&gt;
button_box.addItem(label_zoom);&lt;br /&gt;
button_box.addItem(button_out);&lt;br /&gt;
button_box.addStretch(1);&lt;br /&gt;
&lt;br /&gt;
vbox.addItem(button_box);&lt;br /&gt;
vbox.addStretch(1);&lt;br /&gt;
&lt;br /&gt;
var changeZoom = func(d)&lt;br /&gt;
{&lt;br /&gt;
  zoom = math.max(2, math.min(19, zoom + d));&lt;br /&gt;
  label_zoom.setText(&amp;quot;Zoom &amp;quot; ~ zoom);&lt;br /&gt;
  updateTiles();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# http://polymaps.org/docs/&lt;br /&gt;
# https://github.com/simplegeo/polymaps&lt;br /&gt;
# https://github.com/Leaflet/Leaflet&lt;br /&gt;
&lt;br /&gt;
var maps_base = getprop(&amp;quot;/sim/fg-home&amp;quot;) ~ '/cache/maps';&lt;br /&gt;
&lt;br /&gt;
# http://otile1.mqcdn.com/tiles/1.0.0/map&lt;br /&gt;
# http://otile1.mqcdn.com/tiles/1.0.0/sat&lt;br /&gt;
# (also see http://wiki.openstreetmap.org/wiki/Tile_usage_policy)&lt;br /&gt;
var makeUrl =&lt;br /&gt;
  string.compileTemplate('http://otile1.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.jpg');&lt;br /&gt;
var makePath =&lt;br /&gt;
  string.compileTemplate(maps_base ~ '/osm-{type}/{z}/{x}/{y}.jpg');&lt;br /&gt;
var num_tiles = [4, 3];&lt;br /&gt;
&lt;br /&gt;
var center_tile_offset = [&lt;br /&gt;
  (num_tiles[0] - 1) / 2,&lt;br /&gt;
  (num_tiles[1] - 1) / 2&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
# simple aircraft icon at current position/center of the map&lt;br /&gt;
g.createChild(&amp;quot;path&amp;quot;)&lt;br /&gt;
 .moveTo( tile_size * center_tile_offset[0] - 10,&lt;br /&gt;
          tile_size * center_tile_offset[1] )&lt;br /&gt;
 .horiz(20)&lt;br /&gt;
 .move(-10,-10)&lt;br /&gt;
 .vert(20)&lt;br /&gt;
 .set(&amp;quot;stroke&amp;quot;, &amp;quot;red&amp;quot;)&lt;br /&gt;
 .set(&amp;quot;stroke-width&amp;quot;, 2)&lt;br /&gt;
 .set(&amp;quot;z-index&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# initialize the map by setting up&lt;br /&gt;
# a grid of raster images  &lt;br /&gt;
&lt;br /&gt;
var tiles = setsize([], num_tiles[0]);&lt;br /&gt;
for(var x = 0; x &amp;lt; num_tiles[0]; x += 1)&lt;br /&gt;
{&lt;br /&gt;
  tiles[x] = setsize([], num_tiles[1]);&lt;br /&gt;
  for(var y = 0; y &amp;lt; num_tiles[1]; y += 1)&lt;br /&gt;
    tiles[x][y] = g.createChild(&amp;quot;image&amp;quot;, &amp;quot;map-tile&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var last_tile = [-1,-1];&lt;br /&gt;
var last_type = type;&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# this is the callback that will be regularly called by the timer&lt;br /&gt;
# to update the map&lt;br /&gt;
var updateTiles = func()&lt;br /&gt;
{&lt;br /&gt;
  # get current position&lt;br /&gt;
  var lat = getprop('/position/latitude-deg');&lt;br /&gt;
  var lon = getprop('/position/longitude-deg');&lt;br /&gt;
&lt;br /&gt;
  var n = math.pow(2, zoom);&lt;br /&gt;
  var offset = [&lt;br /&gt;
    n * ((lon + 180) / 360) - center_tile_offset[0],&lt;br /&gt;
    (1 - math.ln(math.tan(lat * math.pi/180) + 1 / math.cos(lat * math.pi/180)) / math.pi) / 2 * n - center_tile_offset[1]&lt;br /&gt;
  ];&lt;br /&gt;
  var tile_index = [int(offset[0]), int(offset[1])];&lt;br /&gt;
&lt;br /&gt;
  var ox = tile_index[0] - offset[0];&lt;br /&gt;
  var oy = tile_index[1] - offset[1];&lt;br /&gt;
&lt;br /&gt;
  for(var x = 0; x &amp;lt; num_tiles[0]; x += 1)&lt;br /&gt;
    for(var y = 0; y &amp;lt; num_tiles[1]; y += 1)&lt;br /&gt;
      tiles[x][y].setTranslation(int((ox + x) * tile_size + 0.5), int((oy + y) * tile_size + 0.5));&lt;br /&gt;
&lt;br /&gt;
  if(    tile_index[0] != last_tile[0]&lt;br /&gt;
      or tile_index[1] != last_tile[1]&lt;br /&gt;
      or type != last_type )&lt;br /&gt;
  {&lt;br /&gt;
    for(var x = 0; x &amp;lt; num_tiles[0]; x += 1)&lt;br /&gt;
      for(var y = 0; y &amp;lt; num_tiles[1]; y += 1)&lt;br /&gt;
      {&lt;br /&gt;
        var pos = {&lt;br /&gt;
          z: zoom,&lt;br /&gt;
          x: int(offset[0] + x),&lt;br /&gt;
          y: int(offset[1] + y),&lt;br /&gt;
          type: type&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        (func {&lt;br /&gt;
        var img_path = makePath(pos);&lt;br /&gt;
        var tile = tiles[x][y];&lt;br /&gt;
&lt;br /&gt;
        if( io.stat(img_path) == nil )&lt;br /&gt;
        { # image not found, save in $FG_HOME&lt;br /&gt;
          var img_url = makeUrl(pos);&lt;br /&gt;
          print('requesting ' ~ img_url);&lt;br /&gt;
          http.save(img_url, img_path)&lt;br /&gt;
              .done(func {print('received image ' ~ img_path); tile.set(&amp;quot;src&amp;quot;, img_path);})&lt;br /&gt;
              .fail(func (r) print('Failed to get image ' ~ img_path ~ ' ' ~ r.status ~ ': ' ~ r.reason));&lt;br /&gt;
        }&lt;br /&gt;
        else # cached image found, reusing&lt;br /&gt;
        {&lt;br /&gt;
          print('loading ' ~ img_path);&lt;br /&gt;
          tile.set(&amp;quot;src&amp;quot;, img_path)&lt;br /&gt;
        }&lt;br /&gt;
        })();&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    last_tile = tile_index;&lt;br /&gt;
    last_type = type;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# set up a timer that will invoke updateTiles at 2-second intervals&lt;br /&gt;
var update_timer = maketimer(2, updateTiles);&lt;br /&gt;
# actually start the timer&lt;br /&gt;
update_timer.start();&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# set up default zoom level&lt;br /&gt;
changeZoom(0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding a NavDisplay ==&lt;br /&gt;
&lt;br /&gt;
== Adding a CDU ==&lt;br /&gt;
&lt;br /&gt;
== Adding a Multi-Function Display (MFD) ==&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=83768</id>
		<title>Canvas snippets</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=83768"/>
		<updated>2015-04-29T14:32:14Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Tile map demo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
{{-}}&lt;br /&gt;
This article is meant to be a collection of self-contained code snippets for doing Nasal/Canvas coding without having to spend too much time working through APIs, documentation and existing code - the idea is to provide snippets that contain comments and explicit assumptions, so that these snippets can be easily adapted by people without necessarily having to be very familiar with Nasal/Canvas coding. In the long term, we're hoping to grow a library of useful code snippets to cover most use-cases, while also covering more complex scenarios, e.g. using Canvas-specific helper frameworks like [[Canvas MapStructure]], the [[NavDisplay]] or the recent CDU work.&lt;br /&gt;
&lt;br /&gt;
Canvas itself is designed to be front-end agnostic, meaning that it doesn't matter where a Canvas is used/displayed - this is accomplished by so called &amp;quot;placements&amp;quot;, which determine where a Canvas texture shown. Thus, the back-end logic can remain the same usually, so that GUI dialogs may show avionics, but also so that avionics may show GUI widgets, which also applies to HUDs, liveries and even placements within the FlightGear scenery.&lt;br /&gt;
&lt;br /&gt;
We encourage people to use the snippets listed below to get started with Nasal/Canvas coding, but also to provide feedback on extending/improving this article to make it even more accessible and useful. Equally, if you're aware of any Canvas-related efforts that may contain useful code snippets, please do feel free to add those snippets here. Even people who don't have any interest in coding itself are encouraged to get involved by helping test the snippets listed below, for which you only need to the [[Nasal Console]], and while you're at it, please also help provide/update screen shots for each code snippet.&lt;br /&gt;
&lt;br /&gt;
Contributions added to this article should ideally satisfy some requirements:&lt;br /&gt;
* be entirely self-contained&lt;br /&gt;
* contain good/clear comments&lt;br /&gt;
* have pointers/references to related code/use-cases&lt;br /&gt;
* make assumptions explicit&lt;br /&gt;
* contain screen shots for each example&lt;br /&gt;
* avoid overloaded symbol names to ensure that examples can be merged and adapted easily&lt;br /&gt;
* dependencies (svg files, images/textures etc) should always be chosen such that snippets always work using $FG_ROOT&lt;br /&gt;
* hard-coded assumptions (e.g. texture dimensions in terms of width/height etc) should be encapsulated using variables&lt;br /&gt;
 &lt;br /&gt;
{{Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Creating a standalone Canvas ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[Special:UploadWizard|Upload requested]] || &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;
var (width, height) = (512,512);&lt;br /&gt;
# Create a standalone Canvas (not attached to any GUI dialog/aircraft etc) &lt;br /&gt;
var myCanvas = canvas.new({&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Livery Test&amp;quot;,   # The name is optional but allow for easier identification&lt;br /&gt;
  &amp;quot;size&amp;quot;: [width, height], # Size of the underlying texture (should be a power of 2, required) [Resolution]&lt;br /&gt;
  &amp;quot;view&amp;quot;: [width, height],  # Virtual resolution (Defines the coordinate system of the canvas [Dimensions]&lt;br /&gt;
                        # which will be stretched the size of the texture, required)&lt;br /&gt;
  &amp;quot;mipmapping&amp;quot;: 1       # Enable mipmapping (optional)&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
# set background color&lt;br /&gt;
myCanvas.set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&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;
&lt;br /&gt;
# OPTIONAL: Create a Canvas dialog window to hold the canvas and show that it's working&lt;br /&gt;
# the Canvas is now standalone, i.e. continues to live once the dialog is closed!&lt;br /&gt;
var window = canvas.Window.new([width,height],&amp;quot;dialog&amp;quot;);&lt;br /&gt;
window.setCanvas(myCanvas);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Creating Tooltips ==&lt;br /&gt;
== Creating Popups ==&lt;br /&gt;
== Creating a Canvas GUI Window ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-dialog.png|left|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;.]] || {{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;
{{Canvas Snippets Boilerplate}}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Raster Images ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas Snippets-raster image.png|thumb|Canvas snippet demonstrating how to load a raster image]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# path is relative to $FG_ROOT (base package)&lt;br /&gt;
var path = &amp;quot;Textures/Splash1.png&amp;quot;;&lt;br /&gt;
# create an image child for the texture&lt;br /&gt;
var child = root.createChild(&amp;quot;image&amp;quot;)&lt;br /&gt;
    .setFile(path)&lt;br /&gt;
    .setTranslation(100, 10)&lt;br /&gt;
    .setSize(130, 130);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Raster Images downloaded on demand ==&lt;br /&gt;
&lt;br /&gt;
The '''path''' could also just as well be a URL, i.e. a raster image retrieved via http - for example, the following snippet is entirely self-contained and can be pasted into the [[Nasal Console]] and directly executed &amp;quot;as is&amp;quot;: &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-raster-images-via-url.png|thumb|screen shot demonstrating how Nasal and Canvas can be used to display raster images downloaded on demand]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# create a new window, dimensions are 400 x 200, using the dialog decoration (i.e. titlebar)&lt;br /&gt;
var window = canvas.Window.new([400,200],&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().set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
# Using specific css colors would also be possible:&lt;br /&gt;
# myCanvas.set(&amp;quot;background&amp;quot;, &amp;quot;#ffaac0&amp;quot;);&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;
&lt;br /&gt;
&lt;br /&gt;
# path now a URL&lt;br /&gt;
var url = &amp;quot;http://www.worldwidetelescope.org/docs/Images/MapOfEarth.jpg&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
# create an image child for the texture&lt;br /&gt;
var child=root.createChild(&amp;quot;image&amp;quot;)&lt;br /&gt;
    .setFile( url ) &lt;br /&gt;
    .setTranslation(45,22) # centered, in relation to dialog coordinates&lt;br /&gt;
    .setSize(310,155); # image dimensions&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding OpenVG Paths ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Openvg-via-canvas.png|thumb|screen shot showing a simple Canvas GUI dialog demonstrating how to use OpenVG-path drawing via Nasal and Canvas]] &lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&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;
var graph = root.createChild(&amp;quot;group&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
var x_axis = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;x-axis&amp;quot;)&lt;br /&gt;
.moveTo(10, height/2)&lt;br /&gt;
.lineTo(width-10, height/2)&lt;br /&gt;
.setColor(1,0,0)&lt;br /&gt;
.setStrokeLineWidth(3);&lt;br /&gt;
&lt;br /&gt;
var y_axis = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;y-axis&amp;quot;)&lt;br /&gt;
.moveTo(10, 10)&lt;br /&gt;
.lineTo(10, height-10)&lt;br /&gt;
.setColor(0,0,1)&lt;br /&gt;
.setStrokeLineWidth(2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-openvg-quadTo.png|thumb|screen shot showing a simple Canvas GUI dialog demonstrating how to use OpenVG-path drawing via Nasal and Canvas (Canvas/OpenVG quadTo API for drawing curves)]] &lt;br /&gt;
| {{Note|This assumes that you are appending this to the snippet shown above.}}&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;
&lt;br /&gt;
var points = [	60,height-20, &lt;br /&gt;
		230,height-100,&lt;br /&gt;
		];&lt;br /&gt;
&lt;br /&gt;
var track = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;track&amp;quot;)&lt;br /&gt;
.moveTo(10, height/2)&lt;br /&gt;
.quadTo( points )&lt;br /&gt;
.setColor(0,1,0)&lt;br /&gt;
.setStrokeLineWidth(4);&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;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-openvg-cubicTo.png|thumb|screen shot showing a simple Canvas GUI dialog demonstrating how to use OpenVG-path drawing via Nasal and Canvas (Canvas/OpenVG cubicTo API for drawing curves)]] &lt;br /&gt;
| {{Note|This assumes that you are appending this to the snippet shown above.}}&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;
var points = [	60,height-20, &lt;br /&gt;
		120,height-120,&lt;br /&gt;
		230,height-100,&lt;br /&gt;
		];&lt;br /&gt;
&lt;br /&gt;
var track = graph.createChild(&amp;quot;path&amp;quot;, &amp;quot;track&amp;quot;)&lt;br /&gt;
.moveTo(10, height/2)&lt;br /&gt;
.cubicTo( points )&lt;br /&gt;
.setColor(0,1,0)&lt;br /&gt;
.setStrokeLineWidth(4);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Vector Images ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-svg-support.png|thumb|screen shot demonstrating how the scripted Nasal-based SVG parser can be used to dynamically turn SVG files into OpenVG instructions understood by Canvas]] &lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
# change the background color &lt;br /&gt;
myCanvas.set(&amp;quot;background&amp;quot;, &amp;quot;#ffaac0&amp;quot;);&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;
&lt;br /&gt;
var filename = &amp;quot;/Nasal/canvas/map/Images/boeingAirplane.svg&amp;quot;;&lt;br /&gt;
var svg_symbol = root.createChild('group');&lt;br /&gt;
canvas.parsesvg(svg_symbol, filename);&lt;br /&gt;
&lt;br /&gt;
svg_symbol.setTranslation(width/2,height/2);&lt;br /&gt;
&lt;br /&gt;
#svg_symbol.setScale(0.2);&lt;br /&gt;
#svg_symbol.setRotation(radians)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Using the SymbolCache ==&lt;br /&gt;
Whenever a symbol may need to be shown/instanced multiple times (possibly using different styling), it makes sense to use caching - otherwise, identical symbols would be treated as separate OpenVG groups, all of which would need to be rasterized/rendedered separately (i.e. 100 identical symbols would be updated/rendered one by one). &lt;br /&gt;
&lt;br /&gt;
Typically, a map may display multiple instances of an otherwise identical symbol (think VOR, NDB, DME etc) - equally, a multiplayer map may showing multiple aircraft symbols at the same time. In these cases, it makes sense to use the SymbolCache framework, which will render symbols into a separate Canvas texture and provide a texture map that can be treated as a lookup map, which even supports styling for otherwise identical symbols. To learn more, please refer to [[Canvas MapStructure#The_SymbolCache|SymbolCache]]&lt;br /&gt;
... &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-SymbolCache-Instancing.png|thumb|Screen shot showing a Canvas based GUI dialog that is using the SymbolCache for instancing multiple symbols (including support for styling)]] &lt;br /&gt;
| {{Caution|This is currently untested code}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# this is the function that draws a symbol using OpenVG paths&lt;br /&gt;
# it accepts a group to draw to and returns the rendered group &lt;br /&gt;
# to the caller&lt;br /&gt;
var drawVOR = func(group) {&lt;br /&gt;
    return group.createChild(&amp;quot;path&amp;quot;)&lt;br /&gt;
        .moveTo(-15,0)&lt;br /&gt;
        .lineTo(-7.5,12.5)&lt;br /&gt;
        .lineTo(7.5,12.5)&lt;br /&gt;
        .lineTo(15,0)&lt;br /&gt;
        .lineTo(7.5,-12.5)&lt;br /&gt;
        .lineTo(-7.5,-12.5)&lt;br /&gt;
        .close()&lt;br /&gt;
        .setStrokeLineWidth(line_width) # style-able&lt;br /&gt;
        .setColor(color); # style-able&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var style = { # styling related attributes (as per the draw* function above)&lt;br /&gt;
    line_width: 3,&lt;br /&gt;
    scale_factor: 1,&lt;br /&gt;
    color: [1,0,0],&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
# create a new cache entry for the styled symbol&lt;br /&gt;
var myCachedSymbol = canvas.StyleableCacheable.new(&lt;br /&gt;
    name:'myVOR', draw_func: drawVOR,&lt;br /&gt;
    cache: canvas.SymbolCache32x32, # the cache to be used&lt;br /&gt;
    draw_mode: canvas.SymbolCache.DRAW_CENTERED,&lt;br /&gt;
    relevant_keys: ['line_width', 'color'], # styling related attributes&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
var target = root.createChild('group');&lt;br /&gt;
&lt;br /&gt;
var x=0;&lt;br /&gt;
var y=height/2;&lt;br /&gt;
&lt;br /&gt;
var xoffset=50;&lt;br /&gt;
&lt;br /&gt;
# render 5 instances symbols using the style specified above&lt;br /&gt;
for (var i=0;i&amp;lt;5;i+=1) {&lt;br /&gt;
# look up the raster image for the symbol&lt;br /&gt;
# render it using the passed style and adjust scaling&lt;br /&gt;
var instanced = myCachedSymbol.render(target, style)&lt;br /&gt;
  .setScale(style.scale_factor)&lt;br /&gt;
  .setTranslation(x+=xoffset,y);&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The example shown above uses a fixed symbol/icon cache that is set up while booting Flightgear - sometimes, we may need cache for different purposes. So, let's assume, we need a new/custom cache with a different resolution for each entry in the cache (e.g. 256x256), we can easily accomplish that by setting up a new cache like this: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var mySymbolCache256x256 = canvas.SymbolCache.new(1024,256);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Adding Text Elements ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:CanvasText-Hello-World.png|thumb|Screen shot showing the CanvasText example contributed by Necolatis]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var myText = root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
      .setText(&amp;quot;Hello world!&amp;quot;)&lt;br /&gt;
      .setFontSize(20, 0.9)          # font size (in texels) and font aspect ratio&lt;br /&gt;
      .setColor(1,0,0,1)             # red, fully opaque&lt;br /&gt;
      .setAlignment(&amp;quot;center-center&amp;quot;) # how the text is aligned to where you place it&lt;br /&gt;
      .setTranslation(160, 80);     # where to place the text&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding GUI Labels ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-Layout-Label-example-by-Necolatis.png|thumb|Canvas demo: Layouts and Labels (by Necolatis)]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. It also assumes you have a Layout item setup and called '''myLayoutItem'''.}}&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
var label = canvas.gui.widgets.Label.new(root, canvas.style, {wordWrap: 0}); # wordwrap: 0 will disable wordwrapping, to enable it use 1 instead&lt;br /&gt;
label.setText(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
myLayout.addItem(label);&lt;br /&gt;
&lt;br /&gt;
var label2 = canvas.gui.widgets.Label.new(root, canvas.style, {wordWrap: 0}); # wordwrap: 0 will disable wordwrapping, to enable it use 1 instead&lt;br /&gt;
label2.setText(&amp;quot;Hello FlightGear&amp;quot;);&lt;br /&gt;
myLayout.addItem(label2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding GUI Buttons (Layouts)==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-demo-layouts-and-buttons-by-Necolatis.png|thumb|Canvas snippet: buttons and layouts (by Necolatis)]] &lt;br /&gt;
|&lt;br /&gt;
&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. It also assumes you have a Layout item setup and called '''myLayoutItem'''.}}&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
# click button&lt;br /&gt;
&lt;br /&gt;
var button = canvas.gui.widgets.Button.new(root, canvas.style, {})&lt;br /&gt;
	.setText(&amp;quot;Click on me&amp;quot;)&lt;br /&gt;
	.setFixedSize(75, 25);&lt;br /&gt;
&lt;br /&gt;
button.listen(&amp;quot;clicked&amp;quot;, func {&lt;br /&gt;
        # add code here to react on click on button.&lt;br /&gt;
print(&amp;quot;Button clicked !&amp;quot;);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
myLayout.addItem(button);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-toggle-button-snippet-by-Necolatis.png|thumb|Canvas toggle button demo by Necolatis]]&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
var button = canvas.gui.widgets.Button.new(root, canvas.style, {})&lt;br /&gt;
        .setText(&amp;quot;Toggle me&amp;quot;)&lt;br /&gt;
        .setCheckable(1) # this indicates that is should be a toggle button&lt;br /&gt;
        .setChecked(0) # depressed by default&lt;br /&gt;
        .setFixedSize(75, 25);&lt;br /&gt;
&lt;br /&gt;
button.listen(&amp;quot;toggled&amp;quot;, func (e) {&lt;br /&gt;
        if( e.detail.checked ) {&lt;br /&gt;
            # add code here to react on button being depressed.&lt;br /&gt;
        } else {&lt;br /&gt;
            # add code here to react on button not being depressed.&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
myLayout.addItem(button);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Canvas Input Dialog ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Snippets-canvas-input-dialog.png|thumb|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;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Layouts ==&lt;br /&gt;
&lt;br /&gt;
== Using Styling ==&lt;br /&gt;
== Adding a HUD ==&lt;br /&gt;
== Adding a 2D Instrument ==&lt;br /&gt;
== Adding a 2D Panel ==&lt;br /&gt;
== Adding a PFD ==&lt;br /&gt;
&lt;br /&gt;
== Adding a Failure Mgmt Widget ==&lt;br /&gt;
{{Note|This kind of widget will typically be useful for dialogs requiring a method for managing aircraft specific system failures (e.g. an instructor console).}}&lt;br /&gt;
&lt;br /&gt;
== Adding a MapStructure map to a Canvas  ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-mapstructure-dialog.png|thumb|[[MapStructure]] layers shown in a Canvas GUI dialog]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var TestMap = root.createChild(&amp;quot;map&amp;quot;);&lt;br /&gt;
TestMap.setController(&amp;quot;Aircraft position&amp;quot;);&lt;br /&gt;
TestMap.setRange(25); &lt;br /&gt;
 &lt;br /&gt;
TestMap.setTranslation(    myCanvas.get(&amp;quot;view[0]&amp;quot;)/2,&lt;br /&gt;
                           myCanvas.get(&amp;quot;view[1]&amp;quot;)/2&lt;br /&gt;
                        );&lt;br /&gt;
var r = func(name,vis=1,zindex=nil) return caller(0)[0];&lt;br /&gt;
&lt;br /&gt;
foreach(var type; [r('APT'), r('VOR') ] )&lt;br /&gt;
 TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: type.zindex,);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Customizing MapStructure Styling  ==&lt;br /&gt;
{{WIP}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-mapstructure-dialog.png|thumb|[[MapStructure]] layers shown in a Canvas GUI dialog]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Using MapStructure and Overlays ==&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |Support for overlays using geo-referenced raster images isn't too well-developed currently, so would need to work with a few hard-coded assumptions (e.g. being specific to a certain raster image and map layout) - but maybe TheTom can provide a few more ideas on how to proceed from here - otherwise, the Map is normally not aware of any non-Map items, i.e. as long as the overlay is added &amp;quot;outside&amp;quot; the Map, it isn't even aware of the raster image - and when it is added as a map element, it would probably be rotated. So there's still some work needed here. But generally, this should work well enough even in its current form (the screen shot is purely based on the Canvas Snippets article, i.e. it just displays a Canvas GUI dialog, adds the downloaded raster image and then adds the MapStructure APS layer - without the Map being aware of the overlay/geo-referencing that is needed currently).&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=238316#p238316&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Using Canvas for visualizing orbital flights (cont'd PM)&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;Fri Apr 10&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-overlay-with-mapstructure.png|thumb|Using the [[MapStructure]] framework in conjunction with raster images as overlays]]&lt;br /&gt;
| {{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== A simple tile map ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas - Tile map demo.png|thumb|A simple, canvas based tile map which is centered around the aircraft.]]&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;
var window = canvas.Window.new([768, 512],&amp;quot;dialog&amp;quot;)&lt;br /&gt;
                   .set('title', &amp;quot;Tile map demo&amp;quot;);&lt;br /&gt;
var g = window.getCanvas(1)&lt;br /&gt;
              .createGroup();&lt;br /&gt;
&lt;br /&gt;
# Simple user interface (Buttons for zoom and label for displaying it)&lt;br /&gt;
var zoom = 10;&lt;br /&gt;
var type = &amp;quot;map&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
var ui_root = window.getCanvas().createGroup();&lt;br /&gt;
var vbox = canvas.VBoxLayout.new();&lt;br /&gt;
window.setLayout(vbox);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var button_in = canvas.gui.widgets.Button.new(ui_root, canvas.style, {})&lt;br /&gt;
                                  .setText(&amp;quot;+&amp;quot;)&lt;br /&gt;
                                  .listen(&amp;quot;clicked&amp;quot;, func changeZoom(1));&lt;br /&gt;
var button_out = canvas.gui.widgets.Button.new(ui_root, canvas.style, {})&lt;br /&gt;
                                  .setText(&amp;quot;-&amp;quot;)&lt;br /&gt;
                                  .listen(&amp;quot;clicked&amp;quot;, func changeZoom(-1));&lt;br /&gt;
button_in.setSizeHint([32, 32]);&lt;br /&gt;
button_out.setSizeHint([32, 32]);&lt;br /&gt;
&lt;br /&gt;
var label_zoom = canvas.gui.widgets.Label.new(ui_root, canvas.style, {});&lt;br /&gt;
&lt;br /&gt;
var button_box = canvas.HBoxLayout.new();&lt;br /&gt;
button_box.addItem(button_in);&lt;br /&gt;
button_box.addItem(label_zoom);&lt;br /&gt;
button_box.addItem(button_out);&lt;br /&gt;
button_box.addStretch(1);&lt;br /&gt;
&lt;br /&gt;
vbox.addItem(button_box);&lt;br /&gt;
vbox.addStretch(1);&lt;br /&gt;
&lt;br /&gt;
var changeZoom = func(d)&lt;br /&gt;
{&lt;br /&gt;
  zoom = math.max(2, math.min(19, zoom + d));&lt;br /&gt;
  label_zoom.setText(&amp;quot;Zoom &amp;quot; ~ zoom);&lt;br /&gt;
  updateTiles();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# http://polymaps.org/docs/&lt;br /&gt;
# https://github.com/simplegeo/polymaps&lt;br /&gt;
# https://github.com/Leaflet/Leaflet&lt;br /&gt;
&lt;br /&gt;
var maps_base = getprop(&amp;quot;/sim/fg-home&amp;quot;) ~ '/cache/maps';&lt;br /&gt;
&lt;br /&gt;
# http://otile1.mqcdn.com/tiles/1.0.0/map&lt;br /&gt;
# http://otile1.mqcdn.com/tiles/1.0.0/sat&lt;br /&gt;
# (also see http://wiki.openstreetmap.org/wiki/Tile_usage_policy)&lt;br /&gt;
var makeUrl =&lt;br /&gt;
  string.compileTemplate('http://otile1.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.jpg');&lt;br /&gt;
var makePath =&lt;br /&gt;
  string.compileTemplate(maps_base ~ '/osm-{type}/{z}/{x}/{y}.jpg');&lt;br /&gt;
var num_tiles = [4, 3];&lt;br /&gt;
&lt;br /&gt;
var center_tile_offset = [&lt;br /&gt;
  (num_tiles[0] - 1) / 2,&lt;br /&gt;
  (num_tiles[1] - 1) / 2&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
# simple aircraft icon at current position/center of the map&lt;br /&gt;
g.createChild(&amp;quot;path&amp;quot;)&lt;br /&gt;
 .moveTo( 256 * center_tile_offset[0] - 10,&lt;br /&gt;
          256 * center_tile_offset[1] )&lt;br /&gt;
 .horiz(20)&lt;br /&gt;
 .move(-10,-10)&lt;br /&gt;
 .vert(20)&lt;br /&gt;
 .set(&amp;quot;stroke&amp;quot;, &amp;quot;red&amp;quot;)&lt;br /&gt;
 .set(&amp;quot;stroke-width&amp;quot;, 2)&lt;br /&gt;
 .set(&amp;quot;z-index&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
var tiles = setsize([], num_tiles[0]);&lt;br /&gt;
for(var x = 0; x &amp;lt; num_tiles[0]; x += 1)&lt;br /&gt;
{&lt;br /&gt;
  tiles[x] = setsize([], num_tiles[1]);&lt;br /&gt;
  for(var y = 0; y &amp;lt; num_tiles[1]; y += 1)&lt;br /&gt;
    tiles[x][y] = g.createChild(&amp;quot;image&amp;quot;, &amp;quot;map-tile&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var last_tile = [-1,-1];&lt;br /&gt;
var last_type = type;&lt;br /&gt;
&lt;br /&gt;
var updateTiles = func()&lt;br /&gt;
{&lt;br /&gt;
  var lat = getprop('/position/latitude-deg');&lt;br /&gt;
  var lon = getprop('/position/longitude-deg');&lt;br /&gt;
&lt;br /&gt;
  var n = math.pow(2, zoom);&lt;br /&gt;
  var offset = [&lt;br /&gt;
    n * ((lon + 180) / 360) - center_tile_offset[0],&lt;br /&gt;
    (1 - math.ln(math.tan(lat * math.pi/180) + 1 / math.cos(lat * math.pi/180)) / math.pi) / 2 * n - center_tile_offset[1]&lt;br /&gt;
  ];&lt;br /&gt;
  var tile_index = [int(offset[0]), int(offset[1])];&lt;br /&gt;
&lt;br /&gt;
  var ox = tile_index[0] - offset[0];&lt;br /&gt;
  var oy = tile_index[1] - offset[1];&lt;br /&gt;
&lt;br /&gt;
  for(var x = 0; x &amp;lt; num_tiles[0]; x += 1)&lt;br /&gt;
    for(var y = 0; y &amp;lt; num_tiles[1]; y += 1)&lt;br /&gt;
      tiles[x][y].setTranslation(int((ox + x) * 256 + 0.5), int((oy + y) * 256 + 0.5));&lt;br /&gt;
&lt;br /&gt;
  if(    tile_index[0] != last_tile[0]&lt;br /&gt;
      or tile_index[1] != last_tile[1]&lt;br /&gt;
      or type != last_type )&lt;br /&gt;
  {&lt;br /&gt;
    for(var x = 0; x &amp;lt; num_tiles[0]; x += 1)&lt;br /&gt;
      for(var y = 0; y &amp;lt; num_tiles[1]; y += 1)&lt;br /&gt;
      {&lt;br /&gt;
        var pos = {&lt;br /&gt;
          z: zoom,&lt;br /&gt;
          x: int(offset[0] + x),&lt;br /&gt;
          y: int(offset[1] + y),&lt;br /&gt;
          type: type&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        (func {&lt;br /&gt;
        var img_path = makePath(pos);&lt;br /&gt;
        var tile = tiles[x][y];&lt;br /&gt;
&lt;br /&gt;
        if( io.stat(img_path) == nil )&lt;br /&gt;
        {&lt;br /&gt;
          var img_url = makeUrl(pos);&lt;br /&gt;
          print('requesting ' ~ img_url);&lt;br /&gt;
          http.save(img_url, img_path)&lt;br /&gt;
              .done(func {print('received image ' ~ img_path); tile.set(&amp;quot;src&amp;quot;, img_path);})&lt;br /&gt;
              .fail(func (r) print('Failed to get image ' ~ img_path ~ ' ' ~ r.status ~ ': ' ~ r.reason));&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
          print('loading ' ~ img_path);&lt;br /&gt;
          tile.set(&amp;quot;src&amp;quot;, img_path)&lt;br /&gt;
        }&lt;br /&gt;
        })();&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    last_tile = tile_index;&lt;br /&gt;
    last_type = type;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
var update_timer = maketimer(2, updateTiles);&lt;br /&gt;
update_timer.start();&lt;br /&gt;
&lt;br /&gt;
changeZoom(0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding a NavDisplay ==&lt;br /&gt;
&lt;br /&gt;
== Adding a CDU ==&lt;br /&gt;
&lt;br /&gt;
== Adding a Multi-Function Display (MFD) ==&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas_-_Tile_map_demo.png&amp;diff=83767</id>
		<title>File:Canvas - Tile map demo.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas_-_Tile_map_demo.png&amp;diff=83767"/>
		<updated>2015-04-29T14:28:11Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=A simple, canvas based tile map which is centered around the aircraft.}}&lt;br /&gt;
|date=2015-04-29 16:26:33&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:TheTom|TheTom]]&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-4.0}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Canvas]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=77735</id>
		<title>User:TheTom</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=77735"/>
		<updated>2014-11-10T16:58:04Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &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;
=== [[Canvas|Canvas (The FlightGear 2D rendering API)]] ===&lt;br /&gt;
&lt;br /&gt;
* Canvas based GUI {{Pending}}&lt;br /&gt;
** Create [[Canvas MessageBox|dialogs]] {{Done}} and widgets {{Pending}} from Nasal&lt;br /&gt;
** Handle keyboard input {{Done}}&lt;br /&gt;
** Expose character and cursor positions (eg. for text input/editing) {{Pending}}&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_Element&amp;diff=77734</id>
		<title>Canvas Element</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_Element&amp;diff=77734"/>
		<updated>2014-11-10T16:49:34Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Some info on blend functions.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas Elements]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
A handful of rendering primitives are available to draw on a canvas. Properties (see [[Property Tree]] for general information on FlightGear's property system) are used to control the appearance and behaviour of such ''Element''s.&lt;br /&gt;
&lt;br /&gt;
= Properties =&lt;br /&gt;
&lt;br /&gt;
== blend-* ==&lt;br /&gt;
&lt;br /&gt;
Set OpenGL blend function.&lt;br /&gt;
For a single function for all color channels (as with [https://www.opengl.org/sdk/docs/man/html/glBlendFunc.xhtml glBlendFunc]) use the properties '''&amp;quot;blend-source&amp;quot;''' and '''&amp;quot;blend-destination&amp;quot;'''.&lt;br /&gt;
To set separate blend functions for the rgb and alpha channels (as with [https://www.opengl.org/sdk/docs/man/html/glBlendFuncSeparate.xhtml glBlendFuncSeparate]) use the properties with '''&amp;quot;*-rgb&amp;quot;''' and '''&amp;quot;*-alpha&amp;quot;''' prefix.&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;dst-alpha&amp;quot; | &amp;quot;dst-color&amp;quot; | &amp;quot;one&amp;quot; | &amp;quot;one-minus-dst-alpha&amp;quot; | &amp;quot;one-minus-dst-color&amp;quot; | &amp;quot;one-minus-src-alpha&amp;quot; | &amp;quot;one-minus-src-color&amp;quot; | &amp;quot;src-alpha&amp;quot; | &amp;quot;src-alpha-saturate&amp;quot; | &amp;quot;src-color&amp;quot; | &amp;quot;constant-color&amp;quot; | &amp;quot;one-minus-constant-color&amp;quot; | &amp;quot;constant-alpha&amp;quot; | &amp;quot;one-minus-constant-alpha&amp;quot; | &amp;quot;zero&amp;quot; (See the [https://www.opengl.org/sdk/docs/man/html/glBlendFunc.xhtml#description OpenGL Reference Pages] for details)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Setting different blend functions for rgb and alpha:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Standard alpha blending&lt;br /&gt;
el.set(&amp;quot;blend-source-rgb&amp;quot;, &amp;quot;src-alpha&amp;quot;);&lt;br /&gt;
el.set(&amp;quot;blend-destination-rgb&amp;quot;, &amp;quot;one-minus-src-alpha&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
# Just keep current alpha&lt;br /&gt;
el.set(&amp;quot;blend-source-alpha&amp;quot;, &amp;quot;zero&amp;quot;);&lt;br /&gt;
el.set(&amp;quot;blend-destination-alpha&amp;quot;, &amp;quot;one&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== clip ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;auto&amp;quot; | &amp;quot;rect(&amp;lt;top&amp;gt;, &amp;lt;right&amp;gt;, &amp;lt;bottom&amp;gt;, &amp;lt;left&amp;gt;)&amp;quot;&lt;br /&gt;
* '''Default''': &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Set clipping rectangle for element and all its children. Only what is inside the clipping bounds will be shown.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# set clipping rectangle with x=10, y=5, width=90, height=45&lt;br /&gt;
el.set(&amp;quot;clip&amp;quot;, &amp;quot;rect(5, 100, 50, 10)&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== clip-frame ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': GLOBAL | PARENT | LOCAL&lt;br /&gt;
* '''Default''': GLOBAL&lt;br /&gt;
&lt;br /&gt;
Set the coordinate reference frame for the ''clip'' property.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# set clip reference frame to parent coordinate frame&lt;br /&gt;
el.set(&amp;quot;clip-frame&amp;quot;, canvas.Element.PARENT);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== visible ==&lt;br /&gt;
&lt;br /&gt;
== z-index ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;lt;number&amp;gt; (Integer)&lt;br /&gt;
* '''Default''': 0&lt;br /&gt;
&lt;br /&gt;
Change order in which elements are drawn. Elements with higher ''z-index'' are drawn later and cover allready drawn elements on overlapping parts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Draw before all elements (if no z-index of the other elements is lower than zero)&lt;br /&gt;
el.set(&amp;quot;z-index&amp;quot;, -1);&lt;br /&gt;
&lt;br /&gt;
# Ensure el2 is drawn before/below el1&lt;br /&gt;
el1.set(&amp;quot;z-index&amp;quot;, 51);&lt;br /&gt;
el2.set(&amp;quot;z-index&amp;quot;, 50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=76674</id>
		<title>Canvas snippets</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=76674"/>
		<updated>2014-09-22T09:06:50Z</updated>

		<summary type="html">&lt;p&gt;TheTom: [canvas.]style is not a layout but the current global canvas gui style...&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 standalone Canvas ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| please upload ...|| &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 standalone Canvas (not attached to any GUI dialog/aircraft etc) &lt;br /&gt;
var myCanvas = canvas.new({&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Livery Test&amp;quot;,   # The name is optional but allow for easier identification&lt;br /&gt;
  &amp;quot;size&amp;quot;: [512, 512], # Size of the underlying texture (should be a power of 2, required) [Resolution]&lt;br /&gt;
  &amp;quot;view&amp;quot;: [512, 512],  # Virtual resolution (Defines the coordinate system of the canvas [Dimensions]&lt;br /&gt;
                        # which will be stretched the size of the texture, required)&lt;br /&gt;
  &amp;quot;mipmapping&amp;quot;: 1       # Enable mipmapping (optional)&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
# set background color&lt;br /&gt;
myCanvas.set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&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;
&lt;br /&gt;
# OPTIONAL: Create a Canvas dialog window to hold the canvas and show that it's working&lt;br /&gt;
# the Canvas is now standalone, i.e. continues to live once the dialog is closed!&lt;br /&gt;
var window = canvas.Window.new([512,512],&amp;quot;dialog&amp;quot;);&lt;br /&gt;
window.setCanvas(myCanvas);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Creating Tooltips ==&lt;br /&gt;
== Creating Popups ==&lt;br /&gt;
== Creating a Canvas GUI Window ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-dialog.png|left|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;.]] || {{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;
&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().set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
# Using specific css colors would also be possible:&lt;br /&gt;
# myCanvas.set(&amp;quot;background&amp;quot;, &amp;quot;#ffaac0&amp;quot;);&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;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding Raster Images ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas Snippets-raster image.png|thumb|Canvas snippet demonstrating how to load a raster image]] ||&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&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=root.createChild(&amp;quot;image&amp;quot;)&lt;br /&gt;
			           .setFile( filename )&lt;br /&gt;
				   .setTranslation(100,10)&lt;br /&gt;
                                   .setSize(130,130);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding OpenVG Paths ==&lt;br /&gt;
== Adding Vector Images ==&lt;br /&gt;
== Adding Text Elements ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:CanvasText-Hello-World.png|thumb|Screen shot showing the CanvasText example contributed by Necolatis]]|| &lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
var myText = root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
      .setText(&amp;quot;Hello world!&amp;quot;)&lt;br /&gt;
      .setFontSize(20, 0.9)          # font size (in texels) and font aspect ratio&lt;br /&gt;
      .setColor(1,0,0,1)             # red, fully opaque&lt;br /&gt;
      .setAlignment(&amp;quot;center-center&amp;quot;) # how the text is aligned to where you place it&lt;br /&gt;
      .setTranslation(160, 80);     # where to place the text&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding GUI Labels ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-Layout-Label-example-by-Necolatis.png|thumb|Canvas demo: Layouts and Labels (by Necolatis)]]|| &lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. It also assumes you have a Layout item setup and called '''myLayoutItem'''.}}&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
var label = canvas.gui.widgets.Label.new(root, canvas.style, {wordWrap: 0}); # wordwrap: 0 will disable wordwrapping, to enable it use 1 instead&lt;br /&gt;
label.setText(&amp;quot;Hello World!&amp;quot;);&lt;br /&gt;
myLayout.addItem(label);&lt;br /&gt;
&lt;br /&gt;
var label2 = canvas.gui.widgets.Label.new(root, canvas.style, {wordWrap: 0}); # wordwrap: 0 will disable wordwrapping, to enable it use 1 instead&lt;br /&gt;
label2.setText(&amp;quot;Hello FlightGear&amp;quot;);&lt;br /&gt;
myLayout.addItem(label2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding GUI Buttons (Layouts)==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Canvas-demo-layouts-and-buttons-by-Necolatis.png|thumb|Canvas snippet: buttons and layouts (by Necolatis)]] [[File:Canvas-toggle-button-snippet-by-Necolatis.png|thumb|Canvas toggle button demo by Necolatis]] ||&lt;br /&gt;
&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. It also assumes you have a Layout item setup and called '''myLayoutItem'''.}}&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
# click button&lt;br /&gt;
&lt;br /&gt;
var button = canvas.gui.widgets.Button.new(root, canvas.style, {})&lt;br /&gt;
	.setText(&amp;quot;Click on me&amp;quot;)&lt;br /&gt;
	.setFixedSize(75, 25);&lt;br /&gt;
&lt;br /&gt;
button.listen(&amp;quot;clicked&amp;quot;, func {&lt;br /&gt;
        # add code here to react on click on button.&lt;br /&gt;
print(&amp;quot;Button clicked !&amp;quot;);&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
myLayout.addItem(button);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&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 layout&lt;br /&gt;
var myLayout = canvas.HBoxLayout.new();&lt;br /&gt;
# assign it to the Canvas&lt;br /&gt;
myCanvas.setLayout(myLayout);&lt;br /&gt;
&lt;br /&gt;
var button = canvas.gui.widgets.Button.new(root, canvas.style, {})&lt;br /&gt;
        .setText(&amp;quot;Toggle me&amp;quot;)&lt;br /&gt;
        .setCheckable(1) # this indicates that is should be a toggle button&lt;br /&gt;
        .setChecked(0) # depressed by default&lt;br /&gt;
        .setFixedSize(75, 25);&lt;br /&gt;
&lt;br /&gt;
button.listen(&amp;quot;toggled&amp;quot;, func (e) {&lt;br /&gt;
        if( e.detail.checked ) {&lt;br /&gt;
            # add code here to react on button being depressed.&lt;br /&gt;
        } else {&lt;br /&gt;
            # add code here to react on button not being depressed.&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
myLayout.addItem(button);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Canvas Input Dialog ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Snippets-canvas-input-dialog.png|thumb|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;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Using Layouts ==&lt;br /&gt;
&lt;br /&gt;
== Using Styling ==&lt;br /&gt;
== Adding a HUD ==&lt;br /&gt;
== Adding a 2D Instrument ==&lt;br /&gt;
== Adding a 2D Panel ==&lt;br /&gt;
== Adding a PFD ==&lt;br /&gt;
&lt;br /&gt;
== Using the SymbolCache ==&lt;br /&gt;
&lt;br /&gt;
== Adding a MapStructure map to a Canvas  ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-mapstructure-dialog.png|thumb|[[MapStructure]] layers shown in a Canvas GUI dialog]]&lt;br /&gt;
||&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var TestMap = root.createChild(&amp;quot;map&amp;quot;);&lt;br /&gt;
TestMap.setController(&amp;quot;Aircraft position&amp;quot;);&lt;br /&gt;
TestMap.setRange(25); &lt;br /&gt;
 &lt;br /&gt;
TestMap.setTranslation(    myCanvas.get(&amp;quot;view[0]&amp;quot;)/2,&lt;br /&gt;
                           myCanvas.get(&amp;quot;view[1]&amp;quot;)/2&lt;br /&gt;
                        );&lt;br /&gt;
var r = func(name,vis=1,zindex=nil) return caller(0)[0];&lt;br /&gt;
&lt;br /&gt;
foreach(var type; [r('APT'), r('VOR') ] )&lt;br /&gt;
 TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: type.zindex,);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Adding a NavDisplay ==&lt;br /&gt;
&lt;br /&gt;
== Adding a Multi-Function Display (MFD) ==&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=76292</id>
		<title>Canvas snippets</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_snippets&amp;diff=76292"/>
		<updated>2014-09-15T13:50:27Z</updated>

		<summary type="html">&lt;p&gt;TheTom: I prefer generic setters and colors from the theme.&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;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-dialog.png|left|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;.]] || {{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;
&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().set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
# Using specific css colors would also be possible:&lt;br /&gt;
# myCanvas.set(&amp;quot;background&amp;quot;, &amp;quot;#ffaac0&amp;quot;);&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;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Adding a MapStructure map to a Canvas  ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
| [[File:Snippets-canvas-mapstructure-dialog.png|thumb|[[MapStructure]] layers shown in a Canvas GUI dialog]]&lt;br /&gt;
||&lt;br /&gt;
{{Note|This assumes that you already have a top-level root group set up, and named it '''root''', just change this variable if you want it to be rendered elsewhere. Equally, this snippet assumes that your canvas is named '''myCanvas'''.}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
var TestMap = root.createChild(&amp;quot;map&amp;quot;);&lt;br /&gt;
TestMap.setController(&amp;quot;Aircraft position&amp;quot;);&lt;br /&gt;
TestMap.setRange(25); &lt;br /&gt;
 &lt;br /&gt;
TestMap.setTranslation(    myCanvas.get(&amp;quot;view[0]&amp;quot;)/2,&lt;br /&gt;
                           myCanvas.get(&amp;quot;view[1]&amp;quot;)/2&lt;br /&gt;
                        );&lt;br /&gt;
var r = func(name,vis=1,zindex=nil) return caller(0)[0];&lt;br /&gt;
&lt;br /&gt;
foreach(var type; [r('APT'), r('VOR') ] )&lt;br /&gt;
 TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: type.zindex,);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Canvas Input Dialog ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Screenshot !! Code !! &lt;br /&gt;
|-&lt;br /&gt;
|[[File:Snippets-canvas-input-dialog.png|thumb|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;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User_talk:TheTom&amp;diff=76026</id>
		<title>User talk:TheTom</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User_talk:TheTom&amp;diff=76026"/>
		<updated>2014-09-08T09:31:19Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Template:Note ==&lt;br /&gt;
[http://wiki.flightgear.org/index.php?title=Template:Note&amp;amp;diff=74755&amp;amp;oldid=73671 Well spotted].  I tried fix it in a similar way earlier but did not seem to succeed for some reason.  Your edit seem to work in the intended way though.&lt;br /&gt;
&lt;br /&gt;
I have now made the same changes to its sister templates {{tl|warning}}, {{tl|caution}} and {{tl|tip}}.&lt;br /&gt;
&lt;br /&gt;
Thanks!&lt;br /&gt;
&lt;br /&gt;
—[[User:Johan G|Johan G]] ([[User_talk:Johan_G|Talk]] | [[Special:Contributions/Johan_G|contribs]]) 09:52, 5 August 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
== tracking animation article not really helpful==&lt;br /&gt;
Hello Tom,&lt;br /&gt;
&lt;br /&gt;
I just wanted to try your tracking animation for a scissor animation on a nose gear. &lt;br /&gt;
I followed your article here in the wiki. It don't work. &lt;br /&gt;
&lt;br /&gt;
Looking at your C-130J doesn't help - as the objects name are not the same like in the animation file.&lt;br /&gt;
I remember that another user in the forum noticed it. On the other side I see the animation working on your C-130J.&lt;br /&gt;
Would you please so kind fix the article as it seems that very something very important to know is missing. &lt;br /&gt;
&lt;br /&gt;
Cheers!&lt;br /&gt;
&lt;br /&gt;
--[[User:HHS|HHS]] ([[User talk:HHS|talk]]) 21:52, 3 September 2014 (UTC)&lt;br /&gt;
&lt;br /&gt;
What does not work? Are there any error messages? I have just copied the XML from the C-130J without modifying it. Do you have an example which does not work?&lt;br /&gt;
&lt;br /&gt;
--[[User:TheTom|TheTom]] ([[User talk:TheTom|talk]]) 09:31, 8 September 2014 (UTC)&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=75383</id>
		<title>User:TheTom</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=75383"/>
		<updated>2014-08-20T09:04:34Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &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 {{Pending}}&lt;br /&gt;
** Expose character and cursor positions (eg. for text input/editing) {{Pending}}&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_event_handling&amp;diff=74758</id>
		<title>Canvas event handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_event_handling&amp;diff=74758"/>
		<updated>2014-08-05T09:42:59Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Example cleanup/formatting.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
{{Note| This feature is only available in FlightGear versions &amp;gt;{{=}} 2.11 !&lt;br /&gt;
To really understand Canvas event handling, you should read [[Using listeners and signals with Nasal]] first and understand how [[Using_Nasal_functions#Function_closures|closures work]].}}&lt;br /&gt;
&lt;br /&gt;
The Canvas event handling system closely follows the W3C [http://www.w3.org/TR/DOM-Level-3-Events/ DOM Event Model]. If you have already used events in JavaScript and HTML most concepts of the Canvas event system should be already familiar to you. The most notable difference is the missing capture phase, but it is usually not used anyhow.&lt;br /&gt;
&lt;br /&gt;
Listeners - simple Nasal functions - can be attached to every element inside the Canvas and the Canvas itself. Once a certain action - like moving the mouse or pressing a button - occurs the associated listeners are called. We can use this for example to detect whether the mouse has moved over an element or if a certain element has been clicked.&lt;br /&gt;
&lt;br /&gt;
= Listen for events =&lt;br /&gt;
&lt;br /&gt;
To receive events callback function can be added to elements on a Canvas as well as to the Canvas itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
canvas.addEventListener(&amp;quot;&amp;lt;type&amp;gt;&amp;quot;, &amp;lt;func&amp;gt;);&lt;br /&gt;
canvas_element.addEventListener(&amp;quot;&amp;lt;type&amp;gt;&amp;quot;, &amp;lt;func&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For each placement of a Canvas handling events can be enabled or disabled. A Canvas placed in a PUI (old GUI) widget or as standalone GUI window receives events by default, whereas Canvases placed onto the aircraft model or in the scenery do not receive any events by default.&lt;br /&gt;
&lt;br /&gt;
{{Note|When using the old [[Howto:Adding_a_canvas_to_a_GUI_dialog|PUI/XML GUI]] with a '''&amp;lt;nowiki&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/nowiki&amp;gt;'''-widget placement, PUI does not trigger any mouseover/hover (mousemove) events. Mouse clicks/wheel/drag are working as expected. For all other placements like on standalone Canvas windows and [[Howto:Add_a_2D_canvas_instrument_to_your_aircraft|3D models]] there is no such limitation. If you find that your code doesn't work as expected, make sure to verify that your layers (canvas groups) use matching z-index ordering, or overlapping symbols may prevent event handlers from being triggered/called.}}&lt;br /&gt;
&lt;br /&gt;
For standalone GUI windows setting '''capture-events''' to ''0'' or ''1'' enables or disables handling of events respectively. For a Canvas placed onto a 3d model, setting ''capture-events'' inside the placement can be used to activate event handling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var dlg = canvas.Window.new([152,74]);&lt;br /&gt;
&lt;br /&gt;
# Disable event handling for this window. Events will pass through&lt;br /&gt;
# and can reach any window or also object covered by the window.&lt;br /&gt;
dlg.setBool(&amp;quot;capture-events&amp;quot;, 0);&lt;br /&gt;
&lt;br /&gt;
# Place the canvas onto the PFD and enable receiving events&lt;br /&gt;
my_canvas.addPlacement({&amp;quot;node&amp;quot;: &amp;quot;PFD-Screen&amp;quot;, &amp;quot;capture-events&amp;quot;: 1});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Event flow =&lt;br /&gt;
&lt;br /&gt;
Events always are targeted at a specific element inside the Canvas. Before any event handler is called the propagation path for the event is determined. It consists of the event target itself and all its ancestor elements (Groups) up to and including the Canvas. Afterwards - during the ''Target Phase'' - all listeners registered on the event target are called. Finally - during the ''Bubbling Phase'' - the event bubbles up the tree, following the propagation path determined in the first step, and all listeners attached to the according elements are called.&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas Eventflow.png|thumb|540px|center|Event flow of Canvas Events similar to W3C DOM Event flow &amp;lt;ref name=&amp;quot;dom-event-flow&amp;quot;&amp;gt;DOM Level 3 event flow. http://www.w3.org/TR/DOM-Level-3-Events/#event-flow&amp;lt;/ref&amp;gt;.]]&lt;br /&gt;
&lt;br /&gt;
= Event classes =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var Event = {&lt;br /&gt;
  # Name of event type [read-only]&lt;br /&gt;
  type: &amp;lt;typename&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Target element [read-only]&lt;br /&gt;
  target: &amp;lt;target-element&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Element the currently called listener is attached to [read-only]&lt;br /&gt;
  currentTarget: &amp;lt;target-element&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Stop further propagation of event (stop&lt;br /&gt;
  # bubbling up to its parents)&lt;br /&gt;
  stopPropagation: func()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var MouseEvent = {&lt;br /&gt;
  parents: [Event],&lt;br /&gt;
&lt;br /&gt;
  # Position in screen coordinates [read-only]&lt;br /&gt;
  screenX: &amp;lt;screen-x&amp;gt;,&lt;br /&gt;
  screenY: &amp;lt;screen-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Position in window/canvas coordinates [read-only]&lt;br /&gt;
  clientX: &amp;lt;client-x&amp;gt;,&lt;br /&gt;
  clientY: &amp;lt;client-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Position in local/element coordinates [read-only]&lt;br /&gt;
  localX: &amp;lt;local-x&amp;gt;,&lt;br /&gt;
  localY: &amp;lt;local-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Distance to position of previous event [read-only]&lt;br /&gt;
  deltaX: &amp;lt;delta-x&amp;gt;,&lt;br /&gt;
  deltaY: &amp;lt;delta-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Current click count (number of clicks within a certain&lt;br /&gt;
  # time limit. max. 3) [read-only]&lt;br /&gt;
  click_count: &amp;lt;click-count&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  # Buttons/modifiers require FlightGear &amp;gt;= 3.1.0&lt;br /&gt;
&lt;br /&gt;
  # Button which triggered this event [read-only]&lt;br /&gt;
  #&lt;br /&gt;
  #  0: primary button (usually the left button)&lt;br /&gt;
  #  1: auxiliary button (usually the middle button/mouse wheel)&lt;br /&gt;
  #  2: secondary button (usually the right button)&lt;br /&gt;
  button: &amp;lt;button&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # State of all mouse buttons at the time the event has been&lt;br /&gt;
  # triggered [read-only]&lt;br /&gt;
  buttons: &amp;lt;active-button-mask&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # State of all keyboard modifiers at the time the event has&lt;br /&gt;
  # been triggered [read-only]&lt;br /&gt;
  modifiers: &amp;lt;modifier-mask&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  ctrlKey: &amp;lt;was-ctrl-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  shiftKey: &amp;lt;was-shift-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  altKey: &amp;lt;was-alt-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  metaKey: &amp;lt;was-meta-down&amp;gt;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Middle-mouse button emulation ==&lt;br /&gt;
&lt;br /&gt;
2-button mice can be setup to emulate a middle-mouse button click by pressing the left and right button simultaneously. On Ubuntu you can use [https://apps.ubuntu.com/cat/applications/gpointing-device-settings gpointing-device-settings] to enable &amp;quot;middle button emulation&amp;quot;&lt;br /&gt;
&amp;lt;ref&amp;gt;https://wiki.ubuntu.com/X/Quirks#A2-button_Mice&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref&amp;gt;http://askubuntu.com/questions/140828/how-can-i-paste-text-by-pressing-the-left-and-right-mouse-buttons-at-the-same-ti&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Event types =&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Description !! DOM equivalent event !! Bubbles &amp;lt;ref name=&amp;quot;dom-event-flow&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| ''mousedown'' || Mouse button pressed || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mousedown mousedown] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseup'' || Mouse button released || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseup mouseup] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''click'' || ''mousedown'' + ''mouseup'' have been triggered for this element without moving more than a certain maximum distance || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-click click] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''dblclick'' || Two ''click'' events have been triggered for this element without moving more than a certain maximum distance and time limit || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-dblclick dblclick] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''drag'' || The mouse has been moved with a button down. After dragging has started above an element, all consecutive ''drag'' events are sent to this element even if the mouse leaves its area || || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''wheel'' || Mouse wheel rotated (see deltaY for direction) || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-wheel wheel] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mousemove'' || Mouse has moved while beeing inside the area of the target element. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mousemove mousemove] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseover'' || Mouse has entered a child or the element itself. ''mouseover'' is also triggered if the mouse moves from one child element to another.  || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseover mouseover] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseout'' || Mouse has left a child or the element itself. ''mouseout'' is also triggered if the mouse moves from one child element to another. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseout mouseout] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseenter'' || Mouse has entered a child or the element itself. In contrary to ''mouseover'', ''mouseenter'' is not triggered if the mouse moves from one child element to another, but only the first time the element or one of its children is entered. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseenter mouseenter] || {{cross}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseleave'' || Mouse has left the element and all of its children. In contrary to ''mouseout'', ''mouseleave'' is not triggered if the mouse moves from one child element to another, but only if the mouse moves outside the element and all its children. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseleave mouseleave] || {{cross}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Example Code =&lt;br /&gt;
(Note that this example makes use of advanced Nasal concepts, such as anonymous functions, method chaining and lots of embedded/inline code):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Canvas GUI demo&lt;br /&gt;
#&lt;br /&gt;
#  Shows an icon in the top-right corner which upon click opens a simple window&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
var dlg = canvas.Window.new([32,32]);&lt;br /&gt;
dlg.setInt(&amp;quot;tf/t[1]&amp;quot;, 4)&lt;br /&gt;
   .setInt(&amp;quot;right&amp;quot;, 4);&lt;br /&gt;
var my_canvas = dlg.createCanvas()&lt;br /&gt;
                   .set(&amp;quot;background&amp;quot;, &amp;quot;rgba(0,0,0,0)&amp;quot;);&lt;br /&gt;
var root = my_canvas.createGroup();&lt;br /&gt;
canvas.parsesvg(root, &amp;quot;gui/dialogs/images/icon-aircraft.svg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
my_canvas.addEventListener(&amp;quot;click&amp;quot;, func&lt;br /&gt;
{&lt;br /&gt;
  var dlg = canvas.Window.new([400,300], &amp;quot;dialog&amp;quot;);&lt;br /&gt;
  var my_canvas = dlg.createCanvas()&lt;br /&gt;
                     .set(&amp;quot;background&amp;quot;, &amp;quot;#f2f1f0&amp;quot;);&lt;br /&gt;
  var root = my_canvas.createGroup();&lt;br /&gt;
  root.addEventListener(&amp;quot;click&amp;quot;, func(e) {&lt;br /&gt;
    printf( &amp;quot;click: screen(%.1f|%.1f) client(%.1f|%.1f) click count = %d&amp;quot;,&lt;br /&gt;
            e.screenX, e.screenY,&lt;br /&gt;
            e.clientX, e.clientY,&lt;br /&gt;
            e.click_count );&lt;br /&gt;
  });&lt;br /&gt;
  root.addEventListener(&amp;quot;dblclick&amp;quot;, func(e) {&lt;br /&gt;
    printf( &amp;quot;dblclick: screen(%.1f|%.1f) client(%.1f|%.1f)&amp;quot;,&lt;br /&gt;
            e.screenX, e.screenY,&lt;br /&gt;
            e.clientX, e.clientY );&lt;br /&gt;
  });&lt;br /&gt;
  root.addEventListener(&amp;quot;wheel&amp;quot;, func(e) {&lt;br /&gt;
    printf( &amp;quot;wheel: screen(%.1f|%.1f) client(%.1f|%.1f) delta = %.1f&amp;quot;,&lt;br /&gt;
            e.screenX, e.screenY,&lt;br /&gt;
            e.clientX, e.clientY,&lt;br /&gt;
            e.deltaY );&lt;br /&gt;
  });&lt;br /&gt;
  var text =&lt;br /&gt;
    root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
        .setText( &amp;quot;This could be used for building an 'Aircraft Help' dialog.\n&amp;quot;&lt;br /&gt;
                ~ &amp;quot;You can also #use it to play around with the new Canvas system :). β&amp;quot; )&lt;br /&gt;
        .setTranslation(10, 30)&lt;br /&gt;
        .set(&amp;quot;alignment&amp;quot;, &amp;quot;left-top&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;character-size&amp;quot;, 14)&lt;br /&gt;
        .set(&amp;quot;font&amp;quot;, &amp;quot;LiberationFonts/LiberationSans-Regular.ttf&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;max-width&amp;quot;, 380)&lt;br /&gt;
        .set(&amp;quot;fill&amp;quot;, &amp;quot;black&amp;quot;);&lt;br /&gt;
  var text_move =&lt;br /&gt;
    root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
        .setText(&amp;quot;Mouse moved over text...&amp;quot;)&lt;br /&gt;
        .setTranslation(20, 200)&lt;br /&gt;
        .set(&amp;quot;alignment&amp;quot;, &amp;quot;left-center&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;character-size&amp;quot;, 15)&lt;br /&gt;
        .set(&amp;quot;font&amp;quot;, &amp;quot;LiberationFonts/LiberationSans-Bold.ttf&amp;quot;)&lt;br /&gt;
        .set(&amp;quot;fill&amp;quot;, &amp;quot;#ff0000&amp;quot;)&lt;br /&gt;
        .hide();&lt;br /&gt;
  var visible_count = 0;&lt;br /&gt;
  text.addEventListener(&amp;quot;mouseover&amp;quot;, func text_move.show());&lt;br /&gt;
  text.addEventListener(&amp;quot;mouseout&amp;quot;, func text_move.hide());&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=74755</id>
		<title>Template:Note</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Note&amp;diff=74755"/>
		<updated>2014-08-05T09:26:30Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Remove &amp;lt;div&amp;gt; block and display: inline-block to prevent layoutproblems with infoboxes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| cellspacing=&amp;quot;0&amp;quot; style=&amp;quot;margin:1em 5% 1em 5%; border: 1px solid #1992ff; border-left-width: 10px; min-width: 50%; background-color: #e0f2ff; padding: 2px;&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;'''&amp;amp;ensp; {{{1|Add message}}}&lt;br /&gt;
|}&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;{{Informative template |1=&lt;br /&gt;
__NOTOC__&lt;br /&gt;
== Goal ==&lt;br /&gt;
Use this template to add a note about something important.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{&amp;lt;/nowiki&amp;gt;'''note'''&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;message&amp;lt;nowiki&amp;gt;}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{note|The gyro compass may drift.  Compare the gyro compass against the wet compass at regular intervals.}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
{{note|The gyro compass may drift.  Compare the gyro compass against the wet compass at regular intervals.}}&lt;br /&gt;
&lt;br /&gt;
== Related templates ==&lt;br /&gt;
* {{tl|caution}} &amp;amp;ndash; When there might be damages to the virtual aircraft or to real equipment&lt;br /&gt;
* {{tl|tip}} &amp;amp;ndash; For helpful tips&lt;br /&gt;
* {{tl|warning}} &amp;amp;ndash; When a virtual aircraft might crash or when real equipment or ones health might be jeopardized&lt;br /&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=74183</id>
		<title>Template:Canvas Navigation</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=74183"/>
		<updated>2014-07-21T15:04:14Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{forum|71|Canvas}}&lt;br /&gt;
{{sidebar&lt;br /&gt;
| name	= Canvas Navigation&lt;br /&gt;
| title = Canvas - the FlightGear 2D drawing API&lt;br /&gt;
| contentstyle= text-align: left;&lt;br /&gt;
&lt;br /&gt;
| content1 = &lt;br /&gt;
* [[Canvas]] - Main Page&lt;br /&gt;
* [[Canvas-hackers]] (team clone)&lt;br /&gt;
* [[Canvas Development]]&lt;br /&gt;
* [[Canvas GUI]]&lt;br /&gt;
* [[Canvas Widgets]]&lt;br /&gt;
* [[Canvas Maps]]&lt;br /&gt;
&lt;br /&gt;
| heading2 = Frameworks&lt;br /&gt;
| content2 = &lt;br /&gt;
{{Canvas Frameworks|mode=navbar}}&lt;br /&gt;
* [[Canvas Glass Cockpit Efforts]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[How the Canvas subsystem works]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| heading3 = Tutorials&lt;br /&gt;
| content3 =&lt;br /&gt;
* [[Howto:Getting started with Canvas]]&lt;br /&gt;
* [[Howto:Adding a canvas to a GUI dialog]] (PUI!)&lt;br /&gt;
* [[Howto:Creating a Canvas GUI dialog file]] (New)&lt;br /&gt;
* [[Howto:Creating a Canvas GUI Widget]]&lt;br /&gt;
* [[Howto:Add a 2D canvas instrument to your aircraft]]&lt;br /&gt;
* [[Howto:Parsing 2D Instruments using the Canvas]]&lt;br /&gt;
* [[Howto:Creating fullscreen Canvas applications]]&lt;br /&gt;
* [[Howto:Use SVG inside a Canvas]]&lt;br /&gt;
* [[Howto:Canvas applications as Nasal submodules]]&lt;br /&gt;
* [[Howto:Using raster images and nested canvases]]&lt;br /&gt;
&amp;lt;!-- * [[Howto:Creating Canvas Widgets in Nasal]] --&amp;gt;&lt;br /&gt;
* [[Howto:Creating a Canvas graph widget]]&lt;br /&gt;
* [[Canvas HUD]]&lt;br /&gt;
| heading4 = Reference&lt;br /&gt;
| content4 =&lt;br /&gt;
* [[Canvas Element]]&lt;br /&gt;
** [[Canvas Group|Group]]&lt;br /&gt;
** [[Canvas Image|Image]]&lt;br /&gt;
** [[Canvas Map|Map]]&lt;br /&gt;
** [[Canvas Path|Path]]&lt;br /&gt;
** [[Canvas Text|Text]]&lt;br /&gt;
* [[Canvas Nasal API]]&lt;br /&gt;
** [[Canvas MessageBox|MessageBox]]&lt;br /&gt;
** [[Canvas Layout System|Layout System]]&lt;br /&gt;
* [[Canvas - Event_Handling|Event Handling]]&lt;br /&gt;
| heading5 = Related&lt;br /&gt;
| content5 =&lt;br /&gt;
* [[Canvas Properties]]&lt;br /&gt;
* [[Unifying the 2D rendering backend via canvas]]&lt;br /&gt;
* [[Howto:Create a 2D drawing API for FlightGear]]&lt;br /&gt;
* [[Howto:Use a Camera View in an Instrument]]&lt;br /&gt;
&lt;br /&gt;
| heading6 = To be ported&lt;br /&gt;
| content6 = &lt;br /&gt;
* [[Navigation display]] {{Progressbar|70}}&lt;br /&gt;
* [[Map]] {{Progressbar|80}}&lt;br /&gt;
* [[FGCanvas]] {{Progressbar|20}}&lt;br /&gt;
&lt;br /&gt;
| heading7 = Obsolete &amp;lt;br/&amp;gt;(deprecated by the Canvas)&lt;br /&gt;
| content7 =&lt;br /&gt;
* [[Complex Glass Cockpit Avionics]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;includeonly&amp;gt;{{main other|[[Category:Canvas]][[Category:Core development projects]]}}&lt;br /&gt;
{{howto other|[[Category:Canvas]][[Category:Howto]]}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
== Usage ==&lt;br /&gt;
Add the template to the top of the article text.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{Canvas Navigation}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding the template to an page in the main namespace, the article namespace, or the howto namespace will add [[:Category:Canvas]] to the page.  In addition [[:Category:Howto]] will be added to articles in the howto namespace, and [[:Category:Core development projects]] will be added to articles in the main namespace.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Navigation templates]]&lt;br /&gt;
[[Category:Canvas]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_layout_system&amp;diff=74182</id>
		<title>Canvas layout system</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_layout_system&amp;diff=74182"/>
		<updated>2014-07-21T15:03:11Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Basic Nasal API documentation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Base class for all widgets/layouts&lt;br /&gt;
#&lt;br /&gt;
var LayoutItem = {&lt;br /&gt;
  getCanvas: func(),&lt;br /&gt;
&lt;br /&gt;
  setCanvas: func(&amp;lt;Canvas&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  getParent: func(),&lt;br /&gt;
&lt;br /&gt;
  setParent: func(&amp;lt;LayoutItem&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  sizeHint: func(),&lt;br /&gt;
&lt;br /&gt;
  minimumSize: func(),&lt;br /&gt;
&lt;br /&gt;
  maximumSize: func(),&lt;br /&gt;
&lt;br /&gt;
  hasHeightForWidth: func(),&lt;br /&gt;
&lt;br /&gt;
  heightForWidth: func(&amp;lt;int: width&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  minimumHeightForWidth: func(&amp;lt;int: width&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  setVisible: func(&amp;lt;bool: visible&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  isVisible: func(),&lt;br /&gt;
&lt;br /&gt;
  isExplicitlyHidden: func(),&lt;br /&gt;
&lt;br /&gt;
  show: func(),&lt;br /&gt;
&lt;br /&gt;
  hide: func(),&lt;br /&gt;
&lt;br /&gt;
  setGeometry: func([&amp;lt;int: x&amp;gt;, &amp;lt;int: y&amp;gt;, &amp;lt;int: width&amp;gt;, &amp;lt;int: height&amp;gt;]),&lt;br /&gt;
&lt;br /&gt;
  geometry: func()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Base class for all layouts&lt;br /&gt;
#&lt;br /&gt;
var Layout = {&lt;br /&gt;
  parents: [LayoutItem],&lt;br /&gt;
&lt;br /&gt;
  # Add an item.&lt;br /&gt;
  addItem: func(&amp;lt;LayoutItem&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Set the spacing/padding between items.&lt;br /&gt;
  setSpacing: func(&amp;lt;int: space&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Get the spacing/padding between items.&lt;br /&gt;
  spacing: func(),&lt;br /&gt;
&lt;br /&gt;
  # Get the number of items (excluding nested items).&lt;br /&gt;
  count: func(),&lt;br /&gt;
&lt;br /&gt;
  # Get the item at the given position.&lt;br /&gt;
  itemAt: func(&amp;lt;int: index&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Remove and get the item at the given position.&lt;br /&gt;
  takeAt: func(&amp;lt;int: index&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Remove the given item from the layout.&lt;br /&gt;
  removeItem: func(&amp;lt;LayoutItem&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Remove all items.&lt;br /&gt;
  clear: func()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Vertical or horizontal box layout&lt;br /&gt;
#&lt;br /&gt;
var BoxLayout = {&lt;br /&gt;
  parents: [Layout],&lt;br /&gt;
&lt;br /&gt;
  addItem: func(&amp;lt;LayoutItem&amp;gt;[, &amp;lt;int: stretch&amp;gt; = 0]),&lt;br /&gt;
&lt;br /&gt;
  addStretch: func([&amp;lt;int: stretch&amp;gt; = 0]),&lt;br /&gt;
&lt;br /&gt;
  addSpacing: func(&amp;lt;int: size&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  insertItem: func(&amp;lt;int: index&amp;gt;, &amp;lt;LayoutItem&amp;gt;[, &amp;lt;int: stretch&amp;gt; = 0]),&lt;br /&gt;
&lt;br /&gt;
  insertStretch: func(&amp;lt;int: index&amp;gt;[, &amp;lt;int: stretch&amp;gt; = 0]),&lt;br /&gt;
&lt;br /&gt;
  insertSpacing: func(&amp;lt;int: index&amp;gt;, &amp;lt;int: size&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Set the stretch factor of the item at the given position to &amp;lt;stretch&amp;gt;.&lt;br /&gt;
  setStretch: func(&amp;lt;int: index&amp;gt;, &amp;lt;int: stretch&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Set the stretch factor of the given item to &amp;lt;stretch&amp;gt;&lt;br /&gt;
  # (if it exists in this layout).&lt;br /&gt;
  setStretchFactor: func(&amp;lt;LayoutItem&amp;gt;, &amp;lt;int: stretch&amp;gt;),&lt;br /&gt;
&lt;br /&gt;
  # Get the stretch factor of the item at the given position.&lt;br /&gt;
  stretch: func(&amp;lt;int: index&amp;gt;)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Horizontal box layout&lt;br /&gt;
#&lt;br /&gt;
var HBoxLayout = {&lt;br /&gt;
  parents: [BoxLayout],&lt;br /&gt;
&lt;br /&gt;
  # Create a horizontal box layout&lt;br /&gt;
  new: func()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# Vertical box layout&lt;br /&gt;
#&lt;br /&gt;
var VBoxLayout = {&lt;br /&gt;
  parents: [BoxLayout],&lt;br /&gt;
&lt;br /&gt;
  # Create a vertical box layout&lt;br /&gt;
  new: func()&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_Element&amp;diff=74123</id>
		<title>Canvas Element</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_Element&amp;diff=74123"/>
		<updated>2014-07-18T11:01:26Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Clipping&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas Elements]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
A handful of rendering primitives are available to draw on a canvas. Properties (see [[Property Tree]] for general information on FlightGear's property system) are used to control the appearance and behaviour of such ''Element''s.&lt;br /&gt;
&lt;br /&gt;
= Properties =&lt;br /&gt;
&lt;br /&gt;
== clip ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;quot;auto&amp;quot; | &amp;quot;rect(&amp;lt;top&amp;gt;, &amp;lt;right&amp;gt;, &amp;lt;bottom&amp;gt;, &amp;lt;left&amp;gt;)&amp;quot;&lt;br /&gt;
* '''Default''': &amp;quot;auto&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Set clipping rectangle for element and all its children. Only what is inside the clipping bounds will be shown.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# set clipping rectangle with x=10, y=5, width=90, height=45&lt;br /&gt;
el.set(&amp;quot;clip&amp;quot;, &amp;quot;rect(5, 100, 50, 10)&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== clip-frame ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': GLOBAL | PARENT | LOCAL&lt;br /&gt;
* '''Default''': GLOBAL&lt;br /&gt;
&lt;br /&gt;
Set the coordinate reference frame for the ''clip'' property.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# set clip reference frame to parent coordinate frame&lt;br /&gt;
el.set(&amp;quot;clip-frame&amp;quot;, canvas.Element.PARENT);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== visible ==&lt;br /&gt;
&lt;br /&gt;
== z-index ==&lt;br /&gt;
&lt;br /&gt;
* '''Format''': &amp;lt;number&amp;gt; (Integer)&lt;br /&gt;
* '''Default''': 0&lt;br /&gt;
&lt;br /&gt;
Change order in which elements are drawn. Elements with higher ''z-index'' are drawn later and cover allready drawn elements on overlapping parts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Draw before all elements (if no z-index of the other elements is lower than zero)&lt;br /&gt;
el.set(&amp;quot;z-index&amp;quot;, -1);&lt;br /&gt;
&lt;br /&gt;
# Ensure el2 is drawn before/below el1&lt;br /&gt;
el1.set(&amp;quot;z-index&amp;quot;, 51);&lt;br /&gt;
el2.set(&amp;quot;z-index&amp;quot;, 50);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_June_2014&amp;diff=73601</id>
		<title>FlightGear Newsletter June 2014</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_June_2014&amp;diff=73601"/>
		<updated>2014-06-30T22:21:35Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Canvas GUI/MessageBox&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Newsletter-header|June 2014}}&lt;br /&gt;
&amp;lt;div style=&amp;quot;border-bottom:3px double #BBB;&amp;quot;&amp;gt;&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; |&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|Development news}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|FlightGear 3.2 - Feature Freeze}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Canvas GUI: Layouting, Widgets and MessageBoxes}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Preview: Aircraft Center - get it on the fly}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Canvas/MapStructure Updates}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-header|Addons and mods}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Damage and disintegration}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Scenesetter}}&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|In the hangar}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Beechcraft Bonanza}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Saab JA-37 Viggen}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Updated P-51D now in git}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Balancing the Boeing 747-400}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Extra500 is updated to production status}}&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|Scenery corner}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|USA state capital buildings}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|LIPY, a scenery conversion from MSFS}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Reshaping Leipzig/Halle Airport}}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-header|Wiki updates}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|An updated Weather article}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|FlightGear 3.2 - Feature Freeze}}}|By [[User:t3r|TorstenD]]|Development news}}&lt;br /&gt;
On June 17, we entered our scheduled feature freeze state for the next release. Please use the remaining weeks to improve the existing features, harden and cleanup the code, edit the [[Next Changelog|ChangeLog]], improve the Manual, document the undocumented etc. etc. The release branches will be created on July 17th to have the release ready by Aug. 17th.&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|Canvas GUI: Layouting, Widgets and MessageBoxes}}}|By [[User:TheTom|TheTom]]}}&lt;br /&gt;
&lt;br /&gt;
=== Widgets and Layouting ===&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas GUI Demo Dialog.png|300px|thumb|Screen shot showing a simple [[Canvas GUI]] dialog with a handful of [[Canvas Widgets|Button Widgets]].]]&lt;br /&gt;
&lt;br /&gt;
Thanks to the recent work of Tom, the [[Canvas]] system now supports basic widgets and layouting, similar to the Qt [http://qt-project.org/doc/qt-5/layout.html Layouting System]. Using vertical and horizontal box layouts widgets can be placed and sized automatically within the available space. Together with standard widgets like buttons, checkboxes, labels and scroll areas, this is a large step forward in creating a modern, new GUI for FlightGear.&lt;br /&gt;
&lt;br /&gt;
For an example on how to use the new system see [[Howto:Creating a Canvas GUI dialog file]].&lt;br /&gt;
&lt;br /&gt;
=== MessageBoxes ===&lt;br /&gt;
&lt;br /&gt;
Based on the new widgets and layouts, [[Canvas MessageBox|Message Boxes]] provide a simple way to report information to the user or ask him simple questions with a standardized appearance. Selecting from a predefined set of icons and buttons showing a message can be as simple as:&lt;br /&gt;
&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;
&lt;br /&gt;
Get more information on how to [[Canvas MessageBox|create Message Boxes on your own...]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Canvas-MessageBox-demo information.png|Reporting information&lt;br /&gt;
Canvas-MessageBox-demo warning dont-show-again.png|Showing a warning (allowing the user to not get it reported the next time)&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|Preview: Aircraft Center - get it on the fly}}}|By [[User:TheTom|TheTom]] and [[User:Zakalawe|Zakalawe]]}}&lt;br /&gt;
&lt;br /&gt;
[[File:Aircraft-center-prototype.png|270px|thumb|Canvas dialog showing the prototype for an [[Aircraft Center]] for directly installing/managing aircraft from within FlightGear, an upcoming feature scheduled for FlightGear 3.2, currently being developed by TheTom and Zakalawe]]&lt;br /&gt;
The &amp;quot;built-in&amp;quot; GUI/launcher is one of the longest-standing feature requests - but it's not just about the GUI (which is rather straightforward in comparison), but about the simulator never having  been developed with this requirement, i.e. run-time reinitialization, in mind - thus, things like &amp;quot;fgrun&amp;quot; (and a plethora of other external launchers) were developed, which acted as a front-end on top of FG, so that FG itself wouldn't need to be changed - i.e. kind of a &amp;quot;remote control&amp;quot; using command line arguments. So it's there for a reason - fgrun uses the FLTK GUI library, which while relatively simple, is much more powerful than our legacy GUI engine, PUI.&lt;br /&gt;
&lt;br /&gt;
Still, people have been asking for this for years, and it's thanks to pretty much a single person, Zakalawe, that switching aircraft is going to become possible pretty soon - he handled all the ugly work of cleaning up the simulator internals to make this happen - it's not exactly glamorous work, you gotta touch a ton of places, and you inevitably introduce a ton of regressions along the way.&lt;br /&gt;
&lt;br /&gt;
And yes, even the legacy FG GUI is entirely based on XML and configurable through just editiing XML files - but the collection of &amp;quot;widgets&amp;quot; (GUI controls like buttons, checkboxes, labels etc) is extremely small and very inflexible.&lt;br /&gt;
&lt;br /&gt;
This is something that is currently being addressed by TheTom and Zakalawe, who've both been working on a new Canvas GUI, and a new Canvas GUI dialog called &amp;quot;Aircraft Center&amp;quot;, which -while still experimental- is intended to eventually allow end-users to easily download/install aircraft right within the simulator, and also switch between aircraft at run-time without having to exit/restart the simulator.&lt;br /&gt;
&lt;br /&gt;
Thus, adopting Canvas is going to address a number of long-standing issues, but it's obviously a process that only just got started, and it will not happen overnight - 2-3 release cycles are not far-fetched, that's how long the whole migration could very well take, unless there are more people interested in helping.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Canvas/MapStructure Updates|By [[User:Hooray|Hooray]] and [[User:Philosopher|Philosopher]]}}&lt;br /&gt;
&lt;br /&gt;
The upcoming FlightGear version (3.2) will contain a canvas-based map dialog, including a modular &amp;quot;plugin&amp;quot; system for creating custom map layers and charts with roughly ~50 lines of code, most of it boilerplate. This is entirely XML/Nasal based (scripted) - symbols can be pretty much anything, raster or vector images (png or svg), but even animated. Styling can be customized, too.&lt;br /&gt;
&lt;br /&gt;
For more info, I suggest to check out: [[MapStructure#Porting the map dialog]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
MapStructureDialog.png|You can basically create arbitrary layers, even for custom objects/positions&lt;br /&gt;
Map-canvas-chain-home-editor.png|The same method can be used for creating a &amp;quot;live&amp;quot; radar display&lt;br /&gt;
MapStructure-TFC-Troubleshooting.png|&lt;br /&gt;
Map-canvas-dialog-storms-overlay.png|But maps and layers can be fairly sophisticated, too - all 100% scripted&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As long as you use the MapStructure framework, all layers can be easily used in dialogs AND instruments&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Coding-wise, there isn't too much involved these days, all the details are covered in the MapStructure article.&lt;br /&gt;
&lt;br /&gt;
[[File:Map-canvas-mapstructure-performance.png|thumb|stress-testing [[MapStructure]] using the ufo @ KSFO circling at 2000 kts in a climb, see [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=21509&amp;amp;p=211611#p211611] ]]&lt;br /&gt;
&lt;br /&gt;
Now that Hyde has committed Philosopher's latest changes, I'd be interested in getting some more feedback on performance.&lt;br /&gt;
Here, I am using the ufo @ksfo circling in a shuttle climb at &amp;gt;= 2000 kts GS and getting roughly 30 fps and 40-60 ms.&lt;br /&gt;
&lt;br /&gt;
The recent GUI work committed by TheTom means that we can phase out the PUI map-canvas.xml dialog and create the whole dialog procedurally using a native canvas window, because we really only need two types of widgets: buttons and checkboxes, which are both supported now, thanks to the new [[Aircraft Center]]. &lt;br /&gt;
&lt;br /&gt;
We're also in the process of turning our map-canvas.xml dialog into a generic, and reusable, widget for $FG_ROOT/Nasal/canvas/gui/widgets - the widget is using the new Layout engine to align other widgets (checkboxes &amp;amp;amp; buttons for now). And one of our goals is to also modernize airports.xml (the airport selection dialog) such that it can use MapStructure. The simplest way would be to simply turn the PUI CanvasWidget into a Canvas.Window() so that layouting etc works as expected, and so that we can simply show the new scripted MapWidget there.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Native Canvas MapWidget Dialog.png|Native Canvas MapWidget dialog using just Canvas Widgets, the Map has been turned into a Canvas Widget itself, so that it can be easily embedded in other dialogs (obviously the whole thing still needs to be cleaned up, layouting isn't currently used yet). See [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23391&amp;amp;p=213435#p213435]&lt;br /&gt;
Native Canvas MapWidget Dialog Prototyping.png|More Canvas/MapWidget prototyping. See [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23391&amp;amp;p=213435#p213435]&lt;br /&gt;
MapStructure dialog with clipping and event handling applied.png|Screen shot showing TheTom's modified demo dialog with a [[MapStructure]] based map that has clipping and event handling applied, i.e. can respond to common mouse events in order to either display tooltips or support drag&amp;amp;drop-style GUI dialogs for editing map-like displays, e.g. for creating an [[Advanced weather]] GUI[http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=17642]. Particular care must be taken to formalize z-index handling (rendering priority) for each MapStructure layer, which is something we still need to work out, especially for possibly overlapping symbols...&lt;br /&gt;
MapStructure-based Weather Editor Widget for Canvas using interactive and editable lcontroller files.png|This screen shot shows an experimental MapStructure-based Weather Editor Widget for [[Canvas]] using interactive and editable lcontroller files that respond to GUI events so that map symbols can be interactively placed on a map.&lt;br /&gt;
The legacy PUI-airport selection dialog using the new Canvas MapWidget.png|This is a screen shot showing Stuart's PUI/XML based airport selection dialog with an embedded Canvas MapWidget that is driven by Philosopher's [[MapStructure]] framework using TheTom's latest GUI/Layouting changes (e.g. checkbox widgets).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Boeing 777 EFB prototype|By [[User:I-NEMO|I-NEMO]]}}&lt;br /&gt;
[[File:777-EFB-MAIN.png|thumb|777-200ER EFB [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23196]]]&lt;br /&gt;
[[File:777-EFB-AIRPORT-SEARCH.png|thumb|777-200 EFB AIRPORT SEARCH, see [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23196&amp;amp;p=211410#p211410]]]&lt;br /&gt;
&lt;br /&gt;
I-NEMO has started porting his 777/EFB prototype to [[Canvas]]&lt;br /&gt;
&lt;br /&gt;
As I wrote several times, I finally decided to put hands on the EFB (Reason: No one ever took care of developing an EFB for the 777; a 'working' EFB, though) with two (2) main goals in mind:&lt;br /&gt;
# do something to compensate for the lacking of an EFB inside the Boeing 777 Seattle.&lt;br /&gt;
# actually try (I repeat it: 'try') to learn some first essentials of nasal.&lt;br /&gt;
&lt;br /&gt;
This Seattle EFB is just a 'rude' one: with this term, I mean (as a word's pun) 'unpolite'. I'm perfectly aware that the coding is horrible, clumsy, repetitive, silly and very, very far from what it should be. My first aim was simply to have a somehow 'working' EFB inside the Seattle's Cockpit. I do not pretend that current 777's EFB.nas is a piece of nice software; but - to my initial purpose - it works. Not completely, not nicely, not properly...but it's a starting point. At least, it works...&lt;br /&gt;
Current development ('modernisation' phase) of the '''Boeing 777 Seattle's EFB''' is going on nicely; the code is shorter, more readable and cleaner.&lt;br /&gt;
I have not finished it, yet (I'd say that it's almost 50% done).&lt;br /&gt;
&lt;br /&gt;
At the moment I have a single Canvas group (i.e., ''EFB_group''), with 5 children: the text-matrix (16 left lines, 16 right lines), a Title line , an Helper line and the Display.&amp;lt;br/&amp;gt;&lt;br /&gt;
The ''Display'' element is then textured with all the various pages' textures, called by the page-handler (''see'' here below).&amp;lt;br/&amp;gt;&lt;br /&gt;
Currently, I'm using the .jpg textures which I had previously generated through Photoshop; in the future they might be replaced by .svg files, depending from actual interactive use of some graphical objects (a few EFB pages do need interaction with graphical parts). Besides - if i'm not wrong - I've read somewhere on the FGWiki that gradients are not handled by the SVG parser...and I do like to use some gradients effects (antialiasing and such) to achieve a sort of realism on the displays.&lt;br /&gt;
&lt;br /&gt;
that's the &amp;lt;u&amp;gt;current status&amp;lt;/u&amp;gt; of the new 777 ''Seattle'''s EFB: it's still far from being perfect, but - as a newbie - I'm quite satisfied for the moment: I need to finish the first version fairly soon, because my to-do-list is long (I have to re-model all the aircraft fuselage [original model has wrong measures, ''sigh!''], produce better gears and flight-control surfaces model &amp;amp;amp; animations in Blender, and then to produce a new Paint-Kit in Photoshop; then all 3D models optimizations...and so forth; of course, we also have to take care of CDU, which will interface with the EFB. So, the job is still very, very long...&lt;br /&gt;
&lt;br /&gt;
The current EFB code is heavily focused on rendering raster images, which can be retained obviously, but in FG, we have additional means to render airport information that is 100% in sync with the FG side of things (navdb). &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
For instance, we are going to &amp;quot;port&amp;quot; the airport-selection dialog to move rendering of airports/runways/taxiways/parking spots into dedicated MapStructure layers that can be properly styled and customized: [[Canvas_MapStructure#Porting_the_airports.xml_dialog]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Airport-selection-dialog.png|250px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As you can probably tell, these kinds of layers would be very useful for any  kind of EFB related application.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As long as the underlying design for a &amp;quot;page&amp;quot;-based MFD framework is sufficiently generic, we can easily replace/augment raster images and procedurally created charts - we could even use the built-in support for fetching via HTTP to download images on-line. In fact, we could then even extend Canvas to directly support rendering PDFs (OSG supports this out-of-the-box), this would make many steps unnecessary, because we could directly access [http://airnav.com http://airnav.com] without having to download/convert/ship any imagery. The code required to pull this off would be very compact in comparison.&lt;br /&gt;
&lt;br /&gt;
Learn more at [[Canvas EFB Framework]] or follow the [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23204 forum discussion]...&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Towards an Aircraft-agnostic MFD Framework|By [[User:Hooray|Hooray]]}}&lt;br /&gt;
Given the recent trend of having several MFD-related efforts without any kind of collaboration/code reuse going on here among our contributors (PFD, ND, Avidyne Entegra R9, EFB), I have started prototyping a generic MFD framework that is purely XML-based, inspired by discussions we've had over the last couple of weeks, and lessons learnt from the missions subsystem.&lt;br /&gt;
&lt;br /&gt;
It is intended to:&lt;br /&gt;
* support multiple independent instances&lt;br /&gt;
* be totally aircraft agnostic&lt;br /&gt;
* support a pure dialog-driven mode&lt;br /&gt;
* support skinning/theming&lt;br /&gt;
&lt;br /&gt;
This is supposed to support modeling complex avionics like a PFD, ND, EFB, CDU etc - and, eventually, also the Avidyne Entegra R9. It's currently just a prototype, but it gets away with very little code and we really only need a few more &amp;quot;skins&amp;quot; for common avionics. I am willing to extend this over time and help maintain it if people can agree to use something like this. It should be straightforward to allow such &amp;quot;MFDs&amp;quot; to be reloaded from disk at run-time, i.e. for more rapid prototyping.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is work in progress - the idea is to identify required building blocks to easily specify most MFD functionality in a generic fashion, without requiring a ton of custom Nasal code and without being specific to a single type of MFD. The whole concept is based on [[FlightGear_Missions_and_Adventures#XML_Extension_Framework]], i.e. providing a Nasal-space mechanism to expose and re-define building blocks to XML space.&lt;br /&gt;
&lt;br /&gt;
The Nasal/Canvas data structures will be transparently created and compiled for each MFD. Each MFD consists of an arbitrary number of buttons, modes and pages. Each MFD can be instantiated multiple times, and each MFD is designed to be aircraft/instrument agnostic, i.e. also works just in a conventional Canvas dialog. Buttons can trigger and switch between modes, and modes may have pages (conventionally implemented through a single SVG file). Each page consists of an arbitrary number of page elements, which can in turn be animated/updated via listeners and timers.  Should look at existing displays, especially the [[NavDisplay]] and the update() method in navdisplay.mfd, but the most complete test-case would probably be the [[Avidyne Entegra R9]] }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Gpsmap196-canvas-panel-page.png|F-JJTH has updated the SVG file implementing the panel page for the [[Garmin GPSMap 196]].&lt;br /&gt;
Canvas-mfd-framework-prototyping.png|This is an adapted version of the [[Garmin GPSMap 196]] that is currently being developed by F-JJTH. Here, the whole instrument is entirely set up in XML space, including buttons/event handling, but also the embedded canvas region that serves as the 'screen'. The idea is to allow arbitrary MFDs to be specified in an aircraft-agnostic fashion, including displays like a PFD, [[NavDisplay]] or EFB. For details, please see [[Canvas Glass Cockpit Efforts]].&lt;br /&gt;
Canvas-mfd-framework-prototyping-with-mapstructure.png|This demonstrates how a purely XML-based MFD framework can instantiate dynamic [[MapStructure]] layers - none of this involves any [[Nasal]] coding now, it's just an XML file - to learn more, see [[Canvas Glass Cockpit Efforts]].&lt;br /&gt;
Canvas-mfd-framework-prototyping-with-mapstructure-with-kln89-skin.png|This screen shot shows the texture of the hard-coded KLN89 instrument used as a skin/theme for the MFD instrument, with a MapStructure-powered map shown.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Logo proposal|By [[User:Aepcam|Aepcam]]}}&lt;br /&gt;
This is a new logo badge concept proposal for FlightGear designed by Michat.&lt;br /&gt;
&lt;br /&gt;
[[File:Fglogo1.png]]&lt;br /&gt;
[[File:Fglogowiki.png]]&lt;br /&gt;
[[File:Fglogoforum.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Damage and disintegration|By [[User:Algernon|Algernon]]|FlightGear addons and mods}}&lt;br /&gt;
{{#ev:youtube|OpwNaoO3xMQ|200|right|Tomaskom's V-1 used in anger over London}}&lt;br /&gt;
{{#ev:youtube|H4XDuLo35ks|200|right|Victor V2.0 damage script causing a catastrophic failure and fire}}&lt;br /&gt;
{{#ev:youtube|uLojBI7ezdM|200|right|L-159 disintegration}}&lt;br /&gt;
The development team at FGUK have been experimenting with modelling aircraft damage in a number of different ways. First of all, Tomaskom has used the particle system carefully to produce visually impressive fireballs and smoke columns with very little FPS impact. First seen in his V-1, we hope to adapt this to simulate realistic fireballs for ground impacts (where appropriate). For the moment, it explodes with the full force of a V-1's explosive payload. On the right is a video excerpt from the #FlightNight which Tom organised to debut the V-1, where we all had '''way''' too much fun bombing London. As you can see, the smoke is visible from quite a long way away from the impact, and despite two fires burning with huge smoke columns, and over ten multiplayer aircraft within model range, the frame rates are still more than acceptable. StuartC has already integrated the explosion and fireball into several development aircraft, and we expect eventually to combine it with the disintegration code and make the size of the explosion dependent on fuel load etc.&lt;br /&gt;
&lt;br /&gt;
In a separate development, Algernon's work on the Victor V2.0(YASim) now includes modelled damage, a collection of Nasal scripts, some modified from existing FlightGear staples, which detects irregularities such as component failures, birdstrikes and combat weapon damage and adversely affects system performance and reliability accordingly. Unserviceability often follows, using the existing FlightGear failures system, and compatibility will be maintained as the failures system is improved. The damage script also calculates probabilites for chain reaction damage - for instance, an explosion or serious fire in one Victor engine will usually have an effect on the other. In extreme circumstances, an explosion will trigger further explosions and destroy the aircraft. The second video on the right shows a serious induced explosion on the Victor's number one engine at night. Some fine-tuning of the Rembrandt light has been carried out since this video was shot, so apologies for the visible cut-off.&lt;br /&gt;
&lt;br /&gt;
Finally, and most spectacularly, Tomaskom has demonstrated the disintegration capabilities of his L-159, which is under development. Hopefully, he will explain all here before publication date.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Scenesetter|By [[User:Algernon|Algernon]]}}&lt;br /&gt;
Scenesetter is a piece of code by Algernon, very early in development but already quite effective, which can effect changes to the time and weather from an AI scenario synchronously with other MP players. A crude proof of concept was used in the recent FGUK #FlightNight &amp;quot;British Weather&amp;quot;, where pilots visited different airfields with various unpleasant flying conditions. Scenesetter pushes METAR strings to the FlightGear weather system based on the location of an associated Navaid, establishing a circular zone of a specified radius around it in which METAR will be changed. Start time can be specified too, either by providing a local start time or a local time offset (useful for Multiplayer use where players will not all start the AI scenario at precisely the same time).&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Beechcraft Bonanza|By [[User:Flyingfisch|Flyingfisch]]|In the hangar}}&lt;br /&gt;
Flyingfisch is building the Beechcraft A35 Bonanza for Flightgear. Some pictures:&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Beech_bonanza_with_panel_lights_on.png|Panel lighting&lt;br /&gt;
Bonanza rbf.png|Remember to do your pre-flight check before startup!&lt;br /&gt;
Bonanza at sunrise.png|The Beech Bonanza at Kent State University (1G3) just before sunrise&lt;br /&gt;
Bonanza interior at sunrise.png|The interior of the Bonanza at sunrise.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Saab JA-37 Viggen|By [[User:Necolatis|Necolatis]]}}&lt;br /&gt;
The Swedish fighter jet [[Saab JA-37 Viggen]] has been updated, since it was included in FlightGear 3.0. More instruments, additional liveries, aerodynamic response to payload and tooltips on instruments. Option for automatic reverse thrust at touchdown, selection of HUD brightness, disabling of structural damage. HUD can now switch to imperial units and show MP and AI aircraft and closest airport. The aircraft now also has multiplayer sounds and better cockpit view helps seeing the landing strip. Support for FG 2.8 by deleting a small section in an xml file. Also worth mentioning is countless bug-fixes and improvements, e.g. better handling at high altitudes and a bug fix in the lift force formula.&lt;br /&gt;
&lt;br /&gt;
[[File:Saab JA-37 Viggen Blue Peter Livery.png|Blå Petter Livery for JA-37]]&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Updated P-51D now in git|By [[User:hvengel|hvengel]]}}&lt;br /&gt;
The new 3D exterior model for the [[North American P-51 Mustang|North American P-51D Mustang]] is now in git and under active development. It is currently in gray primer waiting for the UV map to be finalized. It is now fully integrated into the existing FDM.  Extensive new animation work has been done including animated trim tabs and a fully functional canopy. Here are some screen shots taken in sim for your enjoyment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed heights=250px&amp;gt;&lt;br /&gt;
P-51D testing it's guns before a flight..jpg|P-51D testing it's guns before a flight.&lt;br /&gt;
P-51D trim tab animation..jpg|P-51D trim tab animation.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Balancing the Boeing 747-400|By [[User:Gijs|Gijs]]}}&lt;br /&gt;
After he started developing the [[Boeing 747-400]] as a hobby project six years ago, Gijs finally managed to get the weight and balancing right. The center of gravity is now within 0.05% MAC (40 cm) of the published values.&lt;br /&gt;
&lt;br /&gt;
Make sure to use the new Fuel and Payload dialog to fill your fuel tanks. There is a slider and button that will nicely distribute a specified amount of fuel, while making sure the CoG stays within the operational limits. Before takeoff, check the Takeoff Reference page on the CDU to find the required stab trim units (your current setting is displayed to the left of the throttle quadrant). When you set your trim properly, you can almost relax your yoke to the neutral position after rotate. There's still some FDM work left to fine-tune this.&lt;br /&gt;
&lt;br /&gt;
The updated 747-400 is already available through Git and will be on the download page when FlightGear 3.2 is released.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Extra500 is updated to production status|By [[User:Evandenberg|Evandenberg]]}}&lt;br /&gt;
The [[Extra EA-500]] is updated and has reached &amp;quot;production status&amp;quot;! Just a short list of changes for release 1.1.0:&lt;br /&gt;
* Engine+fuel: realistic flame-out, fuel flow to collector compartment, anti ice influence on TOT, improved oil press and temp model&amp;lt;br/&amp;gt;&lt;br /&gt;
* Aerodynamics: flap performance, elevator-30deg-flaps authority improvement&amp;lt;br/&amp;gt;&lt;br /&gt;
* User interface: interactive checklists&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sounds: corrected sounds for test, CWS and AP disc&amp;lt;br/&amp;gt;&lt;br /&gt;
* Model: added interior, yokes&amp;lt;br/&amp;gt;&lt;br /&gt;
* Avionics: IFD moving map, automatic NAV tuning, automatic NAV switching, magnetic variation fixes&amp;lt;br/&amp;gt;&lt;br /&gt;
* Autopilot: added OBS and fly vectors mode, significant improvement of coupled ILS performance&lt;br /&gt;
A more extensive list can be found in the &amp;quot;version&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
This version does perform a bit better on my computer, but this has to do with improvements to FGFS, not of the aircraft model. So if your computer was struggling with the initial version, we recommend to use current FlightGear git/nightly builds or wait until 3.2 comes out!&lt;br /&gt;
&lt;br /&gt;
Please checkout the [[Extra EA-500|Extra500 wiki]] for download instructions and lots of more info.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed heights=250px&amp;gt;&lt;br /&gt;
File:Extra500 flightgear1.png|Extra500 flying in clouds&lt;br /&gt;
Extra500canvas.png|Work has begun to analyze, refactor and generalize useful parts of the [[Avidyne Entegra R9]] to help reuse some code in similar MFD efforts, like the [[Garmin GPSMap 196]] or [[Canvas EFB Framework]]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|USA state capital buildings|By [[User:Jonbourg|Jonbourg]]|Scenery corner}}&lt;br /&gt;
There is a project to add all the USA state capital buildings into FG.  It is discussed in [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22715&amp;amp;sid=ea847909bde2e1f8ffe5b94bcc673f4f this scenery forum thread]. There is also a wiki page: [[State Capitol Buildings in the United States]].  So far, Idaho, Louisiana &amp;amp; Nebraska have been completed. Hawaii and New York are currently in progress.  Please feel free to join in with any other state that has not been done yet.  Just let us know through the forum and we will add it to the in progress list.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|LIPY, a scenery conversion from MSFS|By [[User:bigstones|bigstones]]}}&lt;br /&gt;
This month saw the [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22623 second &amp;quot;preview&amp;quot; release] of the conversion of a scenery for MS Flight Simulator, [[Falconara Airport]] (ICAO code: LIPY), a small Italian international airport halfway down the Adriatic coast. The original author granted the permission to the conversion and even allowed for it to be included in the FlightGear official [[World Scenery]], at least the GPL compatible parts. This is not a huge limitation though, because most of the material was created from scratch, included pictures taken on purpose at the real airport, with the authorities' collaboration. Copyrighted aerial imagery only include the (unsuable) photoreal ground and some roofs.&lt;br /&gt;
&lt;br /&gt;
[[File:LIPY structures landscape.jpg|650px|right]]&lt;br /&gt;
The conversion was made with [[ModelConverterX]], which makes the job partially easier than by [[Howto:Convert objects from X-Plane|the Blender method]], yet it's still needing fixes because of some misunderstandings with the coordinates axes. The author of the tool, though, seems not very concerned and anyway, it's so rare to have a freeware scenery author allow conversions, that the usefulness of this tool would be greatly reduced anyhow, especially if you plan to upload the models to the [[FlightGear Scenery Database]].&lt;br /&gt;
&lt;br /&gt;
The conversion itself, moreover, sure is not the matter of a button press. MSFS scenery are often packed and &amp;quot;compiled&amp;quot; in *.BGL files such that independent, far objects with the same materials and same LOD level (Level Of Detail) are bound together. This is clearly against FG's way, in which each new scenery generation could change the relative heights, and however MSFS airports are flat, while in FG they're all sloped. A similar thing happens with the texture maps. This basically means that you'll have to join all these objects and split them again based on the model they belong to (e.g. tower, terminal, hangars...)&lt;br /&gt;
&lt;br /&gt;
Another issue with textures is that in FG it's good practice - recommended if not mandatory - to have 2 separate texture maps for the same object, if some parts are translucent. This means that without rebuilding all the texture maps [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22707 you'll likely get artifacts]. Then, you'd have to add the Rembrandt lights if you want, and also the lightmaps (MSFS uses night textures, but Gimp can easily convert them). This whole experience can be summed up in the following quote:&lt;br /&gt;
&lt;br /&gt;
{{cquote|I really wanted to have this scenery in FG because it's my home base, and seeing it ready and so well done just made me want it. However, even if still easier than making it from scratch (even if reusing the textures), I'd have to think well if I had to do this again.|bigstones, maintainer of the conversion}}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Reshaping Leipzig/Halle Airport|By [[User:August|August]]}}&lt;br /&gt;
[[File:2014 new-layout-EDDP 05.jpg|650px|right]]&lt;br /&gt;
In FlightGear Germany's second largest cargo airport [[EDDP]] is well known as a detailed model accessible for everybody via [[TerraSync]]. Until 2013 it was famous for its regular ATC-events. It has been updated several times, at least 2012 by users D-STHO and August. When FlightGear 3.0 was published the airport layout changed from the old 810-standard to the new 850-standard. But the update (based on a taxiway layout modelled for X-Plane) turned out to be very imperfect. Many aprons and taxiways did not exist, dimensions did not appear to be correct and many new facilities which had been added at the real-world airport had not been taken into account. So maintainer August decided to redesign the whole airport from the scratch using [[WorldEditor]]. &lt;br /&gt;
Pilots and developers are now invited to test the new airport model which includes further improvements like predefined STAR-, -SID and Transition procedures and hundreds of replaced Static- and Shared Models. The project will be published on TerraSync as soon as all defects are discovered remedied.&lt;br /&gt;
&lt;br /&gt;
Developer Version:&lt;br /&gt;
   '''git clone''' [https://gitorious.org/eddp-custom-scenery/eddp-custom-scenery/ https://gitorious.org/eddp-custom-scenery/eddp-custom-scenery/]&lt;br /&gt;
&lt;br /&gt;
Feedback is welcome at [[User talk:August|August's wiki page]].&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
2014 new-layout-EDDP 04.jpg|Taxiway T - new ground textures&lt;br /&gt;
2014 new-layout-EDDP 01.jpg|Runway 26L with DHL-area&lt;br /&gt;
2014 new-layout-EDDP 02.jpg|Apron 4&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|An updated Weather article|By [[User:bigstones|bigstones]]|Wiki updates}}&lt;br /&gt;
The [[Weather]] wiki article went through a wide extension. Although Advanced Weather was released quite a while ago, its usage has never been explained in the wiki, and some thorough instructions were available only in a readme in the &amp;quot;docs&amp;quot; folder of the base package which is not commonly explored by users, while the wiki article [[Advanced weather]] is more about the project than the usage.&lt;br /&gt;
&lt;br /&gt;
AW's advanced configuration is known to be not easy. So, if you always only used the weather selection menu and want to know more, or want to understand what the options actually do and how you can combine them, the [[Weather]] article has now been updated with some hints and basic notions extracted from experience and the original documentation, and quality checked by the author of the AW weather engine.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Translators required|}}&lt;br /&gt;
{|&lt;br /&gt;
|[[File:en.gif]]&lt;br /&gt;
|The FlightGear Wiki still needs help for translating it into various languages. If you are interested in making the FlightGear Wiki multi-language then start at [[Help:Translate]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:de.gif]]&lt;br /&gt;
|Das FlightGear Wiki benötigt immer noch Hilfe bei der Übersetzung in verschiedene Sprachen. Wenn Du Interesse daran hast, das FlightGear Wiki Mehrsprachig zu machen, dann fang doch mit [[:de:Help:Übersetzen|Help:Übersetzen]] an.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:nl.gif]]&lt;br /&gt;
|De FlightGear Wiki kan nog steed hulp gebruiken bij het vertalen van artikelen. Als je interesse hebt om de wiki meertalig te maken, raden we je aan om een kijkje te nemen bij [[:nl:Help:Vertalen|Help:Vertalen]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:es.gif]]&lt;br /&gt;
|La FlightGear wiki todavía necesita ayuda para traducirla a varios lenguajes. Si estás interesado en hacer la FlightGear wiki multilingüe, entonces comienza en [[:es:Help:Traducir|Help:Traducir]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Call for volunteers||And finally...}}&lt;br /&gt;
* The [[TerraGear]] maintainers are looking for volunteers to help with development on the next world scenery project.  If you've ever wondered how a full 3D model of earth can be generated from raw data, now is your chance.  See the plan at [[TerraGear roadmap]].&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2014 06]]&lt;br /&gt;
[[Category:Changes after 3.00]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Aircraft-center-prototype.png&amp;diff=73600</id>
		<title>File:Aircraft-center-prototype.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Aircraft-center-prototype.png&amp;diff=73600"/>
		<updated>2014-06-30T21:36:25Z</updated>

		<summary type="html">&lt;p&gt;TheTom: TheTom uploaded a new version of &amp;amp;quot;File:Aircraft-center-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=Canvas dialog showing the prototype for an [[Aircraft Center]] for directly installing/managing aircraft from within FlightGear, an upcoming feature scheduled for FlightGear 3.2, currently being developed by TheTom and Zakalawe}}&lt;br /&gt;
|date=2014-06-13 20:37:55&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas_VBoxLayout_Demo_Dialog.png&amp;diff=73597</id>
		<title>File:Canvas VBoxLayout Demo Dialog.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas_VBoxLayout_Demo_Dialog.png&amp;diff=73597"/>
		<updated>2014-06-30T21:08:31Z</updated>

		<summary type="html">&lt;p&gt;TheTom: TheTom uploaded a new version of &amp;amp;quot;File:Canvas VBoxLayout Demo Dialog.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 a simple [[Canvas GUI]] dialog with a handful of [[Canvas Widgets|Button Widgets]].}}&lt;br /&gt;
|date=2014-06-29 20:02:36&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas_GUI_Demo_Dialog.png&amp;diff=73594</id>
		<title>File:Canvas GUI Demo Dialog.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas_GUI_Demo_Dialog.png&amp;diff=73594"/>
		<updated>2014-06-30T21:05:12Z</updated>

		<summary type="html">&lt;p&gt;TheTom: TheTom moved page File:Canvas GUI Demo Dialog.png to File:Canvas VBoxLayout Demo Dialog.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[File:Canvas VBoxLayout Demo Dialog.png]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas_VBoxLayout_Demo_Dialog.png&amp;diff=73593</id>
		<title>File:Canvas VBoxLayout Demo Dialog.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas_VBoxLayout_Demo_Dialog.png&amp;diff=73593"/>
		<updated>2014-06-30T21:04:57Z</updated>

		<summary type="html">&lt;p&gt;TheTom: TheTom moved page File:Canvas GUI Demo Dialog.png to File:Canvas VBoxLayout Demo Dialog.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Screen shot showing a simple [[Canvas GUI]] dialog with a handful of [[Canvas Widgets|Button Widgets]].}}&lt;br /&gt;
|date=2014-06-29 20:02:36&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Creating_a_Canvas_GUI_dialog_file&amp;diff=73589</id>
		<title>Howto:Creating a Canvas GUI dialog file</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Howto:Creating_a_Canvas_GUI_dialog_file&amp;diff=73589"/>
		<updated>2014-06-30T21:00:15Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Demo code tweaks/prepare for better screenshot&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Stub}}&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas GUI Demo Dialog.png|300px|thumb|Screen shot showing a simple [[Canvas GUI]] dialog with a handful of [[Canvas Widgets|Button Widgets]] arranged with a vertical/vbox layout.]]&lt;br /&gt;
{{Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
'''Targeted FlightGear versions: &amp;gt;= 3.20'''&lt;br /&gt;
&lt;br /&gt;
== Editing Translations/en/menu.xml ==&lt;br /&gt;
Navigate to the sub-menu where you'd like to add your new dialog, e.g. &amp;quot;Equipment&amp;quot; in this case, and then add a key:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;equipment&amp;gt;Equipment&amp;lt;/equipment&amp;gt;&lt;br /&gt;
&amp;lt;canvas-demo-dialog&amp;gt;Canvas Demo Dialog&amp;lt;/canvas-demo-dialog&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Editing gui/menubar.xml ==&lt;br /&gt;
Next, open $FG_ROOT/gui/menubar.xml and navigate to the corresponding sub-menu and add a new item/binding to load your dialog:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;item&amp;gt;&lt;br /&gt;
&amp;lt;name&amp;gt;canvas-demo-dialog&amp;lt;/name&amp;gt;&lt;br /&gt;
&amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
canvas.loadDialog(&amp;quot;CanvasDemo&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating the actual dialog file ==&lt;br /&gt;
{{Note|These dialog files can be edited at run-time and simply closed/re-opened, because the Canvas system will reload them from disk whenever the menu binding is triggered. So this is very convenient for quickly developing and testing your dialogs. For testing purposes, you can also paste the snippet into your [[Nasal Console]] and directly execute it.}}&lt;br /&gt;
Next, open/create $FG_ROOT/Nasal/canvas/gui/dialogs/CanvasDemo.nas and add some boilerplate code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var DemoDialog = {&lt;br /&gt;
  new: func&lt;br /&gt;
  {&lt;br /&gt;
    var m = {&lt;br /&gt;
      parents: [DemoDialog],&lt;br /&gt;
      _dlg: canvas.Window.new([140,160], &amp;quot;dialog&amp;quot;)&lt;br /&gt;
                         .set(&amp;quot;title&amp;quot;, &amp;quot;VBoxLayout&amp;quot;)&lt;br /&gt;
                         .set(&amp;quot;resize&amp;quot;, 1),&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    m._dlg.getCanvas(1)&lt;br /&gt;
          .set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&lt;br /&gt;
    m._root = m._dlg.getCanvas().createGroup();&lt;br /&gt;
 &lt;br /&gt;
    var vbox = canvas.VBoxLayout.new();&lt;br /&gt;
    m._dlg.setLayout(vbox);&lt;br /&gt;
&lt;br /&gt;
    # this is where you can add widgets from $FG_ROOT/Nasal/canvas/gui/widgets, e.g.:&lt;br /&gt;
    for(var i = 0; i &amp;lt; 5; i += 1 )&lt;br /&gt;
      vbox.addItem(&lt;br /&gt;
        canvas.gui.widgets.Button.new(m._root, canvas.style, {})&lt;br /&gt;
                                 .setText(&amp;quot;Button #&amp;quot; ~ i)&lt;br /&gt;
      );&lt;br /&gt;
&lt;br /&gt;
    var hint = vbox.sizeHint();&lt;br /&gt;
    hint[0] = math.max(140, hint[0]);&lt;br /&gt;
    m._dlg.setSize(hint);&lt;br /&gt;
&lt;br /&gt;
    return m;&lt;br /&gt;
  },&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var demo = DemoDialog.new();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, start FlightGear and open your new dialog&lt;br /&gt;
&lt;br /&gt;
== Adding Widgets ==&lt;br /&gt;
In order to keep your dialog sufficiently generic, you'll want to refrain from adding too much custom functionality to it, and instead decompose your functionality into a collection of '''widgets'''. Widgets are GUI controls like a label, button, checkbox etc - i.e. these widgets have a certain appearance and may respond to events such  as being clicked for example. Whenever you create custom widgets instead of adding all the code to a single dialog, you'll end up with reusable components that can be easily other in other dialogs. In addition, you are making sure to establish a losely-coupled design, so that your widgets are sufficient generic and do not contain any use-case specific logic.&lt;br /&gt;
&lt;br /&gt;
This means for example that a generic '''PropertyBrowser''' could be easily reused in other dialogs/windows requiring a corresponding property browser. But this also meanns that such a property browser widget should also be modularized, i.e. by using a lower-level '''ListView''' or '''TreeView''' widget and merely parameterizing that by showing properties. This approach has the added advantage that the corresponding '''ListView/TreeView''' widgets could be re-used in other places, such as for example an aircraft list, a [[Nasal Browser|Nasal Namespace Browser]].&lt;br /&gt;
&lt;br /&gt;
Likewise, a widget-focused approach means that useful functionality like a [[Interactive Nasal REPL]] can be easily used in other places, without developers having to do any refactoring.&lt;br /&gt;
&lt;br /&gt;
We're also trying to make sure that Canvas Widgets can be easily used not just by GUI dialogs but also by Canvas-based instruments/MFDs - without any code duplication or Copy&amp;amp;Paste being required.&lt;br /&gt;
&lt;br /&gt;
== Using Layouts ==&lt;br /&gt;
{{Note|This section still needs to be written (volunteers invivted to help!)-In the meantime, please refer to $FG_ROOT/Nasal/canvas/gui/dialogs/AircraftCenter.nas}}&lt;br /&gt;
&lt;br /&gt;
== Using Styling ==&lt;br /&gt;
{{Note|This section still needs to be written (volunteers invivted to help!)-In the meantime, please refer to $FG_ROOT/Nasal/canvas/gui/styles/DefaultStyle.nas}}&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_June_2014&amp;diff=73580</id>
		<title>FlightGear Newsletter June 2014</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_June_2014&amp;diff=73580"/>
		<updated>2014-06-30T20:43:21Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Canvas cleanup/restructuring - more to come...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Newsletter-header|June 2014}}&lt;br /&gt;
&amp;lt;div style=&amp;quot;border-bottom:3px double #BBB;&amp;quot;&amp;gt;&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; |&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|Development news}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|FlightGear 3.2 - Feature Freeze}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Canvas GUI: Layouting, Widgets and MessageBoxes}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Preview: Aircraft Center - get it on the fly}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Logo proposal}}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-header|Addons and mods}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Damage and disintegration}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Scenesetter}}&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|In the hangar}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Beechcraft Bonanza}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Saab JA-37 Viggen}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Updated P-51D now in git}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Balancing the Boeing 747-400}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Extra500 is updated to production status}}&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|Scenery corner}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|USA state capital buildings}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|LIPY, a scenery conversion from MSFS}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Reshaping Leipzig/Halle Airport}}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-header|Wiki updates}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|An updated Weather article}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|FlightGear 3.2 - Feature Freeze}}}|By [[User:t3r|TorstenD]]|Development news}}&lt;br /&gt;
On June 17, we entered our scheduled feature freeze state for the next release. Please use the remaining weeks to improve the existing features, harden and cleanup the code, edit the [[Next Changelog|ChangeLog]], improve the Manual, document the undocumented etc. etc. The release branches will be created on July 17th to have the release ready by Aug. 17th.&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|Canvas GUI: Layouting, Widgets and MessageBoxes}}}|By [[User:TheTom|TheTom]]}}&lt;br /&gt;
Thanks to Tom's and James' recent work on the upcoming [[Aircraft Center]] for downloading and switching between aircraft without having to exit FlightGear, beginning with FlightGear 3.2, FlightGear's [[Canvas]]-based GUI will contain support for so called [[Canvas MessageBox|Message Boxes]]:&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;br /&gt;
&lt;br /&gt;
[[File:Canvas GUI Demo Dialog.png|300px|thumb|Screen shot showing a simple [[Canvas GUI]] dialog with a handful of [[Canvas Widgets|Button Widgets]].]]&lt;br /&gt;
&lt;br /&gt;
For an example see [[Howto:Creating a Canvas GUI dialog file]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|Preview: Aircraft Center - get it on the fly}}}|By [[User:TheTom|TheTom]] and [[User:Zakalawe|Zakalawe]]}}&lt;br /&gt;
&lt;br /&gt;
[[File:Aircraft-center-prototype.png|270px|thumb|Canvas dialog showing the prototype for an [[Aircraft Center]] for directly installing/managing aircraft from within FlightGear, an upcoming feature scheduled for FlightGear 3.2, currently being developed by TheTom and Zakalawe]]&lt;br /&gt;
The &amp;quot;built-in&amp;quot; GUI/launcher is one of the longest-standing feature requests - but it's not just about the GUI (which is rather straightforward in comparison), but about the simulator never having  been developed with this requirement, i.e. run-time reinitialization, in mind - thus, things like &amp;quot;fgrun&amp;quot; (and a plethora of other external launchers) were developed, which acted as a front-end on top of FG, so that FG itself wouldn't need to be changed - i.e. kind of a &amp;quot;remote control&amp;quot; using command line arguments. So it's there for a reason - fgrun uses the FLTK GUI library, which while relatively simple, is much more powerful than our legacy GUI engine, PUI.&lt;br /&gt;
&lt;br /&gt;
Still, people have been asking for this for years, and it's thanks to pretty much a single person, Zakalawe, that switching aircraft is going to become possible pretty soon - he handled all the ugly work of cleaning up the simulator internals to make this happen - it's not exactly glamorous work, you gotta touch a ton of places, and you inevitably introduce a ton of regressions along the way.&lt;br /&gt;
&lt;br /&gt;
And yes, even the legacy FG GUI is entirely based on XML and configurable through just editiing XML files - but the collection of &amp;quot;widgets&amp;quot; (GUI controls like buttons, checkboxes, labels etc) is extremely small and very inflexible.&lt;br /&gt;
&lt;br /&gt;
This is something that is currently being addressed by TheTom and Zakalawe, who've both been working on a new Canvas GUI, and a new Canvas GUI dialog called &amp;quot;Aircraft Center&amp;quot;, which -while still experimental- is intended to eventually allow end-users to easily download/install aircraft right within the simulator, and also switch between aircraft at run-time without having to exit/restart the simulator.&lt;br /&gt;
&lt;br /&gt;
Thus, adopting Canvas is going to address a number of long-standing issues, but it's obviously a process that only just got started, and it will not happen overnight - 2-3 release cycles are not far-fetched, that's how long the whole migration could very well take, unless there are more people interested in helping.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Logo proposal|By [[User:Aepcam|Aepcam]]}}&lt;br /&gt;
This is a new logo badge concept proposal for FlightGear designed by Michat.&lt;br /&gt;
&lt;br /&gt;
[[File:Fglogo1.png]]&lt;br /&gt;
[[File:Fglogowiki.png]]&lt;br /&gt;
[[File:Fglogoforum.png]]&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|MapStructure stress-testing|By [[User:Hooray|Hooray]]}}&lt;br /&gt;
[[File:Map-canvas-mapstructure-performance.png|thumb|stress-testing [[MapStructure]] using the ufo @ KSFO circling at 2000 kts in a climb, see [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=21509&amp;amp;p=211611#p211611] ]]&lt;br /&gt;
&lt;br /&gt;
{{cquote&lt;br /&gt;
  |&amp;lt;nowiki&amp;gt;Now that Hyde has committed Philosopher's latest changes, I'd be interested in getting some more feedback on performance.&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Here, I am using the ufo @ksfo circling in a shuttle climb at &amp;gt;= 2000 kts GS and getting roughly 30 fps and 40-60 ms.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=211611#p211611&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: NavDisplay &amp;amp; MapStructure discussion (previously via PM)&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;Tue Jun 03&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Boeing 777 EFB prototype|By [[User:I-NEMO|I-NEMO]]}}&lt;br /&gt;
[[File:777-EFB-MAIN.png|thumb|777-200ER EFB [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23196]]]&lt;br /&gt;
[[File:777-EFB-AIRPORT-SEARCH.png|thumb|777-200 EFB AIRPORT SEARCH, see [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23196&amp;amp;p=211410#p211410]]]&lt;br /&gt;
&lt;br /&gt;
I-NEMO has started porting his 777/EFB prototype to [[Canvas]]&lt;br /&gt;
&lt;br /&gt;
As I wrote several times, I finally decided to put hands on the EFB (Reason: No one ever took care of developing an EFB for the 777; a 'working' EFB, though) with two (2) main goals in mind:&lt;br /&gt;
# do something to compensate for the lacking of an EFB inside the Boeing 777 Seattle.&lt;br /&gt;
# actually try (I repeat it: 'try') to learn some first essentials of nasal.&lt;br /&gt;
&lt;br /&gt;
This Seattle EFB is just a 'rude' one: with this term, I mean (as a word's pun) 'unpolite'. I'm perfectly aware that the coding is horrible, clumsy, repetitive, silly and very, very far from what it should be. My first aim was simply to have a somehow 'working' EFB inside the Seattle's Cockpit. I do not pretend that current 777's EFB.nas is a piece of nice software; but - to my initial purpose - it works. Not completely, not nicely, not properly...but it's a starting point. At least, it works...&lt;br /&gt;
Current development ('modernisation' phase) of the '''Boeing 777 Seattle's EFB''' is going on nicely; the code is shorter, more readable and cleaner.&lt;br /&gt;
I have not finished it, yet (I'd say that it's almost 50% done).&lt;br /&gt;
&lt;br /&gt;
At the moment I have a single Canvas group (i.e., ''EFB_group''), with 5 children: the text-matrix (16 left lines, 16 right lines), a Title line , an Helper line and the Display.&amp;lt;br/&amp;gt;&lt;br /&gt;
The ''Display'' element is then textured with all the various pages' textures, called by the page-handler (''see'' here below).&amp;lt;br/&amp;gt;&lt;br /&gt;
Currently, I'm using the .jpg textures which I had previously generated through Photoshop; in the future they might be replaced by .svg files, depending from actual interactive use of some graphical objects (a few EFB pages do need interaction with graphical parts). Besides - if i'm not wrong - I've read somewhere on the FGWiki that gradients are not handled by the SVG parser...and I do like to use some gradients effects (antialiasing and such) to achieve a sort of realism on the displays.&lt;br /&gt;
&lt;br /&gt;
that's the &amp;lt;u&amp;gt;current status&amp;lt;/u&amp;gt; of the new 777 ''Seattle'''s EFB: it's still far from being perfect, but - as a newbie - I'm quite satisfied for the moment: I need to finish the first version fairly soon, because my to-do-list is long (I have to re-model all the aircraft fuselage [original model has wrong measures, ''sigh!''], produce better gears and flight-control surfaces model &amp;amp;amp; animations in Blender, and then to produce a new Paint-Kit in Photoshop; then all 3D models optimizations...and so forth; of course, we also have to take care of CDU, which will interface with the EFB. So, the job is still very, very long...&lt;br /&gt;
&lt;br /&gt;
The current EFB code is heavily focused on rendering raster images, which can be retained obviously, but in FG, we have additional means to render airport information that is 100% in sync with the FG side of things (navdb). &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
For instance, we are going to &amp;quot;port&amp;quot; the airport-selection dialog to move rendering of airports/runways/taxiways/parking spots into dedicated MapStructure layers that can be properly styled and customized: [[Canvas_MapStructure#Porting_the_airports.xml_dialog]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Airport-selection-dialog.png|250px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As you can probably tell, these kinds of layers would be very useful for any  kind of EFB related application.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As long as the underlying design for a &amp;quot;page&amp;quot;-based MFD framework is sufficiently generic, we can easily replace/augment raster images and procedurally created charts - we could even use the built-in support for fetching via HTTP to download images on-line. In fact, we could then even extend Canvas to directly support rendering PDFs (OSG supports this out-of-the-box), this would make many steps unnecessary, because we could directly access [http://airnav.com http://airnav.com] without having to download/convert/ship any imagery. The code required to pull this off would be very compact in comparison.&lt;br /&gt;
&lt;br /&gt;
Learn more at [[Canvas EFB Framework]] or follow the [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23204 forum discussion]...&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Towards an Aircraft-agnostic MFD Framework|By [[User:Hooray|Hooray]]}}&lt;br /&gt;
Given the recent trend of having several MFD-related efforts without any kind of collaboration/code reuse going on here among our contributors (PFD, ND, Avidyne Entegra R9, EFB), I have started prototyping a generic MFD framework that is purely XML-based, inspired by discussions we've had over the last couple of weeks, and lessons learnt from the missions subsystem.&lt;br /&gt;
&lt;br /&gt;
It is intended to:&lt;br /&gt;
* support multiple independent instances&lt;br /&gt;
* be totally aircraft agnostic&lt;br /&gt;
* support a pure dialog-driven mode&lt;br /&gt;
* support skinning/theming&lt;br /&gt;
&lt;br /&gt;
This is supposed to support modeling complex avionics like a PFD, ND, EFB, CDU etc - and, eventually, also the Avidyne Entegra R9. It's currently just a prototype, but it gets away with very little code and we really only need a few more &amp;quot;skins&amp;quot; for common avionics. I am willing to extend this over time and help maintain it if people can agree to use something like this. It should be straightforward to allow such &amp;quot;MFDs&amp;quot; to be reloaded from disk at run-time, i.e. for more rapid prototyping.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is work in progress - the idea is to identify required building blocks to easily specify most MFD functionality in a generic fashion, without requiring a ton of custom Nasal code and without being specific to a single type of MFD. The whole concept is based on [[FlightGear_Missions_and_Adventures#XML_Extension_Framework]], i.e. providing a Nasal-space mechanism to expose and re-define building blocks to XML space.&lt;br /&gt;
&lt;br /&gt;
The Nasal/Canvas data structures will be transparently created and compiled for each MFD. Each MFD consists of an arbitrary number of buttons, modes and pages. Each MFD can be instantiated multiple times, and each MFD is designed to be aircraft/instrument agnostic, i.e. also works just in a conventional Canvas dialog. Buttons can trigger and switch between modes, and modes may have pages (conventionally implemented through a single SVG file). Each page consists of an arbitrary number of page elements, which can in turn be animated/updated via listeners and timers.  Should look at existing displays, especially the [[NavDisplay]] and the update() method in navdisplay.mfd, but the most complete test-case would probably be the [[Avidyne Entegra R9]] }}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Gpsmap196-canvas-panel-page.png|F-JJTH has updated the SVG file implementing the panel page for the [[Garmin GPSMap 196]].&lt;br /&gt;
Canvas-mfd-framework-prototyping.png|This is an adapted version of the [[Garmin GPSMap 196]] that is currently being developed by F-JJTH. Here, the whole instrument is entirely set up in XML space, including buttons/event handling, but also the embedded canvas region that serves as the 'screen'. The idea is to allow arbitrary MFDs to be specified in an aircraft-agnostic fashion, including displays like a PFD, [[NavDisplay]] or EFB. For details, please see [[Canvas Glass Cockpit Efforts]].&lt;br /&gt;
Canvas-mfd-framework-prototyping-with-mapstructure.png|This demonstrates how a purely XML-based MFD framework can instantiate dynamic [[MapStructure]] layers - none of this involves any [[Nasal]] coding now, it's just an XML file - to learn more, see [[Canvas Glass Cockpit Efforts]].&lt;br /&gt;
Canvas-mfd-framework-prototyping-with-mapstructure-with-kln89-skin.png|This screen shot shows the texture of the hard-coded KLN89 instrument used as a skin/theme for the MFD instrument, with a MapStructure-powered map shown.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Canvas System|By [[User:Hooray|Hooray]]}}&lt;br /&gt;
The upcoming FlightGear version (3.2) will contain a canvas-based map dialog, including a modular &amp;quot;plugin&amp;quot; system for creating custom map layers and charts with roughly ~50 lines of code, most of it boilerplate. This is entirely XML/Nasal based (scripted) - symbols can be pretty much anything, raster or vector images (png or svg), but even animated. Styling can be customized, too.&lt;br /&gt;
&lt;br /&gt;
For more info, I suggest to check out: [[MapStructure#Porting the map dialog]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
MapStructureDialog.png|You can basically create arbitrary layers, even for custom objects/positions&lt;br /&gt;
Map-canvas-chain-home-editor.png|The same method can be used for creating a &amp;quot;live&amp;quot; radar display&lt;br /&gt;
MapStructure-TFC-Troubleshooting.png|&lt;br /&gt;
Map-canvas-dialog-storms-overlay.png|But maps and layers can be fairly sophisticated, too - all 100% scripted&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As long as you use the MapStructure framework, all layers can be easily used in dialogs AND instruments&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Coding-wise, there isn't too much involved these days, all the details are covered in the MapStructure article.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Damage and disintegration|By [[User:Algernon|Algernon]]|FlightGear addons and mods}}&lt;br /&gt;
{{#ev:youtube|OpwNaoO3xMQ|200|right|Tomaskom's V-1 used in anger over London}}&lt;br /&gt;
{{#ev:youtube|H4XDuLo35ks|200|right|Victor V2.0 damage script causing a catastrophic failure and fire}}&lt;br /&gt;
{{#ev:youtube|uLojBI7ezdM|200|right|L-159 disintegration}}&lt;br /&gt;
The development team at FGUK have been experimenting with modelling aircraft damage in a number of different ways. First of all, Tomaskom has used the particle system carefully to produce visually impressive fireballs and smoke columns with very little FPS impact. First seen in his V-1, we hope to adapt this to simulate realistic fireballs for ground impacts (where appropriate). For the moment, it explodes with the full force of a V-1's explosive payload. On the right is a video excerpt from the #FlightNight which Tom organised to debut the V-1, where we all had '''way''' too much fun bombing London. As you can see, the smoke is visible from quite a long way away from the impact, and despite two fires burning with huge smoke columns, and over ten multiplayer aircraft within model range, the frame rates are still more than acceptable. StuartC has already integrated the explosion and fireball into several development aircraft, and we expect eventually to combine it with the disintegration code and make the size of the explosion dependent on fuel load etc.&lt;br /&gt;
&lt;br /&gt;
In a separate development, Algernon's work on the Victor V2.0(YASim) now includes modelled damage, a collection of Nasal scripts, some modified from existing FlightGear staples, which detects irregularities such as component failures, birdstrikes and combat weapon damage and adversely affects system performance and reliability accordingly. Unserviceability often follows, using the existing FlightGear failures system, and compatibility will be maintained as the failures system is improved. The damage script also calculates probabilites for chain reaction damage - for instance, an explosion or serious fire in one Victor engine will usually have an effect on the other. In extreme circumstances, an explosion will trigger further explosions and destroy the aircraft. The second video on the right shows a serious induced explosion on the Victor's number one engine at night. Some fine-tuning of the Rembrandt light has been carried out since this video was shot, so apologies for the visible cut-off.&lt;br /&gt;
&lt;br /&gt;
Finally, and most spectacularly, Tomaskom has demonstrated the disintegration capabilities of his L-159, which is under development. Hopefully, he will explain all here before publication date.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Scenesetter|By [[User:Algernon|Algernon]]}}&lt;br /&gt;
Scenesetter is a piece of code by Algernon, very early in development but already quite effective, which can effect changes to the time and weather from an AI scenario synchronously with other MP players. A crude proof of concept was used in the recent FGUK #FlightNight &amp;quot;British Weather&amp;quot;, where pilots visited different airfields with various unpleasant flying conditions. Scenesetter pushes METAR strings to the FlightGear weather system based on the location of an associated Navaid, establishing a circular zone of a specified radius around it in which METAR will be changed. Start time can be specified too, either by providing a local start time or a local time offset (useful for Multiplayer use where players will not all start the AI scenario at precisely the same time).&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Beechcraft Bonanza|By [[User:Flyingfisch|Flyingfisch]]|In the hangar}}&lt;br /&gt;
Flyingfisch is building the Beechcraft A35 Bonanza for Flightgear. Some pictures:&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Beech_bonanza_with_panel_lights_on.png|Panel lighting&lt;br /&gt;
Bonanza rbf.png|Remember to do your pre-flight check before startup!&lt;br /&gt;
Bonanza at sunrise.png|The Beech Bonanza at Kent State University (1G3) just before sunrise&lt;br /&gt;
Bonanza interior at sunrise.png|The interior of the Bonanza at sunrise.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Saab JA-37 Viggen|By [[User:Necolatis|Necolatis]]}}&lt;br /&gt;
The Swedish fighter jet [[Saab JA-37 Viggen]] has been updated, since it was included in FlightGear 3.0. More instruments, additional liveries, aerodynamic response to payload and tooltips on instruments. Option for automatic reverse thrust at touchdown, selection of HUD brightness, disabling of structural damage. HUD can now switch to imperial units and show MP and AI aircraft and closest airport. The aircraft now also has multiplayer sounds and better cockpit view helps seeing the landing strip. Support for FG 2.8 by deleting a small section in an xml file. Also worth mentioning is countless bug-fixes and improvements, e.g. better handling at high altitudes and a bug fix in the lift force formula.&lt;br /&gt;
&lt;br /&gt;
[[File:Saab JA-37 Viggen Blue Peter Livery.png|Blå Petter Livery for JA-37]]&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Updated P-51D now in git|By [[User:hvengel|hvengel]]}}&lt;br /&gt;
The new 3D exterior model for the [[North American P-51 Mustang|North American P-51D Mustang]] is now in git and under active development. It is currently in gray primer waiting for the UV map to be finalized. It is now fully integrated into the existing FDM.  Extensive new animation work has been done including animated trim tabs and a fully functional canopy. Here are some screen shots taken in sim for your enjoyment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed heights=250px&amp;gt;&lt;br /&gt;
P-51D testing it's guns before a flight..jpg|P-51D testing it's guns before a flight.&lt;br /&gt;
P-51D trim tab animation..jpg|P-51D trim tab animation.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Balancing the Boeing 747-400|By [[User:Gijs|Gijs]]}}&lt;br /&gt;
After he started developing the [[Boeing 747-400]] as a hobby project six years ago, Gijs finally managed to get the weight and balancing right. The center of gravity is now within 0.05% MAC (40 cm) of the published values.&lt;br /&gt;
&lt;br /&gt;
Make sure to use the new Fuel and Payload dialog to fill your fuel tanks. There is a slider and button that will nicely distribute a specified amount of fuel, while making sure the CoG stays within the operational limits. Before takeoff, check the Takeoff Reference page on the CDU to find the required stab trim units (your current setting is displayed to the left of the throttle quadrant). When you set your trim properly, you can almost relax your yoke to the neutral position after rotate. There's still some FDM work left to fine-tune this.&lt;br /&gt;
&lt;br /&gt;
The updated 747-400 is already available through Git and will be on the download page when FlightGear 3.2 is released.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Extra500 is updated to production status|By [[User:Evandenberg|Evandenberg]]}}&lt;br /&gt;
The [[Extra EA-500]] is updated and has reached &amp;quot;production status&amp;quot;! Just a short list of changes for release 1.1.0:&lt;br /&gt;
* Engine+fuel: realistic flame-out, fuel flow to collector compartment, anti ice influence on TOT, improved oil press and temp model&amp;lt;br/&amp;gt;&lt;br /&gt;
* Aerodynamics: flap performance, elevator-30deg-flaps authority improvement&amp;lt;br/&amp;gt;&lt;br /&gt;
* User interface: interactive checklists&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sounds: corrected sounds for test, CWS and AP disc&amp;lt;br/&amp;gt;&lt;br /&gt;
* Model: added interior, yokes&amp;lt;br/&amp;gt;&lt;br /&gt;
* Avionics: IFD moving map, automatic NAV tuning, automatic NAV switching, magnetic variation fixes&amp;lt;br/&amp;gt;&lt;br /&gt;
* Autopilot: added OBS and fly vectors mode, significant improvement of coupled ILS performance&lt;br /&gt;
A more extensive list can be found in the &amp;quot;version&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
This version does perform a bit better on my computer, but this has to do with improvements to FGFS, not of the aircraft model. So if your computer was struggling with the initial version, we recommend to use current FlightGear git/nightly builds or wait until 3.2 comes out!&lt;br /&gt;
&lt;br /&gt;
Please checkout the [[Extra EA-500|Extra500 wiki]] for download instructions and lots of more info.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed heights=250px&amp;gt;&lt;br /&gt;
File:Extra500 flightgear1.png|Extra500 flying in clouds&lt;br /&gt;
Extra500canvas.png|Work has begun to analyze, refactor and generalize useful parts of the [[Avidyne Entegra R9]] to help reuse some code in similar MFD efforts, like the [[Garmin GPSMap 196]] or [[Canvas EFB Framework]]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|USA state capital buildings|By [[User:Jonbourg|Jonbourg]]|Scenery corner}}&lt;br /&gt;
There is a project to add all the USA state capital buildings into FG.  It is discussed in [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22715&amp;amp;sid=ea847909bde2e1f8ffe5b94bcc673f4f this scenery forum thread]. There is also a wiki page: [[State Capitol Buildings in the United States]].  So far, Idaho, Louisiana &amp;amp; Nebraska have been completed. Hawaii and New York are currently in progress.  Please feel free to join in with any other state that has not been done yet.  Just let us know through the forum and we will add it to the in progress list.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|LIPY, a scenery conversion from MSFS|By [[User:bigstones|bigstones]]}}&lt;br /&gt;
This month saw the [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22623 second &amp;quot;preview&amp;quot; release] of the conversion of a scenery for MS Flight Simulator, [[Falconara Airport]] (ICAO code: LIPY), a small Italian international airport halfway down the Adriatic coast. The original author granted the permission to the conversion and even allowed for it to be included in the FlightGear official [[World Scenery]], at least the GPL compatible parts. This is not a huge limitation though, because most of the material was created from scratch, included pictures taken on purpose at the real airport, with the authorities' collaboration. Copyrighted aerial imagery only include the (unsuable) photoreal ground and some roofs.&lt;br /&gt;
&lt;br /&gt;
[[File:LIPY structures landscape.jpg|650px|right]]&lt;br /&gt;
The conversion was made with [[ModelConverterX]], which makes the job partially easier than by [[Howto:Convert objects from X-Plane|the Blender method]], yet it's still needing fixes because of some misunderstandings with the coordinates axes. The author of the tool, though, seems not very concerned and anyway, it's so rare to have a freeware scenery author allow conversions, that the usefulness of this tool would be greatly reduced anyhow, especially if you plan to upload the models to the [[FlightGear Scenery Database]].&lt;br /&gt;
&lt;br /&gt;
The conversion itself, moreover, sure is not the matter of a button press. MSFS scenery are often packed and &amp;quot;compiled&amp;quot; in *.BGL files such that independent, far objects with the same materials and same LOD level (Level Of Detail) are bound together. This is clearly against FG's way, in which each new scenery generation could change the relative heights, and however MSFS airports are flat, while in FG they're all sloped. A similar thing happens with the texture maps. This basically means that you'll have to join all these objects and split them again based on the model they belong to (e.g. tower, terminal, hangars...)&lt;br /&gt;
&lt;br /&gt;
Another issue with textures is that in FG it's good practice - recommended if not mandatory - to have 2 separate texture maps for the same object, if some parts are translucent. This means that without rebuilding all the texture maps [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22707 you'll likely get artifacts]. Then, you'd have to add the Rembrandt lights if you want, and also the lightmaps (MSFS uses night textures, but Gimp can easily convert them). This whole experience can be summed up in the following quote:&lt;br /&gt;
&lt;br /&gt;
{{cquote|I really wanted to have this scenery in FG because it's my home base, and seeing it ready and so well done just made me want it. However, even if still easier than making it from scratch (even if reusing the textures), I'd have to think well if I had to do this again.|bigstones, maintainer of the conversion}}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Reshaping Leipzig/Halle Airport|By [[User:August|August]]}}&lt;br /&gt;
[[File:2014 new-layout-EDDP 05.jpg|650px|right]]&lt;br /&gt;
In FlightGear Germany's second largest cargo airport [[EDDP]] is well known as a detailed model accessible for everybody via [[TerraSync]]. Until 2013 it was famous for its regular ATC-events. It has been updated several times, at least 2012 by users D-STHO and August. When FlightGear 3.0 was published the airport layout changed from the old 810-standard to the new 850-standard. But the update (based on a taxiway layout modelled for X-Plane) turned out to be very imperfect. Many aprons and taxiways did not exist, dimensions did not appear to be correct and many new facilities which had been added at the real-world airport had not been taken into account. So maintainer August decided to redesign the whole airport from the scratch using [[WorldEditor]]. &lt;br /&gt;
Pilots and developers are now invited to test the new airport model which includes further improvements like predefined STAR-, -SID and Transition procedures and hundreds of replaced Static- and Shared Models. The project will be published on TerraSync as soon as all defects are discovered remedied.&lt;br /&gt;
&lt;br /&gt;
Developer Version:&lt;br /&gt;
   '''git clone''' [https://gitorious.org/eddp-custom-scenery/eddp-custom-scenery/ https://gitorious.org/eddp-custom-scenery/eddp-custom-scenery/]&lt;br /&gt;
&lt;br /&gt;
Feedback is welcome at [[User talk:August|August's wiki page]].&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
2014 new-layout-EDDP 04.jpg|Taxiway T - new ground textures&lt;br /&gt;
2014 new-layout-EDDP 01.jpg|Runway 26L with DHL-area&lt;br /&gt;
2014 new-layout-EDDP 02.jpg|Apron 4&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|An updated Weather article|By [[User:bigstones|bigstones]]|Wiki updates}}&lt;br /&gt;
The [[Weather]] wiki article went through a wide extension. Although Advanced Weather was released quite a while ago, its usage has never been explained in the wiki, and some thorough instructions were available only in a readme in the &amp;quot;docs&amp;quot; folder of the base package which is not commonly explored by users, while the wiki article [[Advanced weather]] is more about the project than the usage.&lt;br /&gt;
&lt;br /&gt;
AW's advanced configuration is known to be not easy. So, if you always only used the weather selection menu and want to know more, or want to understand what the options actually do and how you can combine them, the [[Weather]] article has now been updated with some hints and basic notions extracted from experience and the original documentation, and quality checked by the author of the AW weather engine.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Translators required|}}&lt;br /&gt;
{|&lt;br /&gt;
|[[File:en.gif]]&lt;br /&gt;
|The FlightGear Wiki still needs help for translating it into various languages. If you are interested in making the FlightGear Wiki multi-language then start at [[Help:Translate]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:de.gif]]&lt;br /&gt;
|Das FlightGear Wiki benötigt immer noch Hilfe bei der Übersetzung in verschiedene Sprachen. Wenn Du Interesse daran hast, das FlightGear Wiki Mehrsprachig zu machen, dann fang doch mit [[:de:Help:Übersetzen|Help:Übersetzen]] an.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:nl.gif]]&lt;br /&gt;
|De FlightGear Wiki kan nog steed hulp gebruiken bij het vertalen van artikelen. Als je interesse hebt om de wiki meertalig te maken, raden we je aan om een kijkje te nemen bij [[:nl:Help:Vertalen|Help:Vertalen]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:es.gif]]&lt;br /&gt;
|La FlightGear wiki todavía necesita ayuda para traducirla a varios lenguajes. Si estás interesado en hacer la FlightGear wiki multilingüe, entonces comienza en [[:es:Help:Traducir|Help:Traducir]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Call for volunteers||And finally...}}&lt;br /&gt;
* The [[TerraGear]] maintainers are looking for volunteers to help with development on the next world scenery project.  If you've ever wondered how a full 3D model of earth can be generated from raw data, now is your chance.  See the plan at [[TerraGear roadmap]].&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2014 06]]&lt;br /&gt;
[[Category:Changes after 3.00]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Changelog_3.2&amp;diff=73553</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=73553"/>
		<updated>2014-06-30T12:00:42Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Nasal core changes&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;
=== Breaking Changes ===&lt;br /&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;
* improved projection handling for the integrated [[Map]] dialog, implemented by Gijs[https://gitorious.org/fg/flightgear/commit/3f433e2c35ef533a847138e6ae10a5cb398323d7#comment_107170]&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;
'''Atmospheric Light Scattering'''&lt;br /&gt;
&lt;br /&gt;
Atmospheric Light Scattering (ALS) is one of FGs three rendering frameworks, with the aim of providing an integrated simulation of the interaction between weather, light and the environment.&lt;br /&gt;
&lt;br /&gt;
Additions to ALS in version 3.2 include:&lt;br /&gt;
&lt;br /&gt;
* an experimental framework to render cloud shadows on the ground (requires Advanced Weather)&lt;br /&gt;
* a substantial extension of cloud layer visibility using impostor techniques to 150 km&lt;br /&gt;
* a new agriculture effect allowing to render fields without tiling artifacts&lt;br /&gt;
* a new forest effect to simulate managed forest, varying tree size by patch&lt;br /&gt;
* sparkle and fog effect on runway lights&lt;br /&gt;
* much improved visual appearance of rock faces&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Environment Rendering'''&lt;br /&gt;
&lt;br /&gt;
* EarthView, a simple orbital rendering engine based on projecting a textured sphere into the scene. By default, EarthView uses low resolution textures, however using hires textures e.g. from the NASA [http://visibleearth.nasa.gov/ Visible Earth] project very realistic results from altitudes above 100 km can be achieved.&lt;br /&gt;
&lt;br /&gt;
* new deciduous and needle tree textures with much improved visuals&lt;br /&gt;
&lt;br /&gt;
* new regional texture definitions for Ireland, Alaska/Northwest territories and US Southwest &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. Also, maps can now be mostly customized, including custom styling (colors, fonts, symbols etc).&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;
&amp;lt;!-- code freeze ...&lt;br /&gt;
* Hooray is working on adding shader support to Canvas {{Progressbar|30}}&lt;br /&gt;
--&amp;gt;&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;
* Canvas Layout Engine&lt;br /&gt;
* Canvas-based dialog for downloading aircraft [[Aircraft Center]]&lt;br /&gt;
[[File:Aircraft-center-prototype.png|400px|thumb|Canvas dialog showing the prototype for an [[Aircraft Center]] for directly installing/managing aircraft from within FlightGear, an upcoming feature scheduled for FlightGear 3.2, currently being developed by TheTom and Zakalawe]]&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;
* Language enhancements&lt;br /&gt;
** Bitwise operators (|, &amp;amp;, ^, ~, |=, &amp;amp;=, ^=)&lt;br /&gt;
** Support for octal, decimal and hexadecimal numbers in literals as well as in strings&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_June_2014&amp;diff=73552</id>
		<title>FlightGear Newsletter June 2014</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_June_2014&amp;diff=73552"/>
		<updated>2014-06-30T07:40:24Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Newsletter-header|June 2014}}&lt;br /&gt;
&amp;lt;div style=&amp;quot;border-bottom:3px double #BBB;&amp;quot;&amp;gt;&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; |&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|Development news}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|FlightGear 3.2 - Feature Freeze}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Canvas GUI: MessageBox Support}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Logo proposal}}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-header|Addons and mods}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Damage and disintegration}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Scenesetter}}&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|In the hangar}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Beechcraft Bonanza}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Saab JA-37 Viggen}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Updated P-51D now in git}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Balancing the Boeing 747-400}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Extra500 is updated to production status}}&lt;br /&gt;
| valign=&amp;quot;top&amp;quot; width=&amp;quot;33%&amp;quot; |&lt;br /&gt;
{{Newsletter-cover-header|Scenery corner}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|USA state capital buildings}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|LIPY, a scenery conversion from MSFS}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|Reshaping Leipzig/Halle Airport}}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-header|Wiki updates}}&amp;lt;br/&amp;gt;&lt;br /&gt;
{{Newsletter-cover-item|An updated Weather article}}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|FlightGear 3.2 - Feature Freeze}}}|By [[User:t3r|TorstenD]]|Development news}}&lt;br /&gt;
On June 17, we entered our scheduled feature freeze state for the next release. Please use the remaining weeks to improve the existing features, harden and cleanup the code, edit the [[Next Changelog|ChangeLog]], improve the Manual, document the undocumented etc. etc. The release branches will be created on July 17th to have the release ready by Aug. 17th.&lt;br /&gt;
&lt;br /&gt;
{{Template:Newsletter-article-start|{{{1|Canvas GUI: MessageBox Support}}}|By [[User:TheTom|TheTom]]}}&lt;br /&gt;
Thanks to Tom's and James' recent work on the upcoming [[Aircraft Center]] for downloading and switching between aircraft without having to exit FlightGear, beginning with FlightGear 3.2, FlightGear's [[Canvas]]-based GUI will contain support for so called [[Canvas MessageBox|Message Boxes]]:&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;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Logo proposal|By [[User:Aepcam|Aepcam]]}}&lt;br /&gt;
This is a new logo badge concept proposal for FlightGear designed by Michat.&lt;br /&gt;
&lt;br /&gt;
[[File:Fglogo1.png]]&lt;br /&gt;
[[File:Fglogowiki.png]]&lt;br /&gt;
[[File:Fglogoforum.png]]&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|MapStructure stress-testing|By [[User:Hooray|Hooray]]}}&lt;br /&gt;
[[File:Map-canvas-mapstructure-performance.png|thumb|stress-testing [[MapStructure]] using the ufo @ KSFO circling at 2000 kts in a climb, see [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=21509&amp;amp;p=211611#p211611] ]]&lt;br /&gt;
&lt;br /&gt;
{{cquote&lt;br /&gt;
  |&amp;lt;nowiki&amp;gt;Now that Hyde has committed Philosopher's latest changes, I'd be interested in getting some more feedback on performance.&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Here, I am using the ufo @ksfo circling in a shuttle climb at &amp;gt;= 2000 kts GS and getting roughly 30 fps and 40-60 ms.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=211611#p211611&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: NavDisplay &amp;amp; MapStructure discussion (previously via PM)&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;Tue Jun 03&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Creating Canvas GUI Dialogs ==&lt;br /&gt;
'''Targeted FlightGear versions: &amp;gt;= 3.20'''&lt;br /&gt;
[[File:Canvas GUI Demo Dialog.png|400px|thumb|Screen shot showing a simple [[Canvas GUI]] dialog with a handful of [[Canvas Widgets|Button Widgets]].]]&lt;br /&gt;
== Editing Translations/en/menu.xml ==&lt;br /&gt;
Navigate to the sub-menu where you'd like to add your new dialog, e.g. &amp;quot;Equipment&amp;quot; in this case, and then add a key:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;equipment&amp;gt;Equipment&amp;lt;/equipment&amp;gt;&lt;br /&gt;
&amp;lt;canvas-demo-dialog&amp;gt;Canvas Demo Dialog&amp;lt;/canvas-demo-dialog&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Editing gui/menubar.xml ==&lt;br /&gt;
Next, open $FG_ROOT/gui/menubar.xml and navigate to the corresponding sub-menu and add a new item/binding to load your dialog:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;item&amp;gt;&lt;br /&gt;
&amp;lt;name&amp;gt;canvas-demo-dialog&amp;lt;/name&amp;gt;&lt;br /&gt;
&amp;lt;binding&amp;gt;&lt;br /&gt;
&amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
canvas.loadDialog(&amp;quot;CanvasDemo&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/binding&amp;gt;&lt;br /&gt;
&amp;lt;/item&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Creating the actual dialog file ==&lt;br /&gt;
{{Note|These dialog files can be edited at run-time and simply closed/re-opened, because the Canvas system will reload them from disk whenever the menu binding is triggered. So this is very convenient for quickly developing and testing your dialogs.}}&lt;br /&gt;
Next, open/create $FG_ROOT/Nasal/canvas/gui/dialogs/CanvasDemo.nas and add some boilerplate code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var DemoDialog = {&lt;br /&gt;
  new: func&lt;br /&gt;
  {&lt;br /&gt;
    var m = {&lt;br /&gt;
      parents: [DemoDialog],&lt;br /&gt;
      _dlg: canvas.Window.new([400,300], &amp;quot;dialog&amp;quot;)&lt;br /&gt;
                         .set(&amp;quot;title&amp;quot;, &amp;quot;Demo Dialog&amp;quot;)&lt;br /&gt;
                         .set(&amp;quot;resize&amp;quot;, 1),&lt;br /&gt;
      _active_button: nil&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
    m._dlg.getCanvas(1)&lt;br /&gt;
          .set(&amp;quot;background&amp;quot;, canvas.style.getColor(&amp;quot;bg_color&amp;quot;));&lt;br /&gt;
    m._root = m._dlg.getCanvas().createGroup();&lt;br /&gt;
&lt;br /&gt;
    var vbox = VBoxLayout.new();&lt;br /&gt;
    m._dlg.setLayout(vbox);&lt;br /&gt;
&lt;br /&gt;
    return m;&lt;br /&gt;
  },&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var demo = DemoDialog.new();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Finally, start FlightGear and open your new dialog&lt;br /&gt;
&lt;br /&gt;
== Adding Widgets ==&lt;br /&gt;
== Using Layouts ==&lt;br /&gt;
&lt;br /&gt;
== Using Styling ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 777 EFB Prototype by I-NEMO ===&lt;br /&gt;
[[File:777-EFB-MAIN.png|thumb|777-200ER EFB [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23196]]]&lt;br /&gt;
[[File:777-EFB-AIRPORT-SEARCH.png|thumb|777-200 EFB AIRPORT SEARCH, see [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=23196&amp;amp;p=211410#p211410]]]&lt;br /&gt;
&lt;br /&gt;
I-NEMO has started porting his 777/EFB prototype to [[Canvas]]&lt;br /&gt;
&lt;br /&gt;
{{cquote&lt;br /&gt;
  |&amp;lt;nowiki&amp;gt;As I wrote several times, I finally decided to put hands on the EFB (Reason: No one ever took care of developing an EFB for the 777; a 'working' EFB, though) with two (2) main goals in mind:&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
1) to do something to compensate for the lacking of an EFB inside the Seattle.&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
2) to actually try (I repeat it: 'try') to learn some first essentials of nasal.&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=211550#p211550&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB status &amp;amp; plans  ?&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;I-NEMO&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Mon Jun 02&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{cquote&lt;br /&gt;
  |&amp;lt;nowiki&amp;gt; this Seattle EFB is just a 'rude' one: with this term, I mean (as a word's pun) 'unpolite'. I'm perfectly aware that the coding is horrible, clumsy, repetitive, silly and very, very far from what it should be. &amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
My first aim was simply to have a somehow 'working' EFB inside the Seattle's Cockpit.&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
My second aim was to use EFB.nas as a starting playground for a newbie as I am on 'nasal'. &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=211550#p211550&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB status &amp;amp; plans  ?&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;I-NEMO&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Mon Jun 02&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{cquote&lt;br /&gt;
  |&amp;lt;nowiki&amp;gt;I do not pretend that current 777's EFB.nas is a piece of nice software; but - to my initial purpose - it works. Not completely, not nicely, not properly...but it's a starting point. At least, it works...&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=211550#p211550&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB status &amp;amp; plans  ?&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;I-NEMO&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Mon Jun 02&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |Current development ('modernisation' phase) of the '''Boeing 777 Seattle's EFB''' is going on nicely; the code is shorter, more readable and cleaner.&amp;lt;br/&amp;gt;&lt;br /&gt;
I have not finished it, yet (I'd say that it's almost 50% done).&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=213104#p213104&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB: initial feedback&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;I-NEMO&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sat Jun 21&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |At the moment I have a single Canvas group (i.e., ''EFB_group''), with 5 children: the text-matrix (16 left lines, 16 right lines), a Title line , an Helper line and the Display.&amp;lt;br/&amp;gt;&lt;br /&gt;
The ''Display'' element is then textured with all the various pages' textures, called by the page-handler (''see'' here below).&amp;lt;br/&amp;gt;&lt;br /&gt;
Currently, I'm using the .jpg textures which I had previously generated through Photoshop; in the future they might be replaced by .svg files, depending from actual interactive use of some graphical objects (a few EFB pages do need interaction with graphical parts). Besides - if i'm not wrong - I've read somewhere on the FGWiki that gradients are not handled by the SVG parser...and I do like to use some gradients effects (antialiasing and such) to achieve a sort of realism on the displays.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=213104#p213104&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB: initial feedback&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;I-NEMO&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sat Jun 21&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |that's the &amp;lt;u&amp;gt;current status&amp;lt;/u&amp;gt; of the new 777 ''Seattle'''s EFB: it's still far from being perfect, but - as a newbie - I'm quite satisfied for the moment: I need to finish the first version fairly soon, because my to-do-list is long (I have to re-model all the aircraft fuselage [original model has wrong measures, ''sigh!''], produce better gears and flight-control surfaces model &amp;amp;amp; animations in Blender, and then to produce a new Paint-Kit in Photoshop; then all 3D models optimizations...and so forth; of course, we also have to take care of CDU, which will interface with the EFB. So, the job is still very, very long...&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=213104#p213104&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB: initial feedback&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |author=&amp;lt;nowiki&amp;gt;I-NEMO&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
     |date=&amp;lt;nowiki&amp;gt;Sat Jun 21&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |The current EFB code is heavily focused on rendering raster images, which can be retained obviously, but in FG, we have additional means to render airport information that is 100% in sync with the FG side of things (navdb). &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
For instance, we are going to &amp;quot;port&amp;quot; the airport-selection dialog to move rendering of airports/runways/taxiways/parking spots into dedicated MapStructure layers that can be properly styled and customized: [[Canvas_MapStructure#Porting_the_airports.xml_dialog]] &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Airport-selection-dialog.png|250px]]&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As you can probably tell, these kinds of layers would be very useful for any  kind of EFB related application.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
As long as the underlying design for a &amp;quot;page&amp;quot;-based MFD framework is sufficiently generic, we can easily replace/augment raster images and procedurally created charts - we could even use the built-in support for fetching via HTTP to download images on-line. In fact, we could then even extend Canvas to directly support rendering PDFs (OSG supports this out-of-the-box), this would make many steps unnecessary, because we could directly access [http://airnav.com http://airnav.com] without having to download/convert/ship any imagery. The code required to pull this off would be very compact in comparison.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=213084#p213084&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: 777 EFB: initial feedback&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;Sat Jun 21&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Learn more at [[Canvas EFB Framework]] ...&lt;br /&gt;
&lt;br /&gt;
=== Canvas Garmin GPSMap196 Updates ===&lt;br /&gt;
&lt;br /&gt;
[[File:Gpsmap196-canvas-panel-page.png|thumb|F-JJTH has updated the SVG file implementing the panel page for the [[Garmin GPSMap 196]]]]&lt;br /&gt;
&lt;br /&gt;
=== Towards an Aircraft-agnostic MFD Framework ===&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-mfd-framework-prototyping.png|thumb|This is an adapted version of the [[Garmin GPSMap 196]] that is currently being developed by F-JJTH. Here, the whole instrument is entirely set up in XML space, including buttons/event handling, but also the embedded canvas region that serves as the 'screen'. The idea is to allow arbitrary MFDs to be specified in an aircraft-agnostic fashion, including displays like a PFD, [[NavDisplay]] or EFB. For details, please see [[Canvas Glass Cockpit Efforts]].]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-mfd-framework-prototyping-with-mapstructure.png|400px|thumb|This demonstrates how a purely XML-based MFD framework can instantiate dynamic [[MapStructure]] layers - none of this involves any [[Nasal]] coding now, it's just an XML file - to learn more, see [[Canvas Glass Cockpit Efforts]].]]&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas-mfd-framework-prototyping-with-mapstructure-with-kln89-skin.png|400px|thumb|This screen shot shows the texture of the hard-coded KLN89 instrument used as a skin/theme for the MFD instrument, with a MapStructure-powered map shown.]]&lt;br /&gt;
&lt;br /&gt;
=== Canvas System ===&lt;br /&gt;
{{FGCquote&lt;br /&gt;
  |The upcoming FlightGear version (3.2) will contain a canvas-based map dialog, including a modular &amp;quot;plugin&amp;quot; system for creating custom map layers and charts with roughly ~50 lines of code, most of it boilerplate. &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;This is entirely XML/Nasal based (scripted) - symbols can be pretty much anything, raster or vector images (png or svg), but even animated. Styling can be customized, too.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;For more info, I suggest to check out:&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;[[MapStructure#Porting_the_map_dialog|http://wiki.flightgear.org/MapStructure ... map_dialog]]&amp;lt;br&amp;gt;[[File:MapStructureDialog.png|250px]] &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;You can basically create arbitrary layers, even for custom objects/positions:&amp;lt;br&amp;gt;[[File:Map-canvas-chain-home-editor.png|250px]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;The same method can be used for creating a &amp;quot;live&amp;quot; radar display:&amp;lt;br&amp;gt;[[Canvas_Radar|http://wiki.flightgear.org/Canvas_Radar]]&amp;lt;br&amp;gt;[[File:MapStructure-TFC-Troubleshooting.png|250px]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;But maps and layers can be fairly sophisticated, too - all 100% scripted:&amp;lt;br&amp;gt;[[FlightGear_Newsletter_May_2014#A_Canvas-based_Map_dialog|http://wiki.flightgear.org/FlightGear_N ... Map_dialog]]&amp;lt;br&amp;gt;[[File:Map-canvas-dialog-storms-overlay.png|250px]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;As long as you use the MapStructure framework, all layers can be easily used in dialogs AND instruments&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;Coding-wise, there isn't too much involved these days, all the details are covered in the MapStructure article.&lt;br /&gt;
  |{{cite web |url=http://forum.flightgear.org/viewtopic.php?p=212558#p212558&lt;br /&gt;
     |title=&amp;lt;nowiki&amp;gt;Re: Get objects to show up on Map/Radar&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;Sat Jun 14&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   }}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[File:Aircraft-center-prototype.png|500px|thumb|Canvas dialog showing the prototype for an [[Aircraft Center]] for directly installing/managing aircraft from within FlightGear, an upcoming feature scheduled for FlightGear 3.2, currently being developed by TheTom and Zakalawe]]&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Damage and disintegration|By [[User:Algernon|Algernon]]|FlightGear addons and mods}}&lt;br /&gt;
{{#ev:youtube|OpwNaoO3xMQ|200|right|Tomaskom's V-1 used in anger over London}}&lt;br /&gt;
{{#ev:youtube|H4XDuLo35ks|200|right|Victor V2.0 damage script causing a catastrophic failure and fire}}&lt;br /&gt;
{{#ev:youtube|uLojBI7ezdM|200|right|L-159 disintegration}}&lt;br /&gt;
The development team at FGUK have been experimenting with modelling aircraft damage in a number of different ways. First of all, Tomaskom has used the particle system carefully to produce visually impressive fireballs and smoke columns with very little FPS impact. First seen in his V-1, we hope to adapt this to simulate realistic fireballs for ground impacts (where appropriate). For the moment, it explodes with the full force of a V-1's explosive payload. On the right is a video excerpt from the #FlightNight which Tom organised to debut the V-1, where we all had '''way''' too much fun bombing London. As you can see, the smoke is visible from quite a long way away from the impact, and despite two fires burning with huge smoke columns, and over ten multiplayer aircraft within model range, the frame rates are still more than acceptable. StuartC has already integrated the explosion and fireball into several development aircraft, and we expect eventually to combine it with the disintegration code and make the size of the explosion dependent on fuel load etc.&lt;br /&gt;
&lt;br /&gt;
In a separate development, Algernon's work on the Victor V2.0(YASim) now includes modelled damage, a collection of Nasal scripts, some modified from existing FlightGear staples, which detects irregularities such as component failures, birdstrikes and combat weapon damage and adversely affects system performance and reliability accordingly. Unserviceability often follows, using the existing FlightGear failures system, and compatibility will be maintained as the failures system is improved. The damage script also calculates probabilites for chain reaction damage - for instance, an explosion or serious fire in one Victor engine will usually have an effect on the other. In extreme circumstances, an explosion will trigger further explosions and destroy the aircraft. The second video on the right shows a serious induced explosion on the Victor's number one engine at night. Some fine-tuning of the Rembrandt light has been carried out since this video was shot, so apologies for the visible cut-off.&lt;br /&gt;
&lt;br /&gt;
Finally, and most spectacularly, Tomaskom has demonstrated the disintegration capabilities of his L-159, which is under development. Hopefully, he will explain all here before publication date.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Scenesetter|By [[User:Algernon|Algernon]]}}&lt;br /&gt;
Scenesetter is a piece of code by Algernon, very early in development but already quite effective, which can effect changes to the time and weather from an AI scenario synchronously with other MP players. A crude proof of concept was used in the recent FGUK #FlightNight &amp;quot;British Weather&amp;quot;, where pilots visited different airfields with various unpleasant flying conditions. Scenesetter pushes METAR strings to the FlightGear weather system based on the location of an associated Navaid, establishing a circular zone of a specified radius around it in which METAR will be changed. Start time can be specified too, either by providing a local start time or a local time offset (useful for Multiplayer use where players will not all start the AI scenario at precisely the same time).&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Beechcraft Bonanza|By [[User:Flyingfisch|Flyingfisch]]|In the hangar}}&lt;br /&gt;
Flyingfisch is building the Beechcraft A35 Bonanza for Flightgear. Some pictures:&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
Beech_bonanza_with_panel_lights_on.png|Panel lighting&lt;br /&gt;
Bonanza rbf.png|Remember to do your pre-flight check before startup!&lt;br /&gt;
Bonanza at sunrise.png|The Beech Bonanza at Kent State University (1G3) just before sunrise&lt;br /&gt;
Bonanza interior at sunrise.png|The interior of the Bonanza at sunrise.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Saab JA-37 Viggen|By [[User:Necolatis|Necolatis]]}}&lt;br /&gt;
The Swedish fighter jet [[Saab JA-37 Viggen]] has been updated, since it was included in FlightGear 3.0. More instruments, additional liveries, aerodynamic response to payload and tooltips on instruments. Option for automatic reverse thrust at touchdown, selection of HUD brightness, disabling of structural damage. HUD can now switch to imperial units and show MP and AI aircraft and closest airport. The aircraft now also has multiplayer sounds and better cockpit view helps seeing the landing strip. Support for FG 2.8 by deleting a small section in an xml file. Also worth mentioning is countless bug-fixes and improvements, e.g. better handling at high altitudes and a bug fix in the lift force formula.&lt;br /&gt;
&lt;br /&gt;
[[File:Saab JA-37 Viggen Blue Peter Livery.png|Blå Petter Livery for JA-37]]&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Updated P-51D now in git|By [[User:hvengel|hvengel]]}}&lt;br /&gt;
The new 3D exterior model for the [[North American P-51 Mustang|North American P-51D Mustang]] is now in git and under active development. It is currently in gray primer waiting for the UV map to be finalized. It is now fully integrated into the existing FDM.  Extensive new animation work has been done including animated trim tabs and a fully functional canopy. Here are some screen shots taken in sim for your enjoyment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed heights=250px&amp;gt;&lt;br /&gt;
P-51D testing it's guns before a flight..jpg|P-51D testing it's guns before a flight.&lt;br /&gt;
P-51D trim tab animation..jpg|P-51D trim tab animation.&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Balancing the Boeing 747-400|By [[User:Gijs|Gijs]]}}&lt;br /&gt;
After he started developing the [[Boeing 747-400]] as a hobby project six years ago, Gijs finally managed to get the weight and balancing right. The center of gravity is now within 0.05% MAC (40 cm) of the published values.&lt;br /&gt;
&lt;br /&gt;
Make sure to use the new Fuel and Payload dialog to fill your fuel tanks. There is a slider and button that will nicely distribute a specified amount of fuel, while making sure the CoG stays within the operational limits. Before takeoff, check the Takeoff Reference page on the CDU to find the required stab trim units (your current setting is displayed to the left of the throttle quadrant). When you set your trim properly, you can almost relax your yoke to the neutral position after rotate. There's still some FDM work left to fine-tune this.&lt;br /&gt;
&lt;br /&gt;
The updated 747-400 is already available through Git and will be on the download page when FlightGear 3.2 is released.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Extra500 is updated to production status|By [[User:Evandenberg|Evandenberg]]}}&lt;br /&gt;
The [[Extra EA-500]] is updated and has reached &amp;quot;production status&amp;quot;! Just a short list of changes for release 1.1.0:&lt;br /&gt;
* Engine+fuel: realistic flame-out, fuel flow to collector compartment, anti ice influence on TOT, improved oil press and temp model&amp;lt;br/&amp;gt;&lt;br /&gt;
* Aerodynamics: flap performance, elevator-30deg-flaps authority improvement&amp;lt;br/&amp;gt;&lt;br /&gt;
* User interface: interactive checklists&amp;lt;br/&amp;gt;&lt;br /&gt;
* Sounds: corrected sounds for test, CWS and AP disc&amp;lt;br/&amp;gt;&lt;br /&gt;
* Model: added interior, yokes&amp;lt;br/&amp;gt;&lt;br /&gt;
* Avionics: IFD moving map, automatic NAV tuning, automatic NAV switching, magnetic variation fixes&amp;lt;br/&amp;gt;&lt;br /&gt;
* Autopilot: added OBS and fly vectors mode, significant improvement of coupled ILS performance&lt;br /&gt;
A more extensive list can be found in the &amp;quot;version&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
This version does perform a bit better on my computer, but this has to do with improvements to FGFS, not of the aircraft model. So if your computer was struggling with the initial version, we recommend to use current FlightGear git/nightly builds or wait until 3.2 comes out!&lt;br /&gt;
&lt;br /&gt;
Please checkout the [[Extra EA-500|Extra500 wiki]] for download instructions and lots of more info.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=packed heights=250px&amp;gt;&lt;br /&gt;
File:Extra500 flightgear1.png|Extra500 flying in clouds&lt;br /&gt;
Extra500canvas.png|Work has begun to analyze, refactor and generalize useful parts of the [[Avidyne Entegra R9]] to help reuse some code in similar MFD efforts, like the [[Garmin GPSMap 196]] or [[Canvas EFB Framework]]&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|USA state capital buildings|By [[User:Jonbourg|Jonbourg]]|Scenery corner}}&lt;br /&gt;
There is a project to add all the USA state capital buildings into FG.  It is discussed in [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22715&amp;amp;sid=ea847909bde2e1f8ffe5b94bcc673f4f this scenery forum thread]. There is also a wiki page: [[State Capitol Buildings in the United States]].  So far, Idaho, Louisiana &amp;amp; Nebraska have been completed. Hawaii and New York are currently in progress.  Please feel free to join in with any other state that has not been done yet.  Just let us know through the forum and we will add it to the in progress list.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|LIPY, a scenery conversion from MSFS|By [[User:bigstones|bigstones]]}}&lt;br /&gt;
This month saw the [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22623 second &amp;quot;preview&amp;quot; release] of the conversion of a scenery for MS Flight Simulator, [[Falconara Airport]] (ICAO code: LIPY), a small Italian international airport halfway down the Adriatic coast. The original author granted the permission to the conversion and even allowed for it to be included in the FlightGear official [[World Scenery]], at least the GPL compatible parts. This is not a huge limitation though, because most of the material was created from scratch, included pictures taken on purpose at the real airport, with the authorities' collaboration. Copyrighted aerial imagery only include the (unsuable) photoreal ground and some roofs.&lt;br /&gt;
&lt;br /&gt;
[[File:LIPY structures landscape.jpg|650px|right]]&lt;br /&gt;
The conversion was made with [[ModelConverterX]], which makes the job partially easier than by [[Howto:Convert objects from X-Plane|the Blender method]], yet it's still needing fixes because of some misunderstandings with the coordinates axes. The author of the tool, though, seems not very concerned and anyway, it's so rare to have a freeware scenery author allow conversions, that the usefulness of this tool would be greatly reduced anyhow, especially if you plan to upload the models to the [[FlightGear Scenery Database]].&lt;br /&gt;
&lt;br /&gt;
The conversion itself, moreover, sure is not the matter of a button press. MSFS scenery are often packed and &amp;quot;compiled&amp;quot; in *.BGL files such that independent, far objects with the same materials and same LOD level (Level Of Detail) are bound together. This is clearly against FG's way, in which each new scenery generation could change the relative heights, and however MSFS airports are flat, while in FG they're all sloped. A similar thing happens with the texture maps. This basically means that you'll have to join all these objects and split them again based on the model they belong to (e.g. tower, terminal, hangars...)&lt;br /&gt;
&lt;br /&gt;
Another issue with textures is that in FG it's good practice - recommended if not mandatory - to have 2 separate texture maps for the same object, if some parts are translucent. This means that without rebuilding all the texture maps [http://forum.flightgear.org/viewtopic.php?f=5&amp;amp;t=22707 you'll likely get artifacts]. Then, you'd have to add the Rembrandt lights if you want, and also the lightmaps (MSFS uses night textures, but Gimp can easily convert them). This whole experience can be summed up in the following quote:&lt;br /&gt;
&lt;br /&gt;
{{cquote|I really wanted to have this scenery in FG because it's my home base, and seeing it ready and so well done just made me want it. However, even if still easier than making it from scratch (even if reusing the textures), I'd have to think well if I had to do this again.|bigstones, maintainer of the conversion}}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Reshaping Leipzig/Halle Airport|By [[User:August|August]]}}&lt;br /&gt;
[[File:2014 new-layout-EDDP 05.jpg|650px|right]]&lt;br /&gt;
In FlightGear Germany's second largest cargo airport [[EDDP]] is well known as a detailed model accessible for everybody via [[TerraSync]]. Until 2013 it was famous for its regular ATC-events. It has been updated several times, at least 2012 by users D-STHO and August. When FlightGear 3.0 was published the airport layout changed from the old 810-standard to the new 850-standard. But the update (based on a taxiway layout modelled for X-Plane) turned out to be very imperfect. Many aprons and taxiways did not exist, dimensions did not appear to be correct and many new facilities which had been added at the real-world airport had not been taken into account. So maintainer August decided to redesign the whole airport from the scratch using [[WorldEditor]]. &lt;br /&gt;
Pilots and developers are now invited to test the new airport model which includes further improvements like predefined STAR-, -SID and Transition procedures and hundreds of replaced Static- and Shared Models. The project will be published on TerraSync as soon as all defects are discovered remedied.&lt;br /&gt;
&lt;br /&gt;
Developer Version:&lt;br /&gt;
   '''git clone''' [https://gitorious.org/eddp-custom-scenery/eddp-custom-scenery/ https://gitorious.org/eddp-custom-scenery/eddp-custom-scenery/]&lt;br /&gt;
&lt;br /&gt;
Feedback is welcome at [[User talk:August|August's wiki page]].&lt;br /&gt;
&amp;lt;gallery mode=packed&amp;gt;&lt;br /&gt;
2014 new-layout-EDDP 04.jpg|Taxiway T - new ground textures&lt;br /&gt;
2014 new-layout-EDDP 01.jpg|Runway 26L with DHL-area&lt;br /&gt;
2014 new-layout-EDDP 02.jpg|Apron 4&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|An updated Weather article|By [[User:bigstones|bigstones]]|Wiki updates}}&lt;br /&gt;
The [[Weather]] wiki article went through a wide extension. Although Advanced Weather was released quite a while ago, its usage has never been explained in the wiki, and some thorough instructions were available only in a readme in the &amp;quot;docs&amp;quot; folder of the base package which is not commonly explored by users, while the wiki article [[Advanced weather]] is more about the project than the usage.&lt;br /&gt;
&lt;br /&gt;
AW's advanced configuration is known to be not easy. So, if you always only used the weather selection menu and want to know more, or want to understand what the options actually do and how you can combine them, the [[Weather]] article has now been updated with some hints and basic notions extracted from experience and the original documentation, and quality checked by the author of the AW weather engine.&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Translators required|}}&lt;br /&gt;
{|&lt;br /&gt;
|[[File:en.gif]]&lt;br /&gt;
|The FlightGear Wiki still needs help for translating it into various languages. If you are interested in making the FlightGear Wiki multi-language then start at [[Help:Translate]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:de.gif]]&lt;br /&gt;
|Das FlightGear Wiki benötigt immer noch Hilfe bei der Übersetzung in verschiedene Sprachen. Wenn Du Interesse daran hast, das FlightGear Wiki Mehrsprachig zu machen, dann fang doch mit [[:de:Help:Übersetzen|Help:Übersetzen]] an.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:nl.gif]]&lt;br /&gt;
|De FlightGear Wiki kan nog steed hulp gebruiken bij het vertalen van artikelen. Als je interesse hebt om de wiki meertalig te maken, raden we je aan om een kijkje te nemen bij [[:nl:Help:Vertalen|Help:Vertalen]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:es.gif]]&lt;br /&gt;
|La FlightGear wiki todavía necesita ayuda para traducirla a varios lenguajes. Si estás interesado en hacer la FlightGear wiki multilingüe, entonces comienza en [[:es:Help:Traducir|Help:Traducir]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter-article-start|Call for volunteers||And finally...}}&lt;br /&gt;
* The [[TerraGear]] maintainers are looking for volunteers to help with development on the next world scenery project.  If you've ever wondered how a full 3D model of earth can be generated from raw data, now is your chance.  See the plan at [[TerraGear roadmap]].&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter|2014 06]]&lt;br /&gt;
[[Category:Changes after 3.00]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Howto:Animate_gear_scissors&amp;diff=73444</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=73444"/>
		<updated>2014-06-29T08:59:46Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Tracking Animation&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|trackking 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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_event_handling&amp;diff=73389</id>
		<title>Canvas event handling</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_event_handling&amp;diff=73389"/>
		<updated>2014-06-28T10:45:40Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Canvas]]&lt;br /&gt;
{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
'''Note: This feature is only available in FlightGear versions &amp;gt;= 2.11 !'''&lt;br /&gt;
&lt;br /&gt;
The Canvas event handling system closely follows the W3C [http://www.w3.org/TR/DOM-Level-3-Events/ DOM Event Model]. If you have already used events in JavaScript and HTML most concepts of the Canvas event system should be already familiar to you. The most notable difference is the missing capture phase, but it is usually not used anyhow.&lt;br /&gt;
&lt;br /&gt;
Listeners - simple Nasal functions - can be attached to every element inside the Canvas and the Canvas itself. Once a certain action - like moving the mouse or pressing a button - occurs the associated listeners are called. We can use this for example to detect whether the mouse has moved over an element or if a certain element has been clicked.&lt;br /&gt;
&lt;br /&gt;
= Listen for events =&lt;br /&gt;
&lt;br /&gt;
To receive events callback function can be added to elements on a Canvas as well as to the Canvas itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
canvas.addEventListener(&amp;quot;&amp;lt;type&amp;gt;&amp;quot;, &amp;lt;func&amp;gt;);&lt;br /&gt;
canvas_element.addEventListener(&amp;quot;&amp;lt;type&amp;gt;&amp;quot;, &amp;lt;func&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For each placement of a Canvas handling events can be enabled or disabled. A Canvas placed in a PUI (old GUI) widget or as standalone GUI window receives events by default, whereas Canvases placed onto the aircraft model or in the scenery do not receive any events by default.&lt;br /&gt;
&lt;br /&gt;
{{Note|The old [[Howto:Adding_a_canvas_to_a_GUI_dialog|PUI/XML GUI]] does not trigger any mouseover/hover events. Mouse clicks/wheel/drag are working as expected. For all other placements like on standalone Canvas windows and [[Howto:Add_a_2D_canvas_instrument_to_your_aircraft|3D models]] there is no such limitation.}}&lt;br /&gt;
&lt;br /&gt;
For standalone GUI windows setting '''capture-events''' to ''0'' or ''1'' enables or disables handling of events respectively. For a Canvas placed onto a 3d model, setting ''capture-events'' inside the placement can be used to activate event handling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var dlg = canvas.Window.new([152,74]);&lt;br /&gt;
&lt;br /&gt;
# Disable event handling for this window. Events will pass through&lt;br /&gt;
# and can reach any window or also object covered by the window.&lt;br /&gt;
dlg.setBool(&amp;quot;capture-events&amp;quot;, 0);&lt;br /&gt;
&lt;br /&gt;
# Place the canvas onto the PFD and enable receiving events&lt;br /&gt;
my_canvas.addPlacement({&amp;quot;node&amp;quot;: &amp;quot;PFD-Screen&amp;quot;, &amp;quot;capture-events&amp;quot;: 1});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Event flow =&lt;br /&gt;
&lt;br /&gt;
Events always are targeted at a specific element inside the Canvas. Before any event handler is called the propagation path for the event is determined. It consists of the event target itself and all its ancestor elements (Groups) up to and including the Canvas. Afterwards - during the ''Target Phase'' - all listeners registered on the event target are called. Finally - during the ''Bubbling Phase'' - the event bubbles up the tree, following the propagation path determined in the first step, and all listeners attached to the according elements are called.&lt;br /&gt;
&lt;br /&gt;
[[File:Canvas Eventflow.png|thumb|540px|center|Event flow of Canvas Events similar to W3C DOM Event flow &amp;lt;ref name=&amp;quot;dom-event-flow&amp;quot;&amp;gt;DOM Level 3 event flow. http://www.w3.org/TR/DOM-Level-3-Events/#event-flow&amp;lt;/ref&amp;gt;.]]&lt;br /&gt;
&lt;br /&gt;
= Event classes =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var Event = {&lt;br /&gt;
  # Name of event type [read-only]&lt;br /&gt;
  type: &amp;lt;typename&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Target element [read-only]&lt;br /&gt;
  target: &amp;lt;target-element&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Element the currently called listener is attached to [read-only]&lt;br /&gt;
  currentTarget: &amp;lt;target-element&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Stop further propagation of event (stop&lt;br /&gt;
  # bubbling up to its parents)&lt;br /&gt;
  stopPropagation: func()&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
var MouseEvent = {&lt;br /&gt;
  parents: [Event],&lt;br /&gt;
&lt;br /&gt;
  # Position in screen coordinates [read-only]&lt;br /&gt;
  screenX: &amp;lt;screen-x&amp;gt;,&lt;br /&gt;
  screenY: &amp;lt;screen-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Position in window/canvas coordinates [read-only]&lt;br /&gt;
  clientX: &amp;lt;client-x&amp;gt;,&lt;br /&gt;
  clientY: &amp;lt;client-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Position in local/element coordinates [read-only]&lt;br /&gt;
  localX: &amp;lt;local-x&amp;gt;,&lt;br /&gt;
  localY: &amp;lt;local-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Distance to position of previous event [read-only]&lt;br /&gt;
  deltaX: &amp;lt;delta-x&amp;gt;,&lt;br /&gt;
  deltaY: &amp;lt;delta-y&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # Current click count (number of clicks within a certain&lt;br /&gt;
  # time limit. max. 3) [read-only]&lt;br /&gt;
  click_count: &amp;lt;click-count&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  # Buttons/modifiers require FlightGear &amp;gt;= 3.1.0&lt;br /&gt;
&lt;br /&gt;
  # Button which triggered this event [read-only]&lt;br /&gt;
  #&lt;br /&gt;
  #  0: primary button (usually the left button)&lt;br /&gt;
  #  1: auxiliary button (usually the middle button/mouse wheel)&lt;br /&gt;
  #  2: secondary button (usually the right button)&lt;br /&gt;
  button: &amp;lt;button&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # State of all mouse buttons at the time the event has been&lt;br /&gt;
  # triggered [read-only]&lt;br /&gt;
  buttons: &amp;lt;active-button-mask&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # State of all keyboard modifiers at the time the event has&lt;br /&gt;
  # been triggered [read-only]&lt;br /&gt;
  modifiers: &amp;lt;modifier-mask&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  ctrlKey: &amp;lt;was-ctrl-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  shiftKey: &amp;lt;was-shift-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  altKey: &amp;lt;was-alt-down&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
  # [read-only]&lt;br /&gt;
  metaKey: &amp;lt;was-meta-down&amp;gt;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Middle-mouse button emulation ==&lt;br /&gt;
&lt;br /&gt;
2-button mice can be setup to emulate a middle-mouse button click by pressing the left and right button simultaneously. On Ubuntu you can use [https://apps.ubuntu.com/cat/applications/gpointing-device-settings gpointing-device-settings] to enable &amp;quot;middle button emulation&amp;quot;&lt;br /&gt;
&amp;lt;ref&amp;gt;https://wiki.ubuntu.com/X/Quirks#A2-button_Mice&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref&amp;gt;http://askubuntu.com/questions/140828/how-can-i-paste-text-by-pressing-the-left-and-right-mouse-buttons-at-the-same-ti&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Event types =&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Description !! DOM equivalent event !! Bubbles &amp;lt;ref name=&amp;quot;dom-event-flow&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| ''mousedown'' || Mouse button pressed || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mousedown mousedown] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseup'' || Mouse button released || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseup mouseup] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''click'' || ''mousedown'' + ''mouseup'' have been triggered for this element without moving more than a certain maximum distance || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-click click] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''dblclick'' || Two ''click'' events have been triggered for this element without moving more than a certain maximum distance and time limit || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-dblclick dblclick] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''drag'' || The mouse has been moved with a button down. After dragging has started above an element, all consecutive ''drag'' events are sent to this element even if the mouse leaves its area || || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''wheel'' || Mouse wheel rotated (see deltaY for direction) || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-wheel wheel] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mousemove'' || Mouse has moved while beeing inside the area of the target element. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mousemove mousemove] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseover'' || Mouse has entered a child or the element itself. ''mouseover'' is also triggered if the mouse moves from one child element to another.  || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseover mouseover] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseout'' || Mouse has left a child or the element itself. ''mouseout'' is also triggered if the mouse moves from one child element to another. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseout mouseout] || {{tick}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseenter'' || Mouse has entered a child or the element itself. In contrary to ''mouseover'', ''mouseenter'' is not triggered if the mouse moves from one child element to another, but only the first time the element or one of its children is entered. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseenter mouseenter] || {{cross}}&lt;br /&gt;
|-&lt;br /&gt;
| ''mouseleave'' || Mouse has left the element and all of its children. In contrary to ''mouseout'', ''mouseleave'' is not triggered if the mouse moves from one child element to another, but only if the mouse moves outside the element and all its children. || [http://www.w3.org/TR/DOM-Level-3-Events/#event-type-mouseleave mouseleave] || {{cross}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Example Code =&lt;br /&gt;
For the latest examples, please refer to [https://gitorious.org/~tomprogs/fg/toms-fgdata/commits/canvas-gui-demo Tom's canvas-gui-demo branch on gitorious]. This is also where you can find the following code in $FG_ROOT/Nasal/canvas/gui.nas (note that this example makes use of advanced Nasal concepts, such as anonymous functions, method chaining and lots of embedded/inline code):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# Canvas GUI demo&lt;br /&gt;
#&lt;br /&gt;
#  Shows an icon in the top-right corner which upon click opens a simple window&lt;br /&gt;
#&lt;br /&gt;
(func {&lt;br /&gt;
var init_gui = setlistener(&amp;quot;/nasal/std/loaded&amp;quot;, func() {&lt;br /&gt;
  removelistener(init_gui);&lt;br /&gt;
  var dlg = canvas.Window.new([32,32]);&lt;br /&gt;
  dlg.setInt(&amp;quot;tf/t[1]&amp;quot;, 4)&lt;br /&gt;
     .setInt(&amp;quot;right&amp;quot;, 4);&lt;br /&gt;
  var my_canvas = dlg.createCanvas()&lt;br /&gt;
                     .setColorBackground(0,0,0,0);&lt;br /&gt;
  var root = my_canvas.createGroup();&lt;br /&gt;
  canvas.parsesvg(root, &amp;quot;gui/dialogs/images/icon-aircraft.svg&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  my_canvas.addEventListener(&amp;quot;click&amp;quot;, func&lt;br /&gt;
  {&lt;br /&gt;
    var dlg = canvas.Window.new([400,300], &amp;quot;dialog&amp;quot;);&lt;br /&gt;
    var my_canvas = dlg.createCanvas()&lt;br /&gt;
                       .set(&amp;quot;background&amp;quot;, &amp;quot;#f2f1f0&amp;quot;);&lt;br /&gt;
    var root = my_canvas.createGroup();&lt;br /&gt;
    root.addEventListener(&amp;quot;click&amp;quot;, func(e) { printf(&amp;quot;click: screen(%.1f|%.1f) client(%.1f|%.1f) click count = %d&amp;quot;, e.screenX, e.screenY, e.clientX, e.clientY, e.click_count); });&lt;br /&gt;
    root.addEventListener(&amp;quot;dblclick&amp;quot;, func(e) { printf(&amp;quot;dblclick: screen(%.1f|%.1f) client(%.1f|%.1f)&amp;quot;, e.screenX, e.screenY, e.clientX, e.clientY); });&lt;br /&gt;
    root.addEventListener(&amp;quot;wheel&amp;quot;, func(e) { printf(&amp;quot;wheel: screen(%.1f|%.1f) client(%.1f|%.1f) %.1f&amp;quot;, e.screenX, e.screenY, e.clientX, e.clientY, e.deltaY); });&lt;br /&gt;
    var text =&lt;br /&gt;
      root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
          .setText(&amp;quot;This could be used for building an 'Aircraft Help' dialog.\nYou can also #use it to play around with the new Canvas system :). β&amp;quot;)&lt;br /&gt;
          .setTranslation(10, 30)&lt;br /&gt;
          .setAlignment(&amp;quot;left-top&amp;quot;)&lt;br /&gt;
          .setFontSize(14)&lt;br /&gt;
          .setFont(&amp;quot;LiberationFonts/LiberationSans-Regular.ttf&amp;quot;)&lt;br /&gt;
          .set(&amp;quot;max-width&amp;quot;, 380)&lt;br /&gt;
          .setColor(0,0,0);&lt;br /&gt;
    var text_move =&lt;br /&gt;
      root.createChild(&amp;quot;text&amp;quot;)&lt;br /&gt;
          .setText(&amp;quot;Mouse moved over text...&amp;quot;)&lt;br /&gt;
          .set(&amp;quot;character-size&amp;quot;, 15)&lt;br /&gt;
          .set(&amp;quot;font&amp;quot;, &amp;quot;LiberationFonts/LiberationSans-Bold.ttf&amp;quot;)&lt;br /&gt;
          .set(&amp;quot;alignment&amp;quot;, &amp;quot;left-center&amp;quot;)&lt;br /&gt;
          .setTranslation(20, 200)&lt;br /&gt;
          .set(&amp;quot;fill&amp;quot;, &amp;quot;#ff0000&amp;quot;)&lt;br /&gt;
          .hide();&lt;br /&gt;
    var visible_count = 0;&lt;br /&gt;
    text.addEventListener(&amp;quot;mouseover&amp;quot;, func text_move.show());&lt;br /&gt;
    text.addEventListener(&amp;quot;mouseout&amp;quot;, func text_move.hide());&lt;br /&gt;
  });&lt;br /&gt;
});&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_widgets&amp;diff=73179</id>
		<title>Canvas widgets</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_widgets&amp;diff=73179"/>
		<updated>2014-06-24T10:15:56Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Template:Canvas Navigation}}&lt;br /&gt;
&lt;br /&gt;
As of 07/2012, there's a general consensus to replace the current FlightGear GUI (based on PLIB/PUI) by using the new Canvas system.&lt;br /&gt;
&lt;br /&gt;
However, before we can work on adding new widgets to FlightGear, we need to provide wrappers for the existing hardcoded PUI widgets, see [[Canvas GUI]].&lt;br /&gt;
&lt;br /&gt;
Canvas widgets are dynamically created GUI widgets that use the [[Canvas]] subsystem to create custom, owner-drawn, GUI widgets in a scripted fashion using [[Nasal]]. The textures are conventional canvas textures, however they are rendered by the GUI system, so that scripted event handlers can be implemented which respond to GUI events, such as keyboard/mouse input or other events (resize, update, redraw etc). &lt;br /&gt;
&lt;br /&gt;
Using canvas widgets, it will be possible to create your own GUI styles and even completely new, fully interactive, GUI controls (buttons, text boxes, list views, tree views etc) just by using Nasal, without touching any C++ code and without rebuilding FlightGear. The Canvas system supports loading SVG files and raster images, so that canvas elements and GUI widgets can be assembled from SVG elements, meaning that you'll  be able to use a conventional SVG editor like Inkscape to create/edit FlightGear GUI widgets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The Idea ==&lt;br /&gt;
This section lists a bunch of ideas related to supporting Canvas textures for GUI drawing needs, i.e. to render Canvases as textures, but also to increasingly implement parts of the GUI (such as custom widgets) using interactive Canvases with scripted callbacks, the idea is to work around existing GUI/PUI shortcomings by using Canvases to implement custom styles and widgets.&lt;br /&gt;
&lt;br /&gt;
{{cquote|&amp;lt;nowiki&amp;gt;We &lt;br /&gt;
could could allow aircraft dialogs to include custom widgets, although that &lt;br /&gt;
might be unwise for other reasons&amp;lt;/nowiki&amp;gt;&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37868.html|title=&amp;lt;nowiki&amp;gt;Re: [Flightgear-devel] Switching from PUI to osgWidget&amp;lt;/nowiki&amp;gt;|author=&amp;lt;nowiki&amp;gt;James Turner&amp;lt;/nowiki&amp;gt;|date=&amp;lt;nowiki&amp;gt;Tue, 24 Jul 2012 10:36:26 -0700&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;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Plan ==&lt;br /&gt;
In contrast to using some hardcoded GUI system (PUI, osgWidget, etc.) this approach would give much more flexibility and also the means of modifying and creating new widgets without the need to touch any core code.&lt;br /&gt;
&lt;br /&gt;
With the Canvas system every type of widget would be possible, so that also things like submenus can be realized.&lt;br /&gt;
&lt;br /&gt;
Another advantage of the Canvas approach is that it is heavily using the property tree and therefore is already fully accessible from Nasal code and also configurable with the existing xml formats. [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37861.html]&lt;br /&gt;
&lt;br /&gt;
The point of the canvas widget demo is to demonstrate how powerful and flexible the new canvas system really is, i.e. it cannot just be used for aircraft scripting (instruments, MFDs), but also for GUI scripting - which means that using the canvas system would unify the 2D rendering backend (all 2D rendering can be handled via canvas), while reducing the amount of C++ code we have doing these things, which would mean that the GUI system could be entirely maintained in scripting space, i.e. as part of the base package, by people who don't need to know C++ - some basic Nasal knowledge will do.&lt;br /&gt;
&lt;br /&gt;
Basically, adopting the new canvas system for such and similar purposes, will mean that tons of old/oudated C++ code can be phased out and replaced by a single consistent implementation in C++, that is using modern C++/OSG code - which ultimately also means that OSG itself can make more assumptions about what's being rendered, so that more optimizations (= better frame rates) can be more easily accomplished by using OSG coding patterns and protocols in a single place, instead of outdated/custom/3rd party libraries which would need to be manually baked into the existing FG/SG/OSG eco system.&lt;br /&gt;
&lt;br /&gt;
Currently, the canvas system is integrated in such a fashion that it will keep working with the old GUI code still in place.In addition, all of the exsting GUI features (layouting, XML processing) are implicitly supported due to the way the canvas system is implemented at the moment. These are real roadblocks when implementing a new GUI library next to PUI, because all of the existing stuff would need to be explicitly ported (either in C++ space or by converting tons of XML files).&lt;br /&gt;
&lt;br /&gt;
Overall, the canvas system will give us all of this &amp;quot;for free&amp;quot;, and it will mean less C++ code in the source tree, too - i.e. better maintainability.&lt;br /&gt;
&lt;br /&gt;
Also, once the standalone &amp;quot;FGCanvas&amp;quot; is available, it would also be possible to run the GUI in multiple windows or even in separate processes.&lt;br /&gt;
&lt;br /&gt;
In addition, by using the canvas system for GUI widgets, it would also be possible to render aircraft instruments, MFDs, HUDs etc WITHIN GUI dialogs, too.&lt;br /&gt;
&lt;br /&gt;
== Status (06/2014) ==&lt;br /&gt;
{{warning|The canvas gui always handles events first and only if no window was hit forwards events to scenery picks and PUI dialogs. Which means that PUI (old) dialogs rendered on top of new canvas windows, will not receive their GUI events currently. With FlightGear 3.1+ this is no problem anymore, as Canvas windows are drawn on top of PUI dialogs to match the rendering order and the event handling order.}}&lt;br /&gt;
&lt;br /&gt;
* '''TheTom''' (05/2013): &amp;quot;I'm still not completely sure how to implement the GUI, but currently I'm thinking of something similar to most available UI toolkits with mainly using images together with 9-scale/slicing. Theming would be possible by simply exchanging the images and/or modulate them with a color. For some icons/elements also SVG could be used, and maybe I'll implement the possibility to cache rendered images of SVG elements for faster rendering of them.&amp;quot; [http://forum.flightgear.org/viewtopic.php?f=71&amp;amp;t=19850#p182509]&lt;br /&gt;
* '''TheTom''': (30/07/2012) I have now pushed some updates to my branch. It is now possible to create windows (texture rectangles) with just using the property tree and place a canvas texture onto it. Mouse events are passed to the active window (=the window the cursor is hovering over, or for dragging the window where the drag gesture started) and can be handled from Nasal or anything else that has access to the property tree.&lt;br /&gt;
&lt;br /&gt;
{{#ev:youtube|1a6wtPVPWc4}}&lt;br /&gt;
{{#ev:youtube|CIS8UyuJLgM}}&lt;br /&gt;
{{#ev:youtube|Qv-uEX42QZY}}&lt;br /&gt;
{{#ev:youtube|llVaasTEf44}}&lt;br /&gt;
&lt;br /&gt;
=== Missing / Todo ===&lt;br /&gt;
Last updated: 08/2012&lt;br /&gt;
&lt;br /&gt;
List of missing things (if you'd like to get involved to help with any of these, please get in touch via the [http://forum.flightgear.org/viewforum.php?f=71 canvas forum]):&lt;br /&gt;
==== Misc ====&lt;br /&gt;
* '''Documentation''': Read, ask questions, extend. I haven't done too much documentation (apart from inline documentation) just due to the reason that the API is not completely stable yet. You could also try different use-cases and maybe find some examples where the API lacks some features.{{Not done}}&lt;br /&gt;
* '''Own ideas''': Come up with a new idea or something that I have already mentioned somewhere else {{Feedback}}&lt;br /&gt;
* Find more work I've currently forgotten about :) {{Feedback}}&lt;br /&gt;
&lt;br /&gt;
==== C++ ====&lt;br /&gt;
* '''[[#Keyboard Handling|Keyboard input]]''': I haven't thought too much about it and also haven't done anything, but we will definitely need access to keyboard events {{Not done}}&lt;br /&gt;
* '''Clipping''': For different reasons we will need to be able to clip some elements to certain regions. It should work with specifying either a clipping rectangle or by using a path. OpenVG seems to have support for it, although I haven't looked into it too deep. We also need to ensure that it also works with text. At least rectangular regions are needed.(eg. group/clip-min[0..1], group/clip-max[0..1]) {{Not done}}&lt;br /&gt;
* '''Animations''': I don't know if we should do animations just by using interpolator and settimer from Nasal or if we should implement some time-based animations directly in C++. At least we need some helper functions (eg. for blinking elements -&amp;gt; cursor, fading, ...) It would also be possible to implement animations purely in Nasal space, e.g. by supporting a subset of SMIL for SVG, so that existing tools could be used to created animated vector images that are converted to canvas properties by the Nasal parser.&lt;br /&gt;
* Check what is missing to implement the different hardcoded instruments.{{Not done}}&lt;br /&gt;
* provide Nasal hooks to access: taxiways, &amp;lt;del&amp;gt;&amp;lt;parking positions&amp;lt;/del&amp;gt; etc&lt;br /&gt;
* Maybe support displaying shapefiles.{{Not done}}&lt;br /&gt;
* '''Unify the canvas creation a bit''': such that canvases can be moved seamlessly between the different placements (gui, model,hud, etc.). The normal model placement is great but the gui widget placement needs to be able to also use an already existing canvas.{{Not done}}&lt;br /&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.{{Not done}}&lt;br /&gt;
&lt;br /&gt;
==== Nasal ====&lt;br /&gt;
&lt;br /&gt;
* '''[[Canvas_Widgets#Widget_Declaration_via_SVG|Extend gui.nas to support loading widgets from SVG files]]''': We want to be able to load widgets from SVG files and link them to Nasal code in [[$FG_ROOT]]/Nasal/widgets - for example: [[$FG_ROOT]]/Nasal/widgets/button.nas {{Not done}}&lt;br /&gt;
* '''[[Canvas_Widgets#Nasal_requirements|Implement Widgets]]''': {{Not done}}&lt;br /&gt;
* '''[http://wiki.flightgear.org/Canvas_Widgets#Layout_Management_.28_.28Not_done.29.29 Layout Handling]''': {{Not done}}&lt;br /&gt;
* '''[[Canvas_Widgets#Dialog_Parser|Implement the dialog/xml parser]]''': {{Not done}}&lt;br /&gt;
* '''[http://wiki.flightgear.org/Canvas_Widgets#Styling.2C_Theming_and_Skinning_.28XSL.2FCSS_via_SVG.29 Implement a generic CSS/XSL-based styling class]''': (Could also be used to implement styling support of the current GUI) {{Not done}}&lt;br /&gt;
* '''[[Canvas Maps|Geographic Mapping]]''': It's very experimental, missing different projection modes (eg. vertical projection) and especially the Nasal API feels very hackish. {{Progressbar|50}}&lt;br /&gt;
* '''Improve the Nasal API''': Add some helper functions for animating different glass cockpit displays (I have already some basic code, but it needs some generalization).&lt;br /&gt;
&lt;br /&gt;
== Fully Canvas based implementation (in progress as of 08/2012) ==&lt;br /&gt;
This section describes a possible way of completely getting rid of PUI and providing a GUI system by only using the Canvas system.&lt;br /&gt;
&lt;br /&gt;
=== C++ core requirements {{Pending}} ===&lt;br /&gt;
{{Progressbar|40}}&lt;br /&gt;
&lt;br /&gt;
Certain properties can be set to affect the appearance and behavior of the dialog:&lt;br /&gt;
&lt;br /&gt;
* Initial position&lt;br /&gt;
* Dragable&lt;br /&gt;
* Resizeable&lt;br /&gt;
** If true, min/max/initial size&lt;br /&gt;
** If false, size&lt;br /&gt;
* Modal&lt;br /&gt;
* Texture coordinates (allow using just part of the canvas, eg. to have enough space for larger window after resize)&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
* The Canvas manager needs to be extended to support using such a window as target for a placeable definition. If a window is resizeable the size property nodes will be updated to allow the canvas and/or its viewport being resized. {{Done}}&lt;br /&gt;
* It would be also be good to allow the canvas textures to be resized at runtime, so that we don't have to reserve to large canvases just because the dialogs could be resized. {{Pending}}&lt;br /&gt;
* The GUI system should take care of handling and forwarding mouse and keyboard events to the property tree as needed (Some parts of the existing code could probably be reused). Eg. if a canvas is assigned picking should occur on mouse clicks and forwarded to the property tree. {{Pending}}&lt;br /&gt;
* The existing dialog-show command needs to be modified to call the according function in Nasal space which will handle the whole creation and updating of the GUI. {{Pending}} (can be done by using the new removecommand/addcommand APIs meanwhile)&lt;br /&gt;
&lt;br /&gt;
=== Keyboard Handling  ===&lt;br /&gt;
{{Feedback}}&lt;br /&gt;
&lt;br /&gt;
Looking at the mouse handling code, the same technique we use for mouse handling could obviously also be used for keyboard handling:&lt;br /&gt;
* http://www.openscenegraph.org/documentation/NPSTutorials/osgKeyboardInput.htm&lt;br /&gt;
* http://www.openscenegraph.org/projects/osg/wiki/Support/Tutorials/BasicKeyboardInput&lt;br /&gt;
&lt;br /&gt;
So it just involves checking for osgGA::GUIEventAdapter::KEYDOWN and propagating the events to a handful of child properties for each canvas element that subscribed to keyboard events.&lt;br /&gt;
&lt;br /&gt;
It'd make sense to also use a boolean property to enable/disable reception of keyboard events, that will allow us to set the &amp;quot;focus&amp;quot; of windows and widgets. And then we only need to expose some keyboard-specific events like key-up, key-down, key-value etc at the C++ level, which all boils down to just calling fgSet*Value().&lt;br /&gt;
&lt;br /&gt;
The rest will be handled at the Nasal level, so that users can register their own listeners.&lt;br /&gt;
&lt;br /&gt;
The nice thing is that once this is properly implemented, we'll already have a unified I/O handling system for GUIs, instruments, HUDs etc. and it moves all the implementation details to the base package again.&lt;br /&gt;
&lt;br /&gt;
BTW: There is already a property to toggle the mouse cursor via setprop, so this could also be wrapped in gui.nas, obviously being able to use a canvas texture as the cursor would prove the point that &amp;quot;everything is a canvas&amp;quot; in the design.&lt;br /&gt;
&lt;br /&gt;
I was looking through our earlier discussions, and how osgGA can be used for keyboard support.&lt;br /&gt;
And like I mentioned, I think it would make sense to adopt the same approach that you used for mouse support here.&lt;br /&gt;
&lt;br /&gt;
Overall, I feel it would make sense to closely model this after the way this is handled in Java, i.e. using the same &amp;quot;property events&amp;quot; that are supported in Java for mouse/keyboad and &amp;quot;windows&amp;quot; - just specific to canvas textures, instead of just &amp;quot;windows&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
So instead of &amp;quot;window&amp;quot; events, we'd have &amp;quot;texture&amp;quot; events, so that these can also be used for non-GUI purposes, such as instruments&lt;br /&gt;
&lt;br /&gt;
Looking at our last discussion on forwarding mouse events to nested canvases, it would then really make sense to also have &amp;quot;window/texture&amp;quot; events (create, update, redraw, resize, move etc). So that we don't need to add any C++ code for such things.&lt;br /&gt;
&lt;br /&gt;
And by having &amp;quot;high level&amp;quot; events such as &amp;quot;mouse-enter&amp;quot;, &amp;quot;mouse-leave&amp;quot; or &amp;quot;texture-resize&amp;quot;, &amp;quot;texture-moved&amp;quot;, &amp;quot;has-focus&amp;quot;,&amp;quot;lost-focus&amp;quot; etc, it would be very simple to implement MFDs and GUI widgets in Nasal without requiring C++ workarounds.&lt;br /&gt;
&lt;br /&gt;
So it's really just about supporting 10-15 event types in the C++ code which set some properties, so that the rest can be implemented in Nasal.&lt;br /&gt;
&lt;br /&gt;
Obviously, some events would be texture specific, while others would be specific to groups or elements and should probably be forwarded, like you suggested earlier.&lt;br /&gt;
&lt;br /&gt;
And then it'd be very close to how this is handled in Java, because we could use conventional Nasal listener callbacks to model the details in scripting space.&lt;br /&gt;
&lt;br /&gt;
Specialized widgets could then use these events to implement widget-specific events, i.e. for list view, tree views or other complex widgets - but these could then be implemented in Nasal.&lt;br /&gt;
&lt;br /&gt;
We probably want to support Java-style Key listeners and Key bindings, so that widget-behavior can be easily implemented in Nasal space&lt;br /&gt;
&lt;br /&gt;
=== Nasal requirements  ===&lt;br /&gt;
{{Feedback}}&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;del&amp;gt;The API needs to be extended to allow the creation of windows and placing canvases onto them.&amp;lt;/del&amp;gt; {{Done}}&lt;br /&gt;
* We also need a function which parses existing dialog xml files (reimplementing http://gitorious.org/fg/flightgear/blobs/next/src/GUI/FGPUIDialog.cxx#line708 FGPUIDialog.cxx/FGPUIDialog::makeObject]) and maps them to the new canvas widgets. Each widgets sits in is own Nasal file (eg. inside $FG_DATA/gui/widgets) and has to be implemented using a hash with several required functions, implementing the abstract interface of a widget:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var SampleWidget = {&lt;br /&gt;
  # Add the widget to the parent&lt;br /&gt;
  #&lt;br /&gt;
  # @param config A hash containing all parameters for this widget.&lt;br /&gt;
  new: func(parent, config),&lt;br /&gt;
  # Get the minimal required size. Used for positioning following elements&lt;br /&gt;
  # if no absolute coordinates are given and to calculated available space&lt;br /&gt;
  # for widgets with vertical or horizontal stretch enabled.&lt;br /&gt;
  getMinSize: func(),&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, the interface should probably contain methods to:&lt;br /&gt;
&lt;br /&gt;
* show/hide widget&lt;br /&gt;
* destroy widget&lt;br /&gt;
* enable/disable propagation of events (mouse/keyboard)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Also, we are currently able to reload the GUI in FlightGear, we will want to retain this feature. But once we start implementing widgets in Nasal, we won't just want to reload the GUI XML files, but also the widget modules from [[$FG_ROOT]]/Nasal/widgets, so that widgets can be easily developed and tested, without having to restart FG.&lt;br /&gt;
&lt;br /&gt;
This can be implemented in Nasal space, there's no need to modify the Nasal sub modules code for this - however, we also need to ensure that there's a sane way to terminate all active widgets, i.e. by stopping all running instances. This will also be important to handle simulator reinit/reset.&lt;br /&gt;
&lt;br /&gt;
Thus, during instantiation, all widgets would need to register a listener, so that they can be terminated properly using a signal property.&lt;br /&gt;
&lt;br /&gt;
=== Dialog Parser  ===&lt;br /&gt;
{{Feedback}}&lt;br /&gt;
&lt;br /&gt;
* [https://gitorious.org/fg/fgdata/blobs/master/Docs/README.gui [[$FG_ROOT]]/Docs/README.gui]&lt;br /&gt;
* [http://gitorious.org/fg/flightgear/blobs/next/src/GUI/FGPUIDialog.cxx#line710 Supported Widget Types]&lt;br /&gt;
&lt;br /&gt;
The '''parsegui''' function parses a dialog xml file and calls the constructor of the corresponding widget. &lt;br /&gt;
'''The GUI parser should handle XML versioning, so that future updates to the underlying XML format can be easily supported, without tons of custom code. It might make sense to provide a base class, so that future parsers can be easily implemented next to the existing code, so that new parsers don't need to touch any of the old code!'''&lt;br /&gt;
&lt;br /&gt;
We need to keep the existing way of specifying GUI files via XML - it's a nice, declarative way of building the dialogs. Switching to an imperative system would be a step backwards. I do like the idea of a gui/widget/widgetname.nas structure so we can easily create a factory function and hack / add widgets.&lt;br /&gt;
&lt;br /&gt;
It is important to keep in mind that the Canvas system will have at least 3 related uses:&lt;br /&gt;
* HUDs {{Pending}}&lt;br /&gt;
* GUIs {{Pending}}&lt;br /&gt;
* 2D panels {{Pending}}&lt;br /&gt;
&lt;br /&gt;
All of these will require an XML parser that turns the existing structure into canvas nodes. The existing SVG parser is purely implemented in scripting space (see svg.nas) using the XML parser in [[$FG_ROOT]]/Nasal/io.nas &lt;br /&gt;
&lt;br /&gt;
Given that all three file formats are PropertyList-encoded XML files, it should be possible to come up with a &amp;quot;Xml2Canvas&amp;quot; interface class which implements the XML parser and the Canvas interfaces. That will ensure a maximum degree of code reuse.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Afterwards the getMinSize method is used to calculated the available space and stretch widgets if required.&lt;br /&gt;
&lt;br /&gt;
To ensure that the core widgets in [[$FG_ROOT]]/Nasal/widgets cannot be accidently invalidated by users, the widget namespace/hash will be made immutable using globals.nas magic.&lt;br /&gt;
&lt;br /&gt;
=== Building Widgets at the C++ Level ===&lt;br /&gt;
&lt;br /&gt;
We can always create widgets from C++ by adding canvas elements directly through the property tree, but I think a fully scripted GUI is the most flexible and powerful approach. Let's keep in mind that all the original hard coded PUI dialogs were increasingly replaced with XML dialogs in FlightGear, which was important and a lot of work. &lt;br /&gt;
&lt;br /&gt;
One of the most important goals of the canvas system is to make 2D drawing accessible to end users, without having to know C++ and without having to rebuild FlightGear. This automatically means that large parts of FlightGear will become more maintainable, because they can be moved over to the base package. Starting to implement GUI widgets at the C++ level would defeat the purpose.&lt;br /&gt;
&lt;br /&gt;
While it would definitely be possible to implement widgets by directly creating a canvas via the property tree, that would probably be counter-productive, because we clearly don't want any hard coded C++ special cases.&lt;br /&gt;
&lt;br /&gt;
Now, if someone really wants to implement some custom canvas widget that cannot/shouldn't be modeled in scripting space, then the canvas infrastructure can be extended. &lt;br /&gt;
&lt;br /&gt;
Just take a look at how the existing [[Canvas Maps]] are implemented currently. The same approach could be used to provide support for new/more specific drawing modes, such as:&lt;br /&gt;
&lt;br /&gt;
* aircraft/3D model previews&lt;br /&gt;
* scenery cameras&lt;br /&gt;
* or moving map layers&lt;br /&gt;
* shapefiles&lt;br /&gt;
&lt;br /&gt;
The canvas isn't really about end user features, it's a provider of an infrastructure, so that end user features can be more easily expressed and modeled in scripting space, using Nasal. That's why all end user features should be expressible in scripting space, and only the core infrastructure should need C++ extensions to make this easier. The end user APIs will be mostly designed in scripting space.&lt;br /&gt;
&lt;br /&gt;
== Related ==&lt;br /&gt;
* http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg37854.html&lt;br /&gt;
&lt;br /&gt;
== Related Discussions ==&lt;br /&gt;
* [http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=1495800&amp;amp;group_id=583&amp;amp;atid=350583 05/2006: PUI shortcomings]&lt;br /&gt;
* [http://sourceforge.net/mailarchive/forum.php?thread_name=01C87FCC.5E28B080.johnffay%40cybertron.com&amp;amp;forum_name=plib-devel 03/2008:plib devel discussion on possibly depreciating pui]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18501.html 10/2008:OSGWidget]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg20793.html 01/2009:PUI vs. OSGWidget]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg22427.html 06/2009:PLIB/PUI restrictions]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg22510.html 06/2009:OSGWidget related]&lt;br /&gt;
* [http://sourceforge.net/mailarchive/message.php?msg_name=m1ab0ew87h.fsf%40usa.net 09/2009:Atlas migrating from PUI to FLTK]&lt;br /&gt;
* [http://sourceforge.net/mailarchive/forum.php?thread_name=m18wbx49pu.fsf%40usa.net&amp;amp;forum_name=atlas-devel 01/2010: Migrating Atlas to FLTK (limitations)]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg25976.html 01/2010:GUI dialogs suck]&lt;br /&gt;
* [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg25991.html 01/2010:GUI dialogs suck]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73144</id>
		<title>Canvas MessageBox</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73144"/>
		<updated>2014-06-23T15:56:03Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Missing Navigation...&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.info(&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73143</id>
		<title>Canvas MessageBox</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73143"/>
		<updated>2014-06-23T15:51:27Z</updated>

		<summary type="html">&lt;p&gt;TheTom: First proper version. Examples, Severity levels...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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; style=&amp;quot;width:100%&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;
{| style=&amp;quot;width:100%&amp;quot;&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.info(&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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas-MessageBox-demo_warning_dont-show-again.png&amp;diff=73142</id>
		<title>File:Canvas-MessageBox-demo warning dont-show-again.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas-MessageBox-demo_warning_dont-show-again.png&amp;diff=73142"/>
		<updated>2014-06-23T15:42:50Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Canvas MessageBox showing a warning. The answer is saved if the user selects Don't show again.}}&lt;br /&gt;
|date=2014-06-23 17:42:11&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:TheTom|TheTom]]&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]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas-MessageBox-demo_question.png&amp;diff=73141</id>
		<title>File:Canvas-MessageBox-demo question.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas-MessageBox-demo_question.png&amp;diff=73141"/>
		<updated>2014-06-23T15:22:55Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Canvas question MessageBox.}}&lt;br /&gt;
|date=2014-06-23 17:21:11&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:TheTom|TheTom]]&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]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Canvas-MessageBox-demo_information.png&amp;diff=73140</id>
		<title>File:Canvas-MessageBox-demo information.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Canvas-MessageBox-demo_information.png&amp;diff=73140"/>
		<updated>2014-06-23T15:22:44Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Canvas information MessageBox.}}&lt;br /&gt;
|date=2014-06-23 17:21:05&lt;br /&gt;
|source={{own}}&lt;br /&gt;
|author=[[User:TheTom|TheTom]]&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]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73136</id>
		<title>Canvas MessageBox</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Canvas_MessageBox&amp;diff=73136"/>
		<updated>2014-06-23T14:49:41Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Created page with &amp;quot;{| class=&amp;quot;wikitable&amp;quot; |- ! Icon !! Icon Name !! Standard MessageBox !! Description |- | link= || &amp;lt;code&amp;gt;&amp;quot;dialog-question&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;syntaxhighlight...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&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;
| [[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(title, text, cb = nil, buttons = asd aasd asdasdas asda sdsa dsad sads adsad sasda dasd asd)&amp;lt;/syntaxhighlight&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Dialog-info.png|link=]] || &amp;quot;dialog-info&amp;quot; || '''canvas.MessageBox.question''' ||&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Dialog-warning.png|link=]] || &amp;quot;dialog-warning&amp;quot; || '''canvas.MessageBox.question''' ||&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Dialog-error.png|link=]] || &amp;quot;dialog-error&amp;quot; || '''canvas.MessageBox.question''' ||&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=73135</id>
		<title>Template:Canvas Navigation</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=73135"/>
		<updated>2014-06-23T14:36:59Z</updated>

		<summary type="html">&lt;p&gt;TheTom: Add MessageBox. Remove outdated Readme.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{forum|71|Canvas}}&lt;br /&gt;
{{sidebar&lt;br /&gt;
| name	= Canvas Navigation&lt;br /&gt;
| title = Canvas - the FlightGear 2D drawing API&lt;br /&gt;
| contentstyle= text-align: left;&lt;br /&gt;
&lt;br /&gt;
| content1 = &lt;br /&gt;
* [[Canvas]] - Main Page&lt;br /&gt;
* [[Canvas Development]]&lt;br /&gt;
* [[Canvas GUI]]&lt;br /&gt;
* [[Canvas Widgets]]&lt;br /&gt;
* [[Canvas Maps]]&lt;br /&gt;
&lt;br /&gt;
| heading2 = Frameworks&lt;br /&gt;
| content2 = &lt;br /&gt;
{{Canvas Frameworks|mode=navbar}}&lt;br /&gt;
* [[Canvas Glass Cockpit Efforts]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[How the Canvas subsystem works]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| heading3 = Tutorials&lt;br /&gt;
| content3 =&lt;br /&gt;
* [[Howto:Getting started with Canvas]]&lt;br /&gt;
* [[Howto:Adding a canvas to a GUI dialog]]&lt;br /&gt;
* [[Howto:Add a 2D canvas instrument to your aircraft]]&lt;br /&gt;
* [[Howto:Parsing 2D Instruments using the Canvas]]&lt;br /&gt;
* [[Howto:Creating fullscreen Canvas applications]]&lt;br /&gt;
* [[Howto:Use SVG inside a Canvas]]&lt;br /&gt;
* [[Howto:Canvas applications as Nasal submodules]]&lt;br /&gt;
* [[Howto:Using raster images and nested canvases]]&lt;br /&gt;
&amp;lt;!-- * [[Howto:Creating Canvas Widgets in Nasal]] --&amp;gt;&lt;br /&gt;
* [[Howto:Creating a Canvas graph widget]]&lt;br /&gt;
* [[Canvas HUD]]&lt;br /&gt;
| heading4 = Reference&lt;br /&gt;
| content4 =&lt;br /&gt;
* [[Canvas Element]]&lt;br /&gt;
** [[Canvas Group|Group]]&lt;br /&gt;
** [[Canvas Image|Image]]&lt;br /&gt;
** [[Canvas Map|Map]]&lt;br /&gt;
** [[Canvas Path|Path]]&lt;br /&gt;
** [[Canvas Text|Text]]&lt;br /&gt;
* [[Canvas Nasal API]]&lt;br /&gt;
** [[Canvas MessageBox|MessageBox]]&lt;br /&gt;
* [[Canvas - Event_Handling|Event Handling]]&lt;br /&gt;
| heading5 = Related&lt;br /&gt;
| content5 =&lt;br /&gt;
* [[Canvas Properties]]&lt;br /&gt;
* [[Unifying the 2D rendering backend via canvas]]&lt;br /&gt;
* [[FGCanvas]]&lt;br /&gt;
* [[Howto:Create a 2D drawing API for FlightGear]]&lt;br /&gt;
* [[Howto:Use a Camera View in an Instrument]]&lt;br /&gt;
&lt;br /&gt;
| heading6 = To be ported&lt;br /&gt;
| content6 = &lt;br /&gt;
* [[Navigation display]] {{Progressbar|70}}&lt;br /&gt;
* [[Map]] {{Progressbar|60}}&lt;br /&gt;
&lt;br /&gt;
| heading7 = Obsolete &amp;lt;br/&amp;gt;(deprecated by the Canvas)&lt;br /&gt;
| content7 =&lt;br /&gt;
* [[Complex Glass Cockpit Avionics]]&lt;br /&gt;
* [[OpenGL GUI RESOURCES]]&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;includeonly&amp;gt;{{main other|[[Category:Canvas]][[Category:Core development projects]]}}&lt;br /&gt;
{{howto other|[[Category:Canvas]][[Category:Howto]]}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
== Usage ==&lt;br /&gt;
Add the template to the top of the article text.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{Canvas Navigation}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding the template to an page in the main namespace, the article namespace, or the howto namespace will add [[:Category:Canvas]] to the page.  In addition [[:Category:Howto]] will be added to articles in the howto namespace, and [[:Category:Core development projects]] will be added to articles in the main namespace.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Navigation templates]]&lt;br /&gt;
[[Category:Canvas]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Dialog-info.png&amp;diff=73133</id>
		<title>File:Dialog-info.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Dialog-info.png&amp;diff=73133"/>
		<updated>2014-06-23T14:21:51Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Humanity info icon.}}&lt;br /&gt;
|date=2014-06-23 16:03:24&lt;br /&gt;
|source=https://launchpad.net/humanity&lt;br /&gt;
|author=Daniel Foré, K.Vishnoo Charan Reddy, Jonian Guveli&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{GPL}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox icons]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Dialog-error.png&amp;diff=73132</id>
		<title>File:Dialog-error.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Dialog-error.png&amp;diff=73132"/>
		<updated>2014-06-23T14:21:18Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Humanity error icon.}}&lt;br /&gt;
|date=2014-06-23 16:03:25&lt;br /&gt;
|source=https://launchpad.net/humanity&lt;br /&gt;
|author=Daniel Foré, K.Vishnoo Charan Reddy, Jonian Guveli&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{GPL}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox icons]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Dialog-question.png&amp;diff=73131</id>
		<title>File:Dialog-question.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Dialog-question.png&amp;diff=73131"/>
		<updated>2014-06-23T14:21:11Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Humanity question icon.}}&lt;br /&gt;
|date=2014-06-23 16:03:24&lt;br /&gt;
|source=https://launchpad.net/humanity&lt;br /&gt;
|author=Daniel Foré, K.Vishnoo Charan Reddy, Jonian Guveli&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{GPL}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox icons]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Dialog-error.png&amp;diff=73129</id>
		<title>File:Dialog-error.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Dialog-error.png&amp;diff=73129"/>
		<updated>2014-06-23T14:18:56Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Humanity error icon.}}&lt;br /&gt;
|date=2014-06-23 16:03:25&lt;br /&gt;
|source=https://launchpad.net/humanity&lt;br /&gt;
|author=Daniel Foré, K.Vishnoo Charan Reddy, Jonian Guveli&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{subst:uwl}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox icons]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Dialog-question.png&amp;diff=73128</id>
		<title>File:Dialog-question.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Dialog-question.png&amp;diff=73128"/>
		<updated>2014-06-23T14:18:39Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Humanity question icon.}}&lt;br /&gt;
|date=2014-06-23 16:03:24&lt;br /&gt;
|source=https://launchpad.net/humanity&lt;br /&gt;
|author=Daniel Foré, K.Vishnoo Charan Reddy, Jonian Guveli&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{subst:uwl}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox icons]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=File:Dialog-info.png&amp;diff=73127</id>
		<title>File:Dialog-info.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=File:Dialog-info.png&amp;diff=73127"/>
		<updated>2014-06-23T14:18:27Z</updated>

		<summary type="html">&lt;p&gt;TheTom: User created page with UploadWizard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=={{int:filedesc}}==&lt;br /&gt;
{{Information&lt;br /&gt;
|description={{en|1=Humanity info icon.}}&lt;br /&gt;
|date=2014-06-23 16:03:24&lt;br /&gt;
|source=https://launchpad.net/humanity&lt;br /&gt;
|author=Daniel Foré, K.Vishnoo Charan Reddy, Jonian Guveli&lt;br /&gt;
|permission=&lt;br /&gt;
|other_versions=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=={{int:license-header}}==&lt;br /&gt;
{{subst:uwl}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Messagebox icons]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=List_of_Nasal_extension_functions&amp;diff=72953</id>
		<title>List of Nasal extension functions</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=List_of_Nasal_extension_functions&amp;diff=72953"/>
		<updated>2014-06-20T22:45:37Z</updated>

		<summary type="html">&lt;p&gt;TheTom: md5&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Incomplete|The accuracy of this article or section may be compromised due to recent changes in the source code, please help us update this article by incorporating the [http://mapserver.flightgear.org/git/?p=flightgear;a=blob;f=src/Scripting/NasalSys.cxx#l707 latest extension functions]}}&lt;br /&gt;
{{Template:Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Nasal Core Library ==&lt;br /&gt;
&lt;br /&gt;
For a list of functions implemented in C, that are available to Nasal implementations in general, see [http://plausible.org/nasal/lib.html]. Note that only the &amp;lt;tt&amp;gt;thread&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;io&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;math&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;utf8&amp;lt;/tt&amp;gt; libraries are currently included in SimGear.&lt;br /&gt;
&lt;br /&gt;
== FlightGear's Extension Functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see [[$FG_ROOT]]/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
    if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
        setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
}, 1, 0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html |title=multiplayer generic properties |date=8 December 2007 |author=Melchior Franz}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC)&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html |title=Calling FG functions via network interface |author=Melchior Franz |date=2 January 2006}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html |title=Calling FG functions via network interface |author=Melchior Franz |date=7 January 2006}}&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see [[Bindings]] for a full list of available items (since they are most often used in bindings for input devices). The first argument is the name of the command (e.g. &amp;quot;property-interpolate&amp;quot;) and the second is a props.Node object or its ghost which is the &amp;quot;argument&amp;quot; to the fgcommand. (This ensures that fgcommands are universal since props.Node/SGPropertyNode objects can really be accessed from anywhere in FlightGear.) Each fgcommand returns 1 if it succeeded or 0 if it failed.&lt;br /&gt;
&lt;br /&gt;
The profiling related fgcommands '''profiler-start''' and '''profiler-stop''' are documented at [[Built-in Profiler]].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;addcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Add a fgcommand which can be used like a regular fgcommand (global scope, etc.). First argument is the name, second is the function to run. Note that this fgcommand will always return true! Inside the callback/function one can use either cmdarg() to retrieve the arguments or use the first argument passed to the function (since they will be the same).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removecommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
As you can guess, there's also a removecommand() function which will remove '''any''' command – even those implemented in C++! As such it can be very dangerous and remove core functionality, so use with caution.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;logprint()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Similar, but the first argument is reserved for number specifying the priority (i.e. matching a sgDebugPriority object: 1 for bulk, 2 for debug, 3 for info, and 4 for warn). Also see &amp;lt;tt&amp;gt;printlog()&amp;lt;/tt&amp;gt; in globals.nas: it does essentially the same but with named levels (&amp;quot;bulk&amp;quot;, etc.). (The latter relies on &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt;, however, and does not make use of the sophistication of &amp;lt;tt&amp;gt;sglog&amp;lt;/tt&amp;gt; in dealing with source file and line number.)&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized to a value yet. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
getprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Several arguments will be added together to produce a path, with numeric arguments specifying indexes (as of FlightGear 3.1), 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 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;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
for (var i=0; i &amp;lt; 10; i += 1) {&lt;br /&gt;
    print(&amp;quot;View &amp;quot;, i, &amp;quot;'s name is: &amp;quot;, getprop(&amp;quot;/sim/view&amp;quot;, i, &amp;quot;name&amp;quot;));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Returns 1 on success or 0 if the property could not be set (i.e. was read-only).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, like getprop() above. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; has to be erased using the props namespace helper, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
props.globals.getNode(&amp;quot;foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;interpolate()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Give the value from a value or a source node to a destination node in given time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
interpolate(&amp;lt;path&amp;gt;, &amp;lt;value&amp;gt;, &amp;lt;time&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
interpolate(&amp;quot;controls/switches/nav-lights-pos&amp;quot;, 1, 0.25); # After 25ms, nav-lights-pos = 1&lt;br /&gt;
interpolate(&amp;quot;controls/gear/brake-left-pos&amp;quot;, getprop(&amp;quot;controls/gear/brake-left&amp;quot;), 1); # After 1s, brake-left-pos = brake-left&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
myarg2=432;&lt;br /&gt;
settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# simulation time example&lt;br /&gt;
var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
settimer(copilot_annoyed, 10);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# real time example&lt;br /&gt;
var popdown = func ( tipArg ) { &lt;br /&gt;
    fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
&lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
&lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
&lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Nasal scripting language#settimer loops|More information about using the settimer function to create loops.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;maketimer()&amp;lt;/tt&amp;gt; (2.11+) ===&lt;br /&gt;
&lt;br /&gt;
As of 2.11, there is a new API for making a timer that allows more control over what happens in a timer – as opposed to setting one and forgetting about it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var timer = maketimer(&amp;lt;interval&amp;gt;, &amp;lt;function&amp;gt;)&lt;br /&gt;
var timer = maketimer(&amp;lt;interval&amp;gt;, &amp;lt;self&amp;gt;, &amp;lt;function&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
timer.start()&lt;br /&gt;
timer.stop()&lt;br /&gt;
timer.restart(&amp;lt;interval&amp;gt;)&lt;br /&gt;
timer.singleShot [read/write]&lt;br /&gt;
timer.isRunning [read-only]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# create timer with 1 second interval&lt;br /&gt;
var timer = maketimer(1.0, func { &lt;br /&gt;
 print('timer called'); &lt;br /&gt;
 }&lt;br /&gt;
);&lt;br /&gt;
# start the timer (with 1 second inverval)&lt;br /&gt;
timer.start();&lt;br /&gt;
# restart timer with 4 second interval&lt;br /&gt;
timer.restart(4);&lt;br /&gt;
&lt;br /&gt;
# fire one single time in 6 seconds&lt;br /&gt;
timer.singleShot = 1;&lt;br /&gt;
timer.restart(6);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var Tooltip = {&lt;br /&gt;
  new: func&lt;br /&gt;
  {&lt;br /&gt;
    var m = {&lt;br /&gt;
      parents: [Tooltip]&lt;br /&gt;
    }&lt;br /&gt;
    m._hideTimer = maketimer(1.0, m, Tooltip._hideTimeout);&lt;br /&gt;
    m._hideTimer.singleShot = 1;&lt;br /&gt;
&lt;br /&gt;
   return m;&lt;br /&gt;
  },&lt;br /&gt;
  run: func&lt;br /&gt;
  {&lt;br /&gt;
    if( !me._hideTimer.isRunning )&lt;br /&gt;
      me._hideTimer.start();&lt;br /&gt;
  }&lt;br /&gt;
  _hideTimeout: func&lt;br /&gt;
  {&lt;br /&gt;
    print('_hideTimeout');&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
var info = geodinfo(lat, lon);&lt;br /&gt;
&lt;br /&gt;
if (info != nil) {&lt;br /&gt;
    print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
    if (info[1] != nil)&lt;br /&gt;
        print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
debug.dump(geodinfo(lat, lon));&lt;br /&gt;
&lt;br /&gt;
# outputs&lt;br /&gt;
[ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
rolling_friction : 1.5 } ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://forum.flightgear.org/viewtopic.php?f=4&amp;amp;p=135044#p135044 forum discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
{ lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the airport, and a hash with runways, each of which consists of lat/lon/length/width/heading/threshold[12]/stopway[12]. Only one side of each runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
=== Positioned Object Queries ===&lt;br /&gt;
&lt;br /&gt;
Several functions exist to query the navigation database of 'positioned' objects, i.e items with a defined location in the simulation world. (These objects all inherit from &amp;lt;tt&amp;gt;FGPositioned&amp;lt;/tt&amp;gt; internally). The functions return either one, or a vector, of wrapped Nasal objects. These are efficient, but unlike a hash they cannot simply be &amp;lt;tt&amp;gt;debug.dump()&amp;lt;/tt&amp;gt; to view all their members and methods.&lt;br /&gt;
&lt;br /&gt;
When the query functions take a position, the default value is the current aircraft location. An alternative location can be supplied by passing two number (lat, lon), a Geo.Coord object, or any positioned object or waypoint retrieved from another query.&lt;br /&gt;
&lt;br /&gt;
;findAirportsWithinRange()&lt;br /&gt;
: Find all airports within a specified range (in NM) of the current position or explicit position&lt;br /&gt;
;findAirportsByICAO()&lt;br /&gt;
: Find airports matching a complete or partial ICAO code. In particular this can search for all airports starting with a two or three letter prefix.&lt;br /&gt;
;navinfo()&lt;br /&gt;
: Return a list of navaids near a location by type and ident. Type should be 'fix', 'vor', 'ndb', 'dme'&lt;br /&gt;
;findNavaidsWithinRange()&lt;br /&gt;
: Search for navaids within a particular range (in NM), optionally limited by type. This provides a 'find the closest ILS' function&lt;br /&gt;
;findNavaidByFrequency()&lt;br /&gt;
: find the closest navaid (of a particular type) matching an exact frequency&lt;br /&gt;
;findNavaidsByFrequency()&lt;br /&gt;
: find all the navaids matching a particular frequency and optional type, sorted by distance from the search location.&lt;br /&gt;
&lt;br /&gt;
All positioned objects returned by the above methods have the following members:&lt;br /&gt;
;id&lt;br /&gt;
: Identifier - ICAO code for airports, published ident for navaids and fixes&lt;br /&gt;
;lon&lt;br /&gt;
: degrees longitude&lt;br /&gt;
;lat&lt;br /&gt;
: degrees latitude&lt;br /&gt;
&lt;br /&gt;
Depending on type, the following members are also available:&lt;br /&gt;
;name&lt;br /&gt;
: the full name of the airport or navaid if one is defined&lt;br /&gt;
;elevation&lt;br /&gt;
: the ASL elevation of the object in feet&lt;br /&gt;
&lt;br /&gt;
For navaids, the following members are available:&lt;br /&gt;
;frequency&lt;br /&gt;
: the navaid frequency in kHz&lt;br /&gt;
;type&lt;br /&gt;
: the navaid type as a string: vor, dme, loc, ils, ndb&lt;br /&gt;
;course&lt;br /&gt;
: the degrees course associated with the navaid, for localiser and ILS stations&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;history() &amp;lt;/tt&amp;gt; (3.1+) ===&lt;br /&gt;
&lt;br /&gt;
Function to expose flight history as aircraft.history()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hist = aircraft.history();&lt;br /&gt;
&lt;br /&gt;
# get history of aircraft position/orientation collapsing&lt;br /&gt;
# nodes with a distance smaller than the given minimum&lt;br /&gt;
# edge legth&lt;br /&gt;
debug.dump( hist.pathForHistory(&amp;lt;minimum-edge-length-meter&amp;gt;) );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;flightplan()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Function to retrieve the active flight-plan object, or load a flight plan from a file path.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var fp = flightplan();&lt;br /&gt;
var fp = flightplan('/some/path/to/a/flightplan.xml');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In advance of converting the Map and NavDisplay to use the [[Canvas]], James has improved the &amp;quot;flightplan()&amp;quot; extension function of the [[Nasal]] scripting interpreter to expose the full route-path vector for each flight plan leg as a vector on the leg.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var fp = flightplan();&lt;br /&gt;
for (var i=0; i&amp;lt;fp.getPlanSize(); i += 1)&lt;br /&gt;
{&lt;br /&gt;
  var leg = fp.getWP(i);&lt;br /&gt;
  debug.dump(leg.path());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
#benchmarking example:&lt;br /&gt;
var start = systime();&lt;br /&gt;
how_fast_am_I(123);&lt;br /&gt;
var end = systime();&lt;br /&gt;
print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
&lt;br /&gt;
# outputs&lt;br /&gt;
lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
&lt;br /&gt;
# outputs&lt;br /&gt;
x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
&amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
&amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
&amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var start = func(name, attr) {&lt;br /&gt;
    print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
    foreach (var a; keys(attr))&lt;br /&gt;
        print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
}&lt;br /&gt;
var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;resolvepath()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
SimGear features its own [[Resolving Paths|path resolving framework]] that takes a relative path and returns an absolute path, checking from base directories such as [[$FG_ROOT]], [[$FG_HOME]], [[$FG_AIRCRAFT]], and the current aircraft directory (&amp;lt;tt&amp;gt;/sim/aircraft-dir&amp;lt;/tt&amp;gt;). This function in Nasal takes a path string and returns the absolute path or an empty string if the path couldn't be resolved.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var guess_path = func(path...) {&lt;br /&gt;
    var path_concat = string.join(path, &amp;quot;/&amp;quot;);&lt;br /&gt;
    var file_path = resolvepath(path_concat);&lt;br /&gt;
    if (file_path == &amp;quot;&amp;quot;) die(&amp;quot;Path not found: &amp;quot;~path_concat);&lt;br /&gt;
    return file_path;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== HTTP module (2.99+) ===&lt;br /&gt;
&lt;br /&gt;
Get remote data using the HTTP.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;http.load()&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Load resource identified by its URL into memory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var request = http.load(&amp;lt;url&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
http.load(&amp;quot;http://example.com/test.txt&amp;quot;)&lt;br /&gt;
    .done(func(r) print(&amp;quot;Got response: &amp;quot; ~ r.response));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;http.save()&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Save resource to a local file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var request = http.save(&amp;lt;url&amp;gt;, &amp;lt;file_path&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
http.save(&amp;quot;http://example.com/test.png&amp;quot;, getprop('/sim/fg-home') ~ '/cache/test.png')&lt;br /&gt;
    .fail(func print(&amp;quot;Download failed!&amp;quot;))&lt;br /&gt;
    .done(func(r) print(&amp;quot;Finished request with status: &amp;quot; ~ r.status ~ &amp;quot; &amp;quot; ~ r.reason))&lt;br /&gt;
    .always(func print(&amp;quot;Request complete (fail or success)&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;rand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Return a random number as generated by &amp;lt;tt&amp;gt;sg_random&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;srand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Seed the random number generator based upon the current time. Returns 0.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;md5()&amp;lt;/tt&amp;gt; (3.1+) ===&lt;br /&gt;
&lt;br /&gt;
Get the md5 hash of a string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hash = md5(&amp;lt;str&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;abort()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Wrapper for the C++ library abort() function – i.e. it just aborts the process without regard to what's happening. For exiting (gracefully) from FlightGear use the fgcommand &amp;quot;exit&amp;quot; instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=71715</id>
		<title>User:TheTom</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=71715"/>
		<updated>2014-05-21T13:04:33Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &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) {{Not done}}&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=List_of_Nasal_extension_functions&amp;diff=70950</id>
		<title>List of Nasal extension functions</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=List_of_Nasal_extension_functions&amp;diff=70950"/>
		<updated>2014-05-10T22:44:44Z</updated>

		<summary type="html">&lt;p&gt;TheTom: aircraft.history: describe parameter&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Incomplete|The accuracy of this article or section may be compromised due to recent changes in the source code, please help us update this article by incorporating the [http://mapserver.flightgear.org/git/?p=flightgear;a=blob;f=src/Scripting/NasalSys.cxx#l707 latest extension functions]}}&lt;br /&gt;
{{Template:Nasal Navigation}}&lt;br /&gt;
&lt;br /&gt;
== Nasal Core Library ==&lt;br /&gt;
&lt;br /&gt;
For a list of functions implemented in C, that are available to Nasal implementations in general, see [http://plausible.org/nasal/lib.html]. Note that only the &amp;lt;tt&amp;gt;thread&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;io&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;math&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;utf8&amp;lt;/tt&amp;gt; libraries are currently included in SimGear.&lt;br /&gt;
&lt;br /&gt;
== FlightGear's Extension Functions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;cmdarg()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
cmdarg() is a mechanism to pass arguments to a nasal script (wrapped in properties) instead of &amp;quot;normal&amp;quot; function parameters. Note that cmdarg() should be primarily used in Nasal code embedded in XML files and should be considered depreciated otherwise (see [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg18361.html]).&lt;br /&gt;
&lt;br /&gt;
cmdarg() will keep working in (joystick) XML-'''bindings''' and on the top-level of embedded Nasal scripts (i.e. dialog and animation XML files).&lt;br /&gt;
&lt;br /&gt;
As such, the cmdarg() function is primarily used for listener callbacks declared in XML markup, cmdarg() returns the listened-to property as props.Node object, so you can use it with all its methods (see [[$FG_ROOT]]/Nasal/props.nas) for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
print(cmdarg().getPath(), &amp;quot; has been changed to &amp;quot;, cmdarg().getValue())&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The cmdarg() function avoids that you have to type the exact same path twice (once here and once in the setlistener() command) and it makes clear that this is the listened to property. Also, you can use all the nice props.Node methods on cmdarg() directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
setlistener(&amp;quot;/gear/launchbar/state&amp;quot;, func {&lt;br /&gt;
    if (cmdarg().getValue() == &amp;quot;Engaged&amp;quot;)&lt;br /&gt;
        setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Engaged!&amp;quot;);&lt;br /&gt;
}, 1, 0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use of cmdarg() outside of XML-bindings won't cause an error, but (still) return the last cmdarg() property. This just won't be the listened-to property anymore, but whatever the last legitimate cmdarg() user set. Most of the time it will be the property root of a joystick binding.&lt;br /&gt;
&lt;br /&gt;
Don't make any assumptions and use cmdarg() only in one of these cases:&lt;br /&gt;
&lt;br /&gt;
* binding: returns root of this binding's property branch. Needed for accessing an axis' value:         cmdarg().getNode(&amp;quot;setting&amp;quot;).getValue()&lt;br /&gt;
&lt;br /&gt;
* dialog xml files: returns root of that file's property branch in memory. This can be used to let embedded Nasal change the dialog (e.g. clear and build lists) before the final layout is decided&lt;br /&gt;
&lt;br /&gt;
* animation xml files: returns root of this model's place in /ai/models/ when used as AI/MP model. Examples:       /ai/models/multiplayer[3], /ai/models/tanker[1], etc.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg14164.html |title=multiplayer generic properties |date=8 December 2007 |author=Melchior Franz}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* AI aircraft XML files&lt;br /&gt;
&lt;br /&gt;
* remotely invoking Nasal code by setting properties using the built-in telnet daemon (RPC)&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00150.html |title=Calling FG functions via network interface |author=Melchior Franz |date=2 January 2006}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg00336.html |title=Calling FG functions via network interface |author=Melchior Franz |date=7 January 2006}}&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''In all cases, the cmdarg() call must not be delayed until later using settimer() or setlistener(). Because later it'll again return some unrelated property!&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;fgcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Runs an internal &amp;quot;fgcommand&amp;quot;, see [[Bindings]] for a full list of available items (since they are most often used in bindings for input devices). The first argument is the name of the command (e.g. &amp;quot;property-interpolate&amp;quot;) and the second is a props.Node object or its ghost which is the &amp;quot;argument&amp;quot; to the fgcommand. (This ensures that fgcommands are universal since props.Node/SGPropertyNode objects can really be accessed from anywhere in FlightGear.) Each fgcommand returns 1 if it succeeded or 0 if it failed.&lt;br /&gt;
&lt;br /&gt;
The profiling related fgcommands '''profiler-start''' and '''profiler-stop''' are documented at [[Built-in Profiler]].&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;addcommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Add a fgcommand which can be used like a regular fgcommand (global scope, etc.). First argument is the name, second is the function to run. Note that this fgcommand will always return true! Inside the callback/function one can use either cmdarg() to retrieve the arguments or use the first argument passed to the function (since they will be the same).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removecommand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
As you can guess, there's also a removecommand() function which will remove '''any''' command – even those implemented in C++! As such it can be very dangerous and remove core functionality, so use with caution.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;logprint()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Similar, but the first argument is reserved for number specifying the priority (i.e. matching a sgDebugPriority object: 1 for bulk, 2 for debug, 3 for info, and 4 for warn). Also see &amp;lt;tt&amp;gt;printlog()&amp;lt;/tt&amp;gt; in globals.nas: it does essentially the same but with named levels (&amp;quot;bulk&amp;quot;, etc.). (The latter relies on &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt;, however, and does not make use of the sophistication of &amp;lt;tt&amp;gt;sglog&amp;lt;/tt&amp;gt; in dealing with source file and line number.)&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized to a value yet. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
getprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Several arguments will be added together to produce a path, with numeric arguments specifying indexes (as of FlightGear 3.1), 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 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;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
for (var i=0; i &amp;lt; 10; i += 1) {&lt;br /&gt;
    print(&amp;quot;View &amp;quot;, i, &amp;quot;'s name is: &amp;quot;, getprop(&amp;quot;/sim/view&amp;quot;, i, &amp;quot;name&amp;quot;));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Returns 1 on success or 0 if the property could not be set (i.e. was read-only).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string, like getprop() above. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
setprop(&amp;quot;/controls&amp;quot;, &amp;quot;engines/engine[0]&amp;quot;, &amp;quot;reverser&amp;quot;, 1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Erasing a property from the property tree''': a property that has been created, for example through &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; has to be erased using the props namespace helper, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
props.globals.getNode(&amp;quot;foo/bar&amp;quot;).remove(); 		# take out the complete node&lt;br /&gt;
props.globals.getNode(&amp;quot;foo&amp;quot;).removeChild(&amp;quot;bar&amp;quot;); 	# take out a certain child node&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;interpolate()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Give the value from a value or a source node to a destination node in given time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
interpolate(&amp;lt;path&amp;gt;, &amp;lt;value&amp;gt;, &amp;lt;time&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
interpolate(&amp;quot;controls/switches/nav-lights-pos&amp;quot;, 1, 0.25); # After 25ms, nav-lights-pos = 1&lt;br /&gt;
interpolate(&amp;quot;controls/gear/brake-left-pos&amp;quot;, getprop(&amp;quot;controls/gear/brake-left&amp;quot;), 1); # After 1s, brake-left-pos = brake-left&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation time (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first object is a function object (ie, &amp;quot;func { ... }&amp;quot;).  Note that this is different from a function call (ie, &amp;quot;func ( ... )&amp;quot;). If you don't understand what this means, just remember to always enclose the first argument in any call to settimer with the word &amp;quot;func&amp;quot; and braces &amp;quot;{ }&amp;quot;, and it will always work. For instance, if you want print the words &amp;quot;My result&amp;quot; in five seconds, use this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
settimer ( func { print ( &amp;quot;My result&amp;quot;); }, 5);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Inside the braces of the func object you can put any valid Nasal code, including a function call.  In fact, if you want to call a function with certain values as arguments, the way to do it is to turn it into a function object by enclosing it with a func{}, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
myarg1=&amp;quot;My favorite string&amp;quot;;&lt;br /&gt;
myarg2=432;&lt;br /&gt;
settimer ( func { myfunction ( myarg1, myarg2); }, 25);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# simulation time example&lt;br /&gt;
var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
settimer(copilot_annoyed, 10);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# real time example&lt;br /&gt;
var popdown = func ( tipArg ) { &lt;br /&gt;
    fgcommand(&amp;quot;dialog-close&amp;quot;, tipArg); &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
var selfStatusPopupTip = func (label, delay = 10, override = nil) {	&lt;br /&gt;
    var tmpl = props.Node.new({&lt;br /&gt;
            name : &amp;quot;PopTipSelf&amp;quot;, modal : 0, layout : &amp;quot;hbox&amp;quot;,&lt;br /&gt;
            y: 140,&lt;br /&gt;
            text : { label : label, padding : 6 }&lt;br /&gt;
    });&lt;br /&gt;
    if (override != nil) tmpl.setValues(override);&lt;br /&gt;
&lt;br /&gt;
    popdown(tipArgSelf);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-new&amp;quot;, tmpl);&lt;br /&gt;
    fgcommand(&amp;quot;dialog-show&amp;quot;, tipArgSelf);&lt;br /&gt;
&lt;br /&gt;
    currTimerSelf += 1;&lt;br /&gt;
    var thisTimerSelf = currTimerSelf;&lt;br /&gt;
&lt;br /&gt;
    # Final argument 1 is a flag to use &amp;quot;real&amp;quot; time, not simulated time&lt;br /&gt;
    settimer(func { if(currTimerSelf == thisTimerSelf) { popdown(tipArgSelf) } }, delay, 1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Nasal scripting language#settimer loops|More information about using the settimer function to create loops.]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;maketimer()&amp;lt;/tt&amp;gt; (v. 2.11+) ===&lt;br /&gt;
&lt;br /&gt;
As of 2.11, there is a new API for making a timer that allows more control over what happens in a timer – as opposed to setting one and forgetting about it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var timer = maketimer(&amp;lt;interval&amp;gt;, &amp;lt;function&amp;gt;)&lt;br /&gt;
var timer = maketimer(&amp;lt;interval&amp;gt;, &amp;lt;self&amp;gt;, &amp;lt;function&amp;gt;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
timer.start()&lt;br /&gt;
timer.stop()&lt;br /&gt;
timer.restart(&amp;lt;interval&amp;gt;)&lt;br /&gt;
timer.singleShot [read/write]&lt;br /&gt;
timer.isRunning [read-only]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
# create timer with 1 second interval&lt;br /&gt;
var timer = maketimer(1.0, func { &lt;br /&gt;
 print('timer called'); &lt;br /&gt;
 }&lt;br /&gt;
);&lt;br /&gt;
# start the timer (with 1 second inverval)&lt;br /&gt;
timer.start();&lt;br /&gt;
# restart timer with 4 second interval&lt;br /&gt;
timer.restart(4);&lt;br /&gt;
&lt;br /&gt;
# fire one single time in 6 seconds&lt;br /&gt;
timer.singleShot = 1;&lt;br /&gt;
timer.restart(6);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var Tooltip = {&lt;br /&gt;
  new: func&lt;br /&gt;
  {&lt;br /&gt;
    var m = {&lt;br /&gt;
      parents: [Tooltip]&lt;br /&gt;
    }&lt;br /&gt;
    m._hideTimer = maketimer(1.0, m, Tooltip._hideTimeout);&lt;br /&gt;
    m._hideTimer.singleShot = 1;&lt;br /&gt;
&lt;br /&gt;
   return m;&lt;br /&gt;
  },&lt;br /&gt;
  run: func&lt;br /&gt;
  {&lt;br /&gt;
    if( !me._hideTimer.isRunning )&lt;br /&gt;
      me._hideTimer.start();&lt;br /&gt;
  }&lt;br /&gt;
  _hideTimeout: func&lt;br /&gt;
  {&lt;br /&gt;
    print('_hideTimeout');&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot or the scenery tile is not loaded.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
var info = geodinfo(lat, lon);&lt;br /&gt;
&lt;br /&gt;
if (info != nil) {&lt;br /&gt;
    print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
    if (info[1] != nil)&lt;br /&gt;
        print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
debug.dump(geodinfo(lat, lon));&lt;br /&gt;
&lt;br /&gt;
# outputs&lt;br /&gt;
[ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
rolling_friction : 1.5 } ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that geodinfo is a *very* CPU intensive operation, particularly in FG 2.4.0 and earlier, so use sparingly ([http://forum.flightgear.org/viewtopic.php?f=4&amp;amp;p=135044#p135044 forum discussion here]).&lt;br /&gt;
&lt;br /&gt;
=== airportinfo() ===&lt;br /&gt;
Function for retrieval of airport/runway information.&lt;br /&gt;
Usage:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var apt = airportinfo(&amp;quot;KHAF&amp;quot;);   # get info about KHAF&lt;br /&gt;
var apt = airportinfo(lat, lon); # get info about apt closest to lat/lon&lt;br /&gt;
var apt = airportinfo();         # get info about apt closest to aircraft  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The command debug.dump(airportinfo(&amp;quot;KHAF&amp;quot;)) outputs this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
{ lon : -122.4962626410256, lat : 37.51343502564102, has_metar : 0,&lt;br /&gt;
  runways : { 12 : { stopway2 : 0, threshold1 : 232.5624,&lt;br /&gt;
  lon : -122.5010889999999, lat : 37.513831, stopway1 : 0, width : 45.72,&lt;br /&gt;
  threshold2 : 232.5624, heading : 138.1199999999999, length : 1523.0856 } },&lt;br /&gt;
  elevation : 20.42159999999999, id : &amp;quot;KHAF&amp;quot;, name : &amp;quot;Half Moon Bay&amp;quot; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That is: a hash with elements lat/lon/elev/id/name/has_metar for the airport, and a hash with runways, each of which consists of lat/lon/length/width/heading/threshold[12]/stopway[12]. Only one side of each runway is listed -- the other can easily be deduced.&lt;br /&gt;
&lt;br /&gt;
=== Positioned Object Queries ===&lt;br /&gt;
&lt;br /&gt;
Several functions exist to query the navigation database of 'positioned' objects, i.e items with a defined location in the simulation world. (These objects all inherit from &amp;lt;tt&amp;gt;FGPositioned&amp;lt;/tt&amp;gt; internally). The functions return either one, or a vector, of wrapped Nasal objects. These are efficient, but unlike a hash they cannot simply be &amp;lt;tt&amp;gt;debug.dump()&amp;lt;/tt&amp;gt; to view all their members and methods.&lt;br /&gt;
&lt;br /&gt;
When the query functions take a position, the default value is the current aircraft location. An alternative location can be supplied by passing two number (lat, lon), a Geo.Coord object, or any positioned object or waypoint retrieved from another query.&lt;br /&gt;
&lt;br /&gt;
;findAirportsWithinRange()&lt;br /&gt;
: Find all airports within a specified range (in NM) of the current position or explicit position&lt;br /&gt;
;findAirportsByICAO()&lt;br /&gt;
: Find airports matching a complete or partial ICAO code. In particular this can search for all airports starting with a two or three letter prefix.&lt;br /&gt;
;navinfo()&lt;br /&gt;
: Return a list of navaids near a location by type and ident. Type should be 'fix', 'vor', 'ndb', 'dme'&lt;br /&gt;
;findNavaidsWithinRange()&lt;br /&gt;
: Search for navaids within a particular range (in NM), optionally limited by type. This provides a 'find the closest ILS' function&lt;br /&gt;
;findNavaidByFrequency()&lt;br /&gt;
: find the closest navaid (of a particular type) matching an exact frequency&lt;br /&gt;
;findNavaidsByFrequency()&lt;br /&gt;
: find all the navaids matching a particular frequency and optional type, sorted by distance from the search location.&lt;br /&gt;
&lt;br /&gt;
All positioned objects returned by the above methods have the following members:&lt;br /&gt;
;id&lt;br /&gt;
: Identifier - ICAO code for airports, published ident for navaids and fixes&lt;br /&gt;
;lon&lt;br /&gt;
: degrees longitude&lt;br /&gt;
;lat&lt;br /&gt;
: degrees latitude&lt;br /&gt;
&lt;br /&gt;
Depending on type, the following members are also available:&lt;br /&gt;
;name&lt;br /&gt;
: the full name of the airport or navaid if one is defined&lt;br /&gt;
;elevation&lt;br /&gt;
: the ASL elevation of the object in feet&lt;br /&gt;
&lt;br /&gt;
For navaids, the following members are available:&lt;br /&gt;
;frequency&lt;br /&gt;
: the navaid frequency in kHz&lt;br /&gt;
;type&lt;br /&gt;
: the navaid type as a string: vor, dme, loc, ils, ndb&lt;br /&gt;
;course&lt;br /&gt;
: the degrees course associated with the navaid, for localiser and ILS stations&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;history() &amp;lt;/tt&amp;gt; (3.1+) ===&lt;br /&gt;
&lt;br /&gt;
Function to expose flight history as aircraft.history()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var hist = aircraft.history();&lt;br /&gt;
&lt;br /&gt;
# get history of aircraft position/orientation collapsing&lt;br /&gt;
# nodes with a distance smaller than the given minimum&lt;br /&gt;
# edge legth&lt;br /&gt;
debug.dump( hist.pathForHistory(&amp;lt;minimum-edge-length-meter&amp;gt;) );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;flightplan()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Function to retrieve the active flight-plan object, or load a flight plan from a file path.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var fp = flightplan();&lt;br /&gt;
var fp = flightplan('/some/path/to/a/flightplan.xml');&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In advance of converting the Map and NavDisplay to use the [[Canvas]], James has improved the &amp;quot;flightplan()&amp;quot; extension function of the [[Nasal]] scripting interpreter to expose the full route-path vector for each flight plan leg as a vector on the leg.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var fp = flightplan();&lt;br /&gt;
for (var i=0; i&amp;lt;fp.getPlanSize(); i += 1)&lt;br /&gt;
{&lt;br /&gt;
  var leg = fp.getWP(i);&lt;br /&gt;
  debug.dump(leg.path());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
#benchmarking example:&lt;br /&gt;
var start = systime();&lt;br /&gt;
how_fast_am_I(123);&lt;br /&gt;
var end = systime();&lt;br /&gt;
print(&amp;quot;took &amp;quot;, end - start, &amp;quot; seconds&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
&lt;br /&gt;
# outputs&lt;br /&gt;
lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
&lt;br /&gt;
# outputs&lt;br /&gt;
x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in [http://expat.sourceforge.net/ Expat XML parser]. It takes up to five arguments. The first is a mandatory absolute path to an XML file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
&amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
&amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
&amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var start = func(name, attr) {&lt;br /&gt;
    print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
    foreach (var a; keys(attr))&lt;br /&gt;
        print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
}&lt;br /&gt;
var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;resolvepath()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
SimGear features its own [[Resolving Paths|path resolving framework]] that takes a relative path and returns an absolute path, checking from base directories such as [[$FG_ROOT]], [[$FG_HOME]], [[$FG_AIRCRAFT]], and the current aircraft directory (&amp;lt;tt&amp;gt;/sim/aircraft-dir&amp;lt;/tt&amp;gt;). This function in Nasal takes a path string and returns the absolute path or an empty string if the path couldn't be resolved.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var guess_path = func(path...) {&lt;br /&gt;
    var path_concat = string.join(path, &amp;quot;/&amp;quot;);&lt;br /&gt;
    var file_path = resolvepath(path_concat);&lt;br /&gt;
    if (file_path == &amp;quot;&amp;quot;) die(&amp;quot;Path not found: &amp;quot;~path_concat);&lt;br /&gt;
    return file_path;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== HTTP module (v. 2.99+) ===&lt;br /&gt;
&lt;br /&gt;
Get remote data using the HTTP.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;http.load()&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Load resource identified by its URL into memory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var request = http.load(&amp;lt;url&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
http.load(&amp;quot;http://example.com/test.txt&amp;quot;)&lt;br /&gt;
    .done(func(r) print(&amp;quot;Got response: &amp;quot; ~ r.response));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;tt&amp;gt;http.save()&amp;lt;/tt&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
Save resource to a local file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
var request = http.save(&amp;lt;url&amp;gt;, &amp;lt;file_path&amp;gt;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;nasal&amp;quot;&amp;gt;&lt;br /&gt;
http.save(&amp;quot;http://example.com/test.png&amp;quot;, getprop('/sim/fg-home') ~ '/cache/test.png')&lt;br /&gt;
    .fail(func print(&amp;quot;Download failed!&amp;quot;))&lt;br /&gt;
    .done(func(r) print(&amp;quot;Finished request with status: &amp;quot; ~ r.status ~ &amp;quot; &amp;quot; ~ r.reason))&lt;br /&gt;
    .always(func print(&amp;quot;Request complete (fail or success)&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;rand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Return a random number as generated by &amp;lt;tt&amp;gt;sg_random&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;srand()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Seed the random number generator based upon the current time. Returns 0.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;abort()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Wrapper for the C++ library abort() function – i.e. it just aborts the process without regard to what's happening. For exiting (gracefully) from FlightGear use the fgcommand &amp;quot;exit&amp;quot; instead.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=69446</id>
		<title>User:TheTom</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=User:TheTom&amp;diff=69446"/>
		<updated>2014-04-01T14:03:10Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &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;
&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;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Changelog_3.2&amp;diff=69445</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=69445"/>
		<updated>2014-04-01T13:59:57Z</updated>

		<summary type="html">&lt;p&gt;TheTom: No need to mention separate states. The main reason was pushing all attributes on the attribute stack. This was safe but not fast^^&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.0]].&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.00]]. &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;
&lt;br /&gt;
'''Aircraft Modeling'''&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;
&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;
&lt;br /&gt;
''' Usability '''&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;
&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;
'''Documentation'''&lt;br /&gt;
&lt;br /&gt;
'''Highlighted new and improved aircraft'''&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.0 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>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2014&amp;diff=69444</id>
		<title>FlightGear Newsletter April 2014</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=FlightGear_Newsletter_April_2014&amp;diff=69444"/>
		<updated>2014-04-01T13:55:19Z</updated>

		<summary type="html">&lt;p&gt;TheTom: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{newsletter}}&lt;br /&gt;
{{TOC_right|limit=2}}&lt;br /&gt;
&lt;br /&gt;
{{Newsletter being written}}&lt;br /&gt;
== Development news ==&lt;br /&gt;
Note to all contributors: Please also copy your newsletter additions to the changelog for the upcoming release: [[Next Changelog]].&lt;br /&gt;
&lt;br /&gt;
=== Canvas GUI Progress ===&lt;br /&gt;
&lt;br /&gt;
=== Random Buildings ===&lt;br /&gt;
&lt;br /&gt;
=== Project Rembrandt ===&lt;br /&gt;
A number of Mac users have been reporting issues related to running [[Project Rembrandt]] (deferred rendering/shadows) on Mac OSX with ATI/AMD GPUS, we are now looking for Mac users to provide feedback on running Rembrandt on Mac OSX, required information includes errors and warnings shown during startup/runtime, but also screen shots showing any issues. Please see: [[Project Rembrandt#Mac Issues]].&lt;br /&gt;
&lt;br /&gt;
=== Canvas System ===&lt;br /&gt;
&lt;br /&gt;
Tom has updated FlightGear 3.1 to remove a lot of unneeded OpenGL state changes. 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;
&lt;br /&gt;
=== High Level Architecture ===&lt;br /&gt;
&lt;br /&gt;
=== Usability Improvements ===&lt;br /&gt;
&lt;br /&gt;
=== Getting involved as a programmer ===&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
If you are interested in contributing as a core developer, please see [[Howto:Start core development]].&lt;br /&gt;
&lt;br /&gt;
If you interested in other developing, i.e. not C++ but [[Nasal]] scripting and/or XML, there are some articles listed at [[:Category:Popular Community Requests]] that have been suggested, but not fully or partially implemented, and are &amp;quot;mentored efforts&amp;quot;. That means that the community is looking for a hand in implementing them -- help from ''you'' -- but will also have more experienced developers willing to help you, for example by having tailored tutorials or even code snippets written for you. As mentioned in each page, please get in touch if you would like to help with one of those projects. In comparison to C/C++, Nasal is simpler and easier to learn quickly. It also doesn't require recompiling, which means that you can test and develop changes with a standard FlightGear release, i.e. off of the main download page. As long as you can run FlightGear, you can also run Nasal code and contribute. Many tutorials covering a wide range of projects are listed at [[Nasal]], so if you know a programming/scripting language already, or would like to try something new, go ahead: read, write, try and get involved! When it comes to Nasal scripting, playing around with different tutorials and code snippets is more important than being an experienced coder. &lt;br /&gt;
&lt;br /&gt;
Of course, you're also free to work on whatever you want -- FlightGear as a community-driven doesn't tell people what to do, but welcomes any contributions from anybody, as long as they have acceptable quality and are free to be licensed under the GNU GPL. So if you have something you would like to contribute back to FlightGear, please get in touch! (Preferably using Gitorious for larger merge requests, and the forums or (core-) developer's mailing list to inform the developers of what you want to contribute back.) Changes contributed 6-8 weeks before a release will usually appear in the next release, so your changes can be spread across the world.&lt;br /&gt;
&lt;br /&gt;
== Release ChangeLog ==&lt;br /&gt;
This section lists changes committed this month that will be available in the next release, these will be copied to the release changelog shortly before a release (for each month), so that we hopefully get a comprehensive list of new features.&lt;br /&gt;
&lt;br /&gt;
== Interview with a contributor (NAME) ==&lt;br /&gt;
''In each edition we have an interview with a contributor. Suggestions for possible questions are available on [[interview questions]], you are invited to come up with new questions and interview ideas obviously! Anyone is free to write an interview (with him-/herself or others) for next month's newsletter! If you'd like to help interview a contributor or get interviewed, please do consider adding yourself to the [[list of interview volunteers]]! To keep this going and less awkward, we are currently trying to come up with the convention that former interviewees become next month's interviewers.''&lt;br /&gt;
&lt;br /&gt;
* How long have you been involved in FlightGear?&lt;br /&gt;
* What are your major interests in FlightGear?&lt;br /&gt;
* What project are you working on right now?&lt;br /&gt;
* What do you plan on doing in the future?&lt;br /&gt;
* Are you happy with the way the FlightGear project is going?&lt;br /&gt;
* What do you enjoy most about developing for FlightGear?&lt;br /&gt;
* Are there any &amp;quot;hidden features&amp;quot; you have worked on in FlightGear that new users may miss?&lt;br /&gt;
* What advice can you give to new developers who want to get started on their first aircraft/new feature/Nasal script?&lt;br /&gt;
&lt;br /&gt;
More questions are being collected here: [[Interview questions]].&lt;br /&gt;
&lt;br /&gt;
Stay tuned for next month's interview, featuring FlightGear contributor XXXXXXXX &lt;br /&gt;
&lt;br /&gt;
== Nasal for newbies ==&lt;br /&gt;
&lt;br /&gt;
== New software tools and projects ==&lt;br /&gt;
&lt;br /&gt;
== FlightGear addons and mods ==&lt;br /&gt;
&lt;br /&gt;
== In the hangar ==&lt;br /&gt;
&lt;br /&gt;
=== New aircraft ===&lt;br /&gt;
&lt;br /&gt;
=== Updated aircraft ===&lt;br /&gt;
&lt;br /&gt;
=== Liveries ===&lt;br /&gt;
&lt;br /&gt;
== Scenery corner ==&lt;br /&gt;
=== Airports ===&lt;br /&gt;
&lt;br /&gt;
== Aircraft of the month ==&lt;br /&gt;
== Airport of the month ==&lt;br /&gt;
== Screenshot of the month ==&lt;br /&gt;
&lt;br /&gt;
== Suggested flights ==&lt;br /&gt;
== Aircraft reviews ==&lt;br /&gt;
&lt;br /&gt;
== Wiki updates ==&lt;br /&gt;
=== Translators required ===&lt;br /&gt;
{|&lt;br /&gt;
|[[File:en.gif]]&lt;br /&gt;
|The FlightGear Wiki still needs help for translating it into various languages. If you are interested in making the FlightGear Wiki multi-language then start at [[Help:Translate]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:de.gif]]&lt;br /&gt;
|Das FlightGear Wiki benötigt immer noch Hilfe bei der Übersetzung in verschiedene Sprachen. Wenn Du Interesse daran hast, das FlightGear Wiki Mehrsprachig zu machen, dann fang doch mit [[:de:Help:Übersetzen|Help:Übersetzen]] an.&lt;br /&gt;
|-&lt;br /&gt;
|[[File:nl.gif]]&lt;br /&gt;
|De FlightGear Wiki kan nog steed hulp gebruiken bij het vertalen van artikelen. Als je interesse hebt om de wiki meertalig te maken, raden we je aan om een kijkje te nemen bij [[:nl:Help:Vertalen|Help:Vertalen]].&lt;br /&gt;
|-&lt;br /&gt;
|[[File:es.gif]]&lt;br /&gt;
|La FlightGear wiki todavía necesita ayuda para traducirla a varios lenguajes. Si estás interesado en hacer la FlightGear wiki multilingüe, entonces comienza en [[:es:Help:Traducir|Help:Traducir]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Community news ==&lt;br /&gt;
=== FlightGear on YouTube ===&lt;br /&gt;
&lt;br /&gt;
=== New tutorials and screencasts ===&lt;br /&gt;
=== Forum news ===&lt;br /&gt;
=== Multiplayer ===&lt;br /&gt;
=== Virtual airlines ===&lt;br /&gt;
=== FlightGear events ===&lt;br /&gt;
&lt;br /&gt;
== Useful links ==&lt;br /&gt;
== And finally ... ==&lt;br /&gt;
=== Contributing ===&lt;br /&gt;
&lt;br /&gt;
{{Volunteer Intro|mode=showlogo}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
TODO: this needs to be added to  Template:Volunteer Intro&lt;br /&gt;
One of the regular thoughts expressed on the FlightGear forums is &amp;quot;I'd like to contribute but I don't know how to program, and I don't have the time&amp;quot;. Unfortunately, there is a common mis-conception that contributing requires programming and lots of free time. In fact, there are a huge range of ways to contribute to the project without needing to write code or spending days working on something. &lt;br /&gt;
&lt;br /&gt;
For ideas on starting to contribute to FlightGear, you may want to check out: [[Volunteer]].&lt;br /&gt;
&lt;br /&gt;
To learn more about how the project works, please see [http://flightgear.org/forums/viewtopic.php?f=42&amp;amp;t=15267#p149971 this short essay] written by Thorsten, for a more detailed article see [[How the FlightGear project works]].&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== YASim looking for a new maintainer ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{cquote|There are some pending merge requests to add some Yasim features, but we have an issue that since none of the current C++ developers own, or are experts in Yasim, we're reluctant to be the person who merges such changes, and potentially introduces subtle regressions.&lt;br /&gt;
&lt;br /&gt;
Obviously this is chicken-and-egg, since no one can become expert enough in the  code to become a maintainer :)&lt;br /&gt;
&lt;br /&gt;
So, I'm more than happy to apply patches *providing* I can be convinced they are sane+reasonable from a pure code perspective (happy to help with that, too, &lt;br /&gt;
if people are new to C++), and providing we have some assurance that a representative sample of yasim aircraft are unchanged or improved by the patch. &lt;br /&gt;
Suggestions for that means in practice, are most welcome!&lt;br /&gt;
&lt;br /&gt;
Otherwise I worry, given the nature of the solver, we'll keep optimising the solver for some aircraft, and making other existing aircraft worse - until someone tests them, and announced that they're no longer working.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg23986.html &lt;br /&gt;
|title=YASim and documentation&lt;br /&gt;
|author=James Turner |date= Fri, 05 Oct 2012 03:54:43 -0700}}&amp;lt;/ref&amp;gt;|James Turner}}&lt;br /&gt;
&lt;br /&gt;
{{cquote|I am still broadly happy to answer questions if posed (as long as I remember enough to come up with a meaningful answer).  Just cc: me if you do, because my&lt;br /&gt;
latencies here are measured in weeks. &lt;br /&gt;
Bugs can always be fixed.  What YASim needs is a maintainer, not really expertise per se.  The latter comes from the former.&amp;lt;ref&amp;gt;{{cite web |url=http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg23986.html &lt;br /&gt;
|title=YASim and documentation&lt;br /&gt;
|author=Andy Ross |date= Fri, 05 Oct 2012 03:54:43 -0700}}&amp;lt;/ref&amp;gt;|Andy Ross}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Call for volunteers ===&lt;br /&gt;
* The Terragear maintainers are looking for volunteers to help with development on the next world scenery project.  If you've ever wondered how a full 3D model of earth can be generated from raw data, now is your chance.  See the plan at [[World Scenery 3.0 roadmap]].&lt;br /&gt;
* The [[Target4Today]] team is looking for volunteers to help improving FlightGear's combat support&lt;br /&gt;
&lt;br /&gt;
=== Did you know ===&lt;br /&gt;
&lt;br /&gt;
[[Category:FlightGear Newsletter]]&lt;br /&gt;
&amp;lt;!-- this needs to be changed after each release, so that newsletters show up in the proper category --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Changes after 3.00]]&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=68985</id>
		<title>Template:Canvas Navigation</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Template:Canvas_Navigation&amp;diff=68985"/>
		<updated>2014-03-21T19:28:46Z</updated>

		<summary type="html">&lt;p&gt;TheTom: dead link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{forum|71|Canvas}}&lt;br /&gt;
{{sidebar&lt;br /&gt;
| name	= Canvas Navigation&lt;br /&gt;
| title = Canvas - the FlightGear 2D drawing API&lt;br /&gt;
| contentstyle= text-align: left;&lt;br /&gt;
&lt;br /&gt;
| content1 = &lt;br /&gt;
* [[Canvas]] - Main Page&lt;br /&gt;
* [[Canvas Development]]&lt;br /&gt;
* [[Canvas GUI]]&lt;br /&gt;
* [[Canvas Widgets]]&lt;br /&gt;
* [[Canvas Maps]]&lt;br /&gt;
&lt;br /&gt;
| heading2 = Frameworks&lt;br /&gt;
| content2 = &lt;br /&gt;
{{Canvas Frameworks|mode=navbar}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[How the Canvas subsystem works]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
| heading3 = Tutorials&lt;br /&gt;
| content3 =&lt;br /&gt;
* [[Howto:Adding a canvas to a GUI dialog]]&lt;br /&gt;
* [[Howto:Add a 2D canvas instrument to your aircraft]]&lt;br /&gt;
* [[Howto:Parsing 2D Instruments using the Canvas]]&lt;br /&gt;
* [[Howto:Creating fullscreen Canvas applications]]&lt;br /&gt;
* [[Howto:Use SVG inside a Canvas]]&lt;br /&gt;
* [[Howto:Canvas applications as Nasal submodules]]&lt;br /&gt;
* [[Howto:Using raster images and nested canvases]]&lt;br /&gt;
&amp;lt;!-- * [[Howto:Creating Canvas Widgets in Nasal]] --&amp;gt;&lt;br /&gt;
* [[Howto:Creating a Canvas graph widget]]&lt;br /&gt;
* [[Canvas HUD]]&lt;br /&gt;
| heading4 = Reference&lt;br /&gt;
| content4 =&lt;br /&gt;
* [[Canvas Element]]&lt;br /&gt;
** [[Canvas Group|Group]]&lt;br /&gt;
** [[Canvas Image|Image]]&lt;br /&gt;
** [[Canvas Map|Map]]&lt;br /&gt;
** [[Canvas Path|Path]]&lt;br /&gt;
** [[Canvas Text|Text]]&lt;br /&gt;
* [[Canvas Readme]]&lt;br /&gt;
* [[Canvas Nasal API]]&lt;br /&gt;
* [[Canvas - Event_Handling|Event Handling]]&lt;br /&gt;
| heading5 = Related&lt;br /&gt;
| content5 =&lt;br /&gt;
* [[Canvas Properties]]&lt;br /&gt;
* [[Unifying the 2D rendering backend via canvas]]&lt;br /&gt;
* [[FGCanvas]]&lt;br /&gt;
* [[Howto:Create a 2D drawing API for FlightGear]]&lt;br /&gt;
* [[Howto:Use a Camera View in an Instrument]]&lt;br /&gt;
&lt;br /&gt;
| heading6 = To be ported&lt;br /&gt;
| content6 = &lt;br /&gt;
* [[Navigation display]] {{Progressbar|70}}&lt;br /&gt;
* [[Map]] {{Progressbar|60}}&lt;br /&gt;
&lt;br /&gt;
| heading7 = Obsolete &amp;lt;br/&amp;gt;(depreciated by the Canvas)&lt;br /&gt;
| content7 =&lt;br /&gt;
* [[Complex Glass Cockpit Avionics]]&lt;br /&gt;
* [[OpenGL GUI RESOURCES]]&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;includeonly&amp;gt;{{main other|[[Category:Canvas]][[Category:Core development projects]]}}&lt;br /&gt;
{{howto other|[[Category:Canvas]][[Category:Howto]]}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Informative template|1=&lt;br /&gt;
== Usage ==&lt;br /&gt;
Add the template to the top of the article text.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;{{Canvas Navigation}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding the template to an page in the main namespace, the article namespace, or the howto namespace will add [[:Category:Canvas]] to the page.  In addition [[:Category:Howto]] will be added to articles in the howto namespace, and [[:Category:Core development projects]] will be added to articles in the main namespace.&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Navigation templates]]&lt;br /&gt;
[[Category:Canvas]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>TheTom</name></author>
	</entry>
</feed>