Howto:Prototyping a new NavDisplay Style
Jump to navigation
Jump to search
This article is a stub. You can help the wiki by expanding it. |
Objective
Demonstrate how a simple PUI/XML dialog can be used to easily prototype new NavDisplay styles, showing two instances for each pilot, which can be controlled/tested independently.
Approach
This is a PUI/XML dialog with two embedded CanvasWidget areas that instantiate independent ND instances using a subset of the code commonly found in the aircraft specific ND.nas file, adapted to use the embedded Canvas region for rendering the two NDs and GUI buttons/widgets added to control the whole thing without necessarily requiring a fully developed cockpit.
Roadmap
- add buttons for controlling each ND instance (range, zoom, centering)
- use io.include to directly reload the styles stuff (for rapid prototyping)
- procedurally add buttons for each switch by enhancing the myCockpit_switches hash with legends/labels for the UI use-case (use checkboxes for boolean props)
- add a dropdown menu to select the position source (main aircraft vs. AI/MP traffic)
Status
For now this is heavily based on ideas, and code, borrowed from the original MapStructure Debugger (code still available at [1])
Work in progress This article or section will be worked on in the upcoming hours or days. See history for the latest developments. |
Note For testing purposes, put the following dialog into $FG_ROOT/gui/dialogs/canvas-nd.xml and use the Nasal Console to run the dialog (or extend the Menubar accordingly):
fgcommand("dialog-show", props.Node.new({'dialog-name':'canvas-nd'}) ); |
<?xml version="1.0" encoding="UTF-8"?>
<PropertyList>
<name>canvas-nd</name>
<modal>false</modal>
<layout>vbox</layout>
<text>
<label>Canvas ND</label>
</text>
<nasal>
<open><![CDATA[
print("nasal/opening block");
var show_canvas_id = func(c) {
print("Canvas is:", c.getPath());
};
# to be used for shutting down each created instances upon closing the dialog (see the close block below)
var MFDInstances = [];
####
## an adapted version of ND.nas
##
var setupND = func(property_root, my_canvas) {
var myCockpit_switches = {
# symbolic alias : relative property (as used in bindings), initial value, type
'toggle_range': {path: '/inputs/range-nm', value:40, type:'INT'},
'toggle_weather': {path: '/inputs/wxr', value:0, type:'BOOL'},
'toggle_airports': {path: '/inputs/arpt', value:0, type:'BOOL'},
'toggle_stations': {path: '/inputs/sta', value:0, type:'BOOL'},
'toggle_waypoints': {path: '/inputs/wpt', value:0, type:'BOOL'},
'toggle_position': {path: '/inputs/pos', value:0, type:'BOOL'},
'toggle_data': {path: '/inputs/data',value:0, type:'BOOL'},
'toggle_terrain': {path: '/inputs/terr',value:0, type:'BOOL'},
'toggle_traffic': {path: '/inputs/tfc',value:0, type:'BOOL'},
'toggle_centered': {path: '/inputs/nd-centered',value:0, type:'BOOL'},
'toggle_lh_vor_adf': {path: '/inputs/lh-vor-adf',value:0, type:'INT'},
'toggle_rh_vor_adf': {path: '/inputs/rh-vor-adf',value:0, type:'INT'},
'toggle_display_mode': {path: '/mfd/display-mode', value:'MAP', type:'STRING'},
'toggle_display_type': {path: '/mfd/display-type', value:'LCD', type:'STRING'},
'toggle_true_north': {path: '/mfd/true-north', value:0, type:'BOOL'},
'toggle_rangearc': {path: '/mfd/rangearc', value:0, type:'BOOL'},
'toggle_track_heading': {path: '/hdg-trk-selected', value:0, type:'BOOL'},
'toggle_hdg_bug_only': {path: '/hdg-bug-only', value:0, type:'BOOL'},
# add new switches here
};
###
# entry point, this will set up an ND instance
# get a handle to the NavDisplay in canvas namespace (for now), see $FG_ROOT/Nasal/canvas/map/navdisplay.mfd
var ND = canvas.NavDisplay;
##
# set up a new ND instance, under 'instrumentation/efis' and use the
# myCockpit_switches hash to map control properties
# FIXME: use cmdarg() here to use a dialog specific path for all switches
var myND = ND.new("instrumentation/efis", myCockpit_switches, 'Boeing');
var group = my_canvas.createGroup();
myND.newMFD(group, my_canvas);
myND.update();
# store the instance for later cleanup
append(MFDInstances, myND);
return myND;
} # setupND()
]]></open>
<close><![CDATA[
print("nasal/closing block");
foreach(var mfd; MFDInstances) {
mfd.del();
}
]]></close>
</nasal>
<group>
<layout>hbox</layout>
<canvas>
<name>mfd1</name>
<valign>fill</valign>
<halign>fill</halign>
<stretch>true</stretch>
<pref-width>512</pref-width>
<pref-height>512</pref-height>
<view>1024</view>
<view>1024</view>
<nasal>
<!--
this is the Nasal/canvas section where you can run your own Nasal code
to access the canvas section
-->
<load><![CDATA[
# you can add your canvas-specific code here
var my_canvas = canvas.get(cmdarg()); # this will get a handle to the parent canvas:
show_canvas_id(my_canvas);
setupND(property_root: cmdarg(), my_canvas: my_canvas);
]]></load>
</nasal>
</canvas>
<canvas>
<name>mfd2</name>
<valign>fill</valign>
<halign>fill</halign>
<stretch>true</stretch>
<pref-width>512</pref-width>
<pref-height>512</pref-height>
<view>1024</view>
<view>1024</view>
<nasal>
<!--
this is the Nasal/canvas section where you can run your own Nasal code
to access the canvas section
-->
<load><![CDATA[
# you can add your canvas-specific code here
var my_canvas = canvas.get(cmdarg()); # this will get a handle to the parent canvas:
show_canvas_id(my_canvas);
setupND(property_root: cmdarg(), my_canvas: my_canvas);
]]></load>
</nasal>
</canvas>
</group>
<group>
<layout>hbox</layout>
<button>
<legend>Reload</legend>
<default>1</default>
<border>2</border>
<binding>
<command>reinit</command>
<subsystem>gui</subsystem>
</binding>
</button>
<button>
<legend>Exit</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
</PropertyList>