A3XX: New independant improved NDs

This commit is contained in:
Joshua Davidson 2017-06-18 20:14:41 -04:00
parent d9ee54ea76
commit 1ad9f59715
93 changed files with 27711 additions and 348 deletions

View file

@ -764,7 +764,6 @@
<libraries>
<file>Aircraft/A320Family/Nasal/libraries.nas</file>
<file>Aircraft/A320Family/Nasal/PFD_FMA.nas</file>
<file>Aircraft/A320Family/Models/Instruments/ND/ND.nas</file>
<file>Aircraft/A320Family/Nasal/gpws.nas</file>
<file>Aircraft/A320Family/Nasal/efis.nas</file>
<file>Aircraft/A320Family/Nasal/ECAM.nas</file>
@ -797,6 +796,9 @@
<mcdu2>
<file>Aircraft/A320Family/Nasal/MCDU/MCDU2.nas</file>
</mcdu2>
<canvas_nd>
<file>Aircraft/A320Family/Models/Instruments/ND/canvas/ND.nas</file>
</canvas_nd>
</nasal>
</PropertyList>

View file

@ -3682,7 +3682,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-toggle</command>
<property>/instrumentation/efis/inputs/CSTR</property>
<property>/instrumentation/efis[1]/inputs/CSTR</property>
</binding>
</action>
</animation>
@ -3708,7 +3708,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-toggle</command>
<property>/instrumentation/efis/inputs/wpt</property>
<property>/instrumentation/efis[1]/inputs/wpt</property>
</binding>
</action>
</animation>
@ -3738,11 +3738,11 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-toggle</command>
<property>/instrumentation/efis/inputs/VORD</property>
<property>/instrumentation/efis[1]/inputs/VORD</property>
</binding>
<binding>
<command>property-toggle</command>
<property>/instrumentation/efis/inputs/DME</property>
<property>/instrumentation/efis[1]/inputs/DME</property>
</binding>
</action>
</animation>
@ -3768,7 +3768,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-toggle</command>
<property>/instrumentation/efis/inputs/NDB</property>
<property>/instrumentation/efis[1]/inputs/NDB</property>
</binding>
</action>
</animation>
@ -3794,7 +3794,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-toggle</command>
<property>/instrumentation/efis/inputs/arpt</property>
<property>/instrumentation/efis[1]/inputs/arpt</property>
</binding>
</action>
</animation>
@ -3814,7 +3814,7 @@
<animation>
<type>textranslate</type>
<object-name>cstr.001</object-name>
<property>/instrumentation/efis/inputs/CSTR</property>
<property>/instrumentation/efis[1]/inputs/CSTR</property>
<factor>0.0625</factor>
<axis>
<x>0</x>
@ -3838,7 +3838,7 @@
<animation>
<type>textranslate</type>
<object-name>wpt.001</object-name>
<property>/instrumentation/efis/inputs/wpt</property>
<property>/instrumentation/efis[1]/inputs/wpt</property>
<factor>0.0625</factor>
<axis>
<x>0</x>
@ -3862,7 +3862,7 @@
<animation>
<type>textranslate</type>
<object-name>vord.001</object-name>
<property>/instrumentation/efis/inputs/VORD</property>
<property>/instrumentation/efis[1]/inputs/VORD</property>
<factor>0.0625</factor>
<axis>
<x>0</x>
@ -3886,7 +3886,7 @@
<animation>
<type>textranslate</type>
<object-name>ndb.001</object-name>
<property>/instrumentation/efis/inputs/NDB</property>
<property>/instrumentation/efis[1]/inputs/NDB</property>
<factor>0.0625</factor>
<axis>
<x>0</x>
@ -3910,7 +3910,7 @@
<animation>
<type>textranslate</type>
<object-name>arpt.001</object-name>
<property>/instrumentation/efis/inputs/arpt</property>
<property>/instrumentation/efis[1]/inputs/arpt</property>
<factor>0.0625</factor>
<axis>
<x>0</x>
@ -3951,7 +3951,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>nasal</command>
<script>libraries.mode_inc();</script>
<script>libraries.mode2_inc();</script>
</binding>
</action>
<action>
@ -3960,7 +3960,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>nasal</command>
<script>libraries.mode_dec();</script>
<script>libraries.mode2_dec();</script>
</binding>
</action>
</animation>
@ -3997,7 +3997,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>nasal</command>
<script>libraries.ctl_func("range",1);</script>
<script>libraries.ctl2_func("range",1);</script>
</binding>
</action>
<action>
@ -4006,7 +4006,7 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>nasal</command>
<script>libraries.ctl_func("range",-1);</script>
<script>libraries.ctl2_func("range",-1);</script>
</binding>
</action>
</animation>
@ -4042,14 +4042,14 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-cycle</command>
<property>/instrumentation/efis/input/vor-adf-1</property>
<property>/instrumentation/efis[1]/input/vor-adf-1</property>
<value>0</value> <!-- OFF -->
<value>1</value> <!-- VOR -->
<value>2</value> <!-- ADF -->
</binding>
<binding>
<command>property-cycle</command>
<property>/instrumentation/efis/input/lh-vor-adf</property>
<property>/instrumentation/efis[1]/input/lh-vor-adf</property>
<value>0</value> <!-- OFF -->
<value>1</value> <!-- VOR -->
<value>-1</value> <!-- ADF -->
@ -4088,14 +4088,14 @@
<repeatable type="bool">false</repeatable>
<binding>
<command>property-cycle</command>
<property>/instrumentation/efis/input/vor-adf-2</property>
<property>/instrumentation/efis[1]/input/vor-adf-2</property>
<value>0</value> <!-- OFF -->
<value>1</value> <!-- VOR -->
<value>2</value> <!-- ADF -->
</binding>
<binding>
<command>property-cycle</command>
<property>/instrumentation/efis/input/rh-vor-adf</property>
<property>/instrumentation/efis[1]/input/rh-vor-adf</property>
<value>0</value> <!-- OFF -->
<value>1</value> <!-- VOR -->
<value>-1</value> <!-- ADF -->
@ -4129,7 +4129,7 @@
<animation>
<type>rotate</type>
<object-name>nd-mode-right</object-name>
<property>/instrumentation/efis/mfd/pnl_mode-num</property>
<property>/instrumentation/efis[1]/mfd/pnl_mode-num</property>
<interpolation>
<entry><ind>0</ind><dep> 0</dep></entry>
<entry><ind>1</ind><dep> 45</dep></entry>
@ -4172,7 +4172,7 @@
<animation>
<type>rotate</type>
<object-name>nd-range-right</object-name>
<property>/instrumentation/efis/inputs/range-nm</property>
<property>/instrumentation/efis[1]/inputs/range-nm</property>
<interpolation>
<entry><ind>10</ind><dep>0</dep></entry>
<entry><ind>20</ind><dep>45</dep></entry>

View file

@ -0,0 +1,680 @@
##
# storage container for all ND instances
var nd_display = {};
#canvas.NDStyles.Airbus = {
var airbusSt = {
font_mapper: func(family, weight) {
if( family == "Liberation Sans" and weight == "normal" )
return "LiberationFonts/LiberationSans-Regular.ttf";
},
# where all the symbols are stored
# TODO: SVG elements should be renamed to use boeing/airbus prefix
# aircraft developers should all be editing the same ND.svg image
# the code can deal with the differences now
svg_filename: "Nasal/canvas/map/boeingND.svg",
##
## this loads and configures existing layers (currently, *.layer files in Nasal/canvas/map)
##
layers: [
{
name:'fixes',
disabled:1,
update_on:['toggle_range','toggle_waypoints'],
predicate: func(nd, layer) {
# print("Running fixes predicate");
var visible=nd.get_switch('toggle_waypoints') and nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN']) and (nd.rangeNm() <= 40);
if (visible) {
# print("fixes update requested!");
trigger_update( layer );
}
layer._view.setVisible(visible);
}, # end of layer update predicate
}, # end of fixes layer
{
name:'FIX',
isMapStructure:1,
update_on:['toggle_range','toggle_waypoints'],
# FIXME: this is a really ugly place for controller code
predicate: func(nd, layer) {
# print("Running vor layer predicate");
# toggle visibility here
var visible=nd.get_switch('toggle_waypoints') and nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN']) and (nd.rangeNm() <= 40);
layer.group.setVisible( nd.get_switch('toggle_waypoints') );
if (visible) {
#print("Updating MapStructure ND layer: FIX");
# (Hopefully) smart update
layer.update();
}
}, # end of layer update predicate
}, # end of FIX layer
# Should redraw every 10 seconds
{
name:'storms',
update_on:['toggle_range','toggle_weather','toggle_display_mode'],
predicate: func(nd, layer) {
# print("Running fixes predicate");
var visible=nd.get_switch('toggle_weather') and nd.get_switch('toggle_display_mode') != "PLAN";
if (visible) {
#print("storms update requested!");
trigger_update( layer );
}
layer._view.setVisible(visible);
}, # end of layer update predicate
}, # end of storms layer
{
name:'airplaneSymbol',
update_on:['toggle_display_mode'],
predicate: func(nd, layer) {
var visible = nd.get_switch('toggle_display_mode') == "PLAN";
if (visible) {
trigger_update( layer );
}
layer._view.setVisible(visible);
},
},
{
name:'airports-nd',
update_on:['toggle_range','toggle_airports','toggle_display_mode'],
predicate: func(nd, layer) {
# print("Running airports-nd predicate");
var visible = nd.get_switch('toggle_airports') and nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN']);
if (visible) {
trigger_update( layer ); # clear & redraw
}
layer._view.setVisible( visible );
}, # end of layer update predicate
}, # end of airports layer
# Should distinct between low and high altitude navaids. Hiding above 40 NM for now, to prevent clutter/lag.
{
name:'vor',
disabled:1,
update_on:['toggle_range','toggle_vor','toggle_display_mode'],
predicate: func(nd, layer) {
# print("Running vor layer predicate");
var visible = nd.get_switch('toggle_vor') and nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN']) and (nd.rangeNm() <= 40);
if(visible) {
trigger_update( layer ); # clear & redraw
}
layer._view.setVisible( nd.get_switch('toggle_vor') );
}, # end of layer update predicate
}, # end of VOR layer
{
name:'VOR',
isMapStructure:1,
update_on:['toggle_range','toggle_vor','toggle_display_mode'],
# FIXME: this is a really ugly place for controller code
predicate: func(nd, layer) {
# print("Running vor layer predicate");
# toggle visibility here
var visible = nd.get_switch('toggle_vor') and nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN']) and (nd.rangeNm() <= 40);
layer.group.setVisible( visible );
if (visible) {
#print("Updating MapStructure ND layer: VOR");
# (Hopefully) smart update
layer.update();
}
}, # end of layer update predicate
}, # end of VOR layer
# Should distinct between low and high altitude navaids. Hiding above 40 NM for now, to prevent clutter/lag.
{ name:'dme', disabled:1, update_on:['toggle_range','toggle_stations'],
predicate: func(nd, layer) {
var visible = nd.get_switch('toggle_stations') and nd.in_mode('toggle_display_mode', ['MAP']) and (nd.rangeNm() <= 40);
if(visible) {
trigger_update( layer ); # clear & redraw
}
layer._view.setVisible( nd.get_switch('toggle_stations') );
}, # end of layer update predicate
}, # end of DME layers
{ name:'DME', isMapStructure:1, update_on:['toggle_range','toggle_stations'],
# FIXME: this is a really ugly place for controller code
predicate: func(nd, layer) {
var visible = nd.get_switch('toggle_stations') and nd.in_mode('toggle_display_mode', ['MAP']) and (nd.rangeNm() <= 40);
# print("Running vor layer predicate");
# toggle visibility here
layer.group.setVisible( visible );
if (visible) {
#print("Updating MapStructure ND layer: DME");
# (Hopefully) smart update
layer.update();
}
}, # end of layer update predicate
}, # end of DME layer
{
name:'mp-traffic',
update_on:['toggle_range','toggle_traffic'],
predicate: func(nd, layer) {
var visible = nd.get_switch('toggle_traffic');
layer._view.setVisible( visible );
if (visible) {
trigger_update( layer ); # clear & redraw
}
}, # end of layer update predicate
}, # end of traffic layer
{
name:'TFC',
disabled:1,
isMapStructure:1,
update_on:['toggle_range','toggle_traffic'],
predicate: func(nd, layer) {
var visible = nd.get_switch('toggle_traffic');
layer.group.setVisible( visible );
if (visible) {
#print("Updating MapStructure ND layer: TFC");
layer.update();
}
}, # end of layer update predicate
}, # end of traffic layer
{
name:'runway-nd',
update_on:['toggle_range','toggle_display_mode'],
predicate: func(nd, layer) {
var visible = (nd.rangeNm() <= 40) and getprop("autopilot/route-manager/active") and nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN']) ;
if (visible)
trigger_update( layer ); # clear & redraw
layer._view.setVisible( visible );
}, # end of layer update predicate
}, # end of airports-nd layer
{
name:'route',
update_on:['toggle_range','toggle_display_mode'],
predicate: func(nd, layer) {
var visible= (nd.in_mode('toggle_display_mode', ['NAV', 'ARC','PLAN']));
if (visible)
trigger_update( layer ); # clear & redraw
layer._view.setVisible( visible );
}, # end of layer update predicate
}, # end of route layer
## add other layers here, layer names must match the registered names as used in *.layer files for now
## this will all change once we're using Philosopher's MapStructure framework
], # end of vector with configured layers
# This is where SVG elements are configured by providing "behavior" hashes, i.e. for animations
# to animate each SVG symbol, specify behavior via callbacks (predicate, and true/false implementation)
# SVG identifier, callback etc
# TODO: update_on([]), update_mode (update() vs. timers/listeners)
# TODO: support putting symbols on specific layers
features: [
{
# TODO: taOnly doesn't need to use getprop polling in update(), use a listener instead!
id: 'taOnly', # the SVG ID
impl: { # implementation hash
init: func(nd, symbol), # for updateCenter stuff, called during initialization in the ctor
predicate: func(nd) getprop("instrumentation/tcas/inputs/mode") == 2, # the condition
is_true: func(nd) nd.symbols.taOnly.show(), # if true, run this
is_false: func(nd) nd.symbols.taOnly.hide(), # if false, run this
}, # end of taOnly behavior/callbacks
}, # end of taOnly
{
id: 'tas',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.aircraft_source.get_spd() > 100,
is_true: func(nd) {
nd.symbols.tas.setText(sprintf("%3.0f",getprop("/velocities/airspeed-kt") ));
nd.symbols.tas.show();
},
is_false: func(nd) nd.symbols.tas.hide(),
},
},
{
id: 'tasLbl',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.aircraft_source.get_spd() > 100,
is_true: func(nd) nd.symbols.tasLbl.show(),
is_false: func(nd) nd.symbols.tasLbl.hide(),
},
},
{
id: 'ilsFreq',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS']),
is_true: func(nd) {
nd.symbols.ilsFreq.show();
if(getprop("instrumentation/nav/in-range"))
nd.symbols.ilsFreq.setText(getprop("instrumentation/nav/nav-id"));
else
nd.symbols.ilsFreq.setText(getprop("instrumentation/nav/frequencies/selected-mhz-fmt"));
},
is_false: func(nd) nd.symbols.ilsFreq.hide(),
},
},
{
id: 'ilsLbl',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS']),
is_true: func(nd) {
nd.symbols.ilsLbl.show();
},
is_false: func(nd) nd.symbols.ilsLbl.hide(),
},
},
{
id: 'wpActiveId',
impl: {
init: func(nd,symbol),
predicate: func(nd) getprop("/autopilot/route-manager/wp/id") != nil and getprop("autopilot/route-manager/active"),
is_true: func(nd) {
nd.symbols.wpActiveId.setText(getprop("/autopilot/route-manager/wp/id"));
nd.symbols.wpActiveId.show();
},
is_false: func(nd) nd.symbols.wpActiveId.hide(),
}, # of wpActiveId.impl
}, # of wpActiveId
{
id: 'wpActiveDist',
impl: {
init: func(nd,symbol),
predicate: func(nd) getprop("/autopilot/route-manager/wp/dist") != nil and getprop("autopilot/route-manager/active"),
is_true: func(nd) {
nd.symbols.wpActiveDist.setText(sprintf("%3.01f",getprop("/autopilot/route-manager/wp/dist")));
nd.symbols.wpActiveDist.show();
},
is_false: func(nd) nd.symbols.wpActiveDist.hide(),
},
},
{
id: 'wpActiveDistLbl',
impl: {
init: func(nd,symbol),
predicate: func(nd) getprop("/autopilot/route-manager/wp/dist") != nil and getprop("autopilot/route-manager/active"),
is_true: func(nd) {
nd.symbols.wpActiveDistLbl.show();
if(getprop("/autopilot/route-manager/wp/dist") > 1000)
nd.symbols.wpActiveDistLbl.setText(" NM");
},
is_false: func(nd) nd.symbols.wpActiveDistLbl.hide(),
},
},
{
id: 'eta',
impl: {
init: func(nd,symbol),
predicate: func(nd) getprop("autopilot/route-manager/wp/eta") != nil and getprop("autopilot/route-manager/active"),
is_true: func(nd) {
var etaSec = getprop("/sim/time/utc/day-seconds")+getprop("autopilot/route-manager/wp/eta-seconds");
var h = math.floor(etaSec/3600);
etaSec=etaSec-3600*h;
var m = math.floor(etaSec/60);
etaSec=etaSec-60*m;
var s = etaSec/10;
if (h>24) h=h-24;
nd.symbols.eta.setText(sprintf("%02.0f%02.0f.%01.0fz",h,m,s));
nd.symbols.eta.show();
},
is_false: func(nd) nd.symbols.eta.hide(),
}, # of eta.impl
}, # of eta
{
id: 'gsGroup',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS']),
is_true: func(nd) {
if(nd.get_switch('toggle_centered'))
nd.symbols.gsGroup.setTranslation(0,0);
else
nd.symbols.gsGroup.setTranslation(0,150);
nd.symbols.gsGroup.show();
},
is_false: func(nd) nd.symbols.gsGroup.hide(),
},
},
{
id:'hdg',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS','NAV', 'ARC','VOR']),
is_true: func(nd) {
var hdgText = "";
if(nd.in_mode('toggle_display_mode', ['NAV', 'ARC'])) {
if(nd.get_switch('toggle_true_north'))
hdgText = nd.aircraft_source.get_trk_tru();
else
hdgText = nd.aircraft_source.get_trk_mag();
} else {
if(nd.get_switch('toggle_true_north'))
hdgText = nd.aircraft_source.get_hdg_tru();
else
hdgText = nd.aircraft_source.get_hdg_mag();
}
nd.symbols.hdg.setText(sprintf("%03.0f", hdgText+0.5));
},
is_false: NOTHING,
},
},
{
id:'hdgGroup',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS','NAV','ARC','VOR']),
is_true: func(nd) {
nd.symbols.hdgGroup.show();
if(nd.get_switch('toggle_centered'))
nd.symbols.hdgGroup.setTranslation(0,100);
else
nd.symbols.hdgGroup.setTranslation(0,0);
},
is_false: func(nd) nd.symbols.hdgGroup.hide(),
},
},
{
id:'gs',
impl: {
init: func(nd,symbol),
common: func(nd) nd.symbols.gs.setText(sprintf("%3.0f",nd.aircraft_source.get_gnd_spd() )),
predicate: func(nd) nd.aircraft_source.get_gnd_spd() >= 30,
is_true: func(nd) {
nd.symbols.gs.setFontSize(36);
},
is_false: func(nd) nd.symbols.gs.setFontSize(52),
},
},
{
id:'rangeArcs',
impl: {
init: func(nd,symbol),
predicate: func(nd) ((nd.in_mode('toggle_display_mode', ['ILS','VOR']) and nd.get_switch('toggle_weather')) or nd.get_switch('toggle_display_mode') == "ARC"),
is_true: func(nd) nd.symbols.rangeArcs.show(),
is_false: func(nd) nd.symbols.rangeArcs.hide(),
}, # of rangeArcs.impl
}, # of rangeArcs
{
id:'rangePln1',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.get_switch('toggle_display_mode') == "PLAN",
is_true: func(nd) {
nd.symbols.rangePln1.show();
nd.symbols.rangePln1.setText(sprintf("%3.0f",nd.rangeNm()));
},
is_false: func(nd) nd.symbols.rangePln1.hide(),
},
},
{
id:'rangePln2',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.get_switch('toggle_display_mode') == "PLAN",
is_true: func(nd) {
nd.symbols.rangePln2.show();
nd.symbols.rangePln2.setText(sprintf("%3.0f",nd.rangeNm()/2));
},
is_false: func(nd) nd.symbols.rangePln2.hide(),
},
},
{
id:'rangePln3',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.get_switch('toggle_display_mode') == "PLAN",
is_true: func(nd) {
nd.symbols.rangePln3.show();
nd.symbols.rangePln3.setText(sprintf("%3.0f",nd.rangeNm()/2));
},
is_false: func(nd) nd.symbols.rangePln3.hide(),
},
},
{
id:'rangePln4',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.get_switch('toggle_display_mode') == "PLAN",
is_true: func(nd) {
nd.symbols.rangePln4.show();
nd.symbols.rangePln4.setText(sprintf("%3.0f",nd.rangeNm()));
},
is_false: func(nd) nd.symbols.rangePln4.hide(),
},
},
{
id:'crsLbl',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS','VOR']),
is_true: func(nd) nd.symbols.crsLbl.show(),
is_false: func(nd) nd.symbols.crsLbl.hide(),
},
},
{
id:'crs',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS','VOR']),
is_true: func(nd) {
nd.symbols.crs.show();
if(getprop("instrumentation/nav/radials/selected-deg") != nil)
nd.symbols.crs.setText(sprintf("%03.0f",getprop("instrumentation/nav/radials/selected-deg")));
},
is_false: func(nd) nd.symbols.crs.hide(),
},
},
{
id:'dmeLbl',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS','VOR']),
is_true: func(nd) nd.symbols.dmeLbl.show(),
is_false: func(nd) nd.symbols.dmeLbl.hide(),
},
},
{
id:'dme',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS','VOR']),
is_true: func(nd) {
nd.symbols.dme.show();
if(getprop("instrumentation/dme/in-range"))
nd.symbols.dme.setText(sprintf("%3.1f",getprop("instrumentation/nav/nav-distance")*0.000539));
},
is_false: func(nd) nd.symbols.dme.hide(),
},
},
{
id:'trkInd2',
impl: {
init: func(nd,symbol),
predicate: func(nd) (nd.in_mode('toggle_display_mode', ['ILS','VOR'])),
is_true: func(nd) {
nd.symbols.trkInd2.show();
nd.symbols.trkInd2.setRotation((nd.aircraft_source.get_trk_tru()-nd.aircraft_source.get_hdg_tru())*D2R);
},
is_false: func(nd) nd.symbols.trkInd2.hide(),
},
},
{
id:'vorCrsPtr',
impl: {
init: func(nd,symbol),
predicate: func(nd) (nd.in_mode('toggle_display_mode', ['ILS','VOR'])),
is_true: func(nd) {
nd.symbols.vorCrsPtr.show();
nd.symbols.vorCrsPtr.setRotation((getprop("instrumentation/nav/radials/selected-deg")-nd.aircraft_source.get_hdg_tru())*D2R);
},
is_false: func(nd) nd.symbols.vorCrsPtr.hide(),
},
},
{
id:'vorCrsPtr2',
impl: {
init: func(nd,symbol),
predicate: func(nd) (nd.in_mode('toggle_display_mode', ['ILS','VOR'])),
is_true: func(nd) {
nd.symbols.vorCrsPtr2.show();
nd.symbols.vorCrsPtr2.setRotation((getprop("instrumentation/nav/radials/selected-deg")-nd.aircraft_source.get_hdg_tru())*D2R);
},
is_false: func(nd) nd.symbols.vorCrsPtr2.hide(),
},
},
{
id: 'gsDiamond',
impl: {
init: func(nd,symbol),
predicate: func(nd) nd.in_mode('toggle_display_mode', ['ILS']),
is_true: func(nd) {
if(getprop("instrumentation/nav/gs-needle-deflection-norm") != nil)
nd.symbols.gsDiamond.setTranslation(-getprop("instrumentation/nav/gs-needle-deflection-norm")*150,0);
},
is_false: func(nd) nd.symbols.gsGroup.hide(),
},
},
{
id:'locPtr',
impl: {
init: func(nd,symbol),
predicate: func(nd) (nd.in_mode('toggle_display_mode', ['ILS','VOR']) and !nd.get_switch('toggle_centered') and getprop("instrumentation/nav/in-range")),
is_true: func(nd) {
nd.symbols.locPtr.show();
var deflection = getprop("instrumentation/nav/heading-needle-deflection-norm");
nd.symbols.locPtr.setTranslation(deflection*150,0);
},
is_false: func(nd) nd.symbols.locPtr.hide(),
},
},
{
id:'locPtr2',
impl: {
init: func(nd,symbol),
predicate: func(nd) (nd.in_mode('toggle_display_mode', ['ILS','VOR']) and nd.get_switch('toggle_centered') and getprop("instrumentation/nav/in-range")),
is_true: func(nd) {
nd.symbols.locPtr2.show();
var deflection = getprop("instrumentation/nav/heading-needle-deflection-norm");
nd.symbols.locPtr2.setTranslation(deflection*150,0);
},
is_false: func(nd) nd.symbols.locPtr2.hide(),
},
},
{
id:'wind',
impl: {
init: func(nd,symbol),
predicate: ALWAYS,
is_true: func(nd) {
var windDir = getprop("environment/wind-from-heading-deg");
if(!nd.get_switch('toggle_true_north'))
windDir = windDir + getprop("environment/magnetic-variation-deg");
nd.symbols.wind.setText(sprintf("%03.0f / %02.0f",windDir,getprop("environment/wind-speed-kt")));
},
is_false: NOTHING,
},
},
{
id:'windArrow',
impl: {
init: func(nd,symbol),
predicate: func(nd) (!(nd.in_mode('toggle_display_mode', ['PLAN']) and (nd.get_switch('toggle_display_type') == "LCD")) and nd.aircraft_source.get_spd() > 100),
is_true: func(nd) {
nd.symbols.windArrow.show();
var windArrowRot = getprop("environment/wind-from-heading-deg");
if(nd.in_mode('toggle_display_mode', ['NAV','ARC','PLAN'])) {
if(nd.get_switch('toggle_true_north'))
windArrowRot = windArrowRot - nd.aircraft_source.get_trk_tru();
else
windArrowRot = windArrowRot - nd.aircraft_source.get_trk_mag();
} else {
if(nd.get_switch('toggle_true_north'))
windArrowRot = windArrowRot - nd.aircraft_source.get_hdg_tru();
else
windArrowRot = windArrowRot - nd.aircraft_source.get_hdg_mag();
}
nd.symbols.windArrow.setRotation(windArrowRot*D2R);
},
is_false: func(nd) nd.symbols.windArrow.hide(),
},
},
], # end of vector with features
}
###
# entry point, this will set up all ND instances
setlistener("sim/signals/fdm-initialized", func() {
##
# configure aircraft specific cockpit/ND switches here
# these are to be found in the property branch you specify
# via the NavDisplay.new() call
# the backend code in navdisplay.mfd should NEVER contain any aircraft-specific
# properties, or it will break other aircraft using different properties
# instead, make up an identifier (hash key) and map it to the property used
# in your aircraft, relative to your ND root in the backend code, only ever
# refer to the handle/key instead via the me.get_switch('toggle_range') method
# which would internally look up the matching aircraft property, e.g. '/instrumentation/efis'/inputs/range-nm'
#
# note: it is NOT sufficient to just add new switches here, the backend code in navdisplay.mfd also
# needs to know what to do with them !
# refer to incomplete symbol implementations to learn how they work (e.g. WXR, STA)
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: '/nd/display-mode', value:'NAV', type:'STRING'},
'toggle_display_type': {path: '/mfd/display-type', value:'LCD', type:'STRING'},
'toggle_true_north': {path: '/mfd/true-north', value:0, type:'BOOL'},
# add new switches here
};
# get a handle to the NavDisplay in canvas namespace (for now), see $FG_ROOT/Nasal/canvas/map/navdisplay.mfd
var ND = canvas.NavDisplay;
## TODO: We want to support multiple independent ND instances here!
# foreach(var pilot; var pilots = [ {name:'cpt', path:'instrumentation/efis',
# name:'fo', path:'instrumentation[1]/efis']) {
##
# set up a new ND instance, under 'instrumentation/efis' and use the
# myCockpit_switches hash to map control properties
var NDCpt = ND.new("instrumentation/efis", myCockpit_switches, 'Airbus');
nd_display.main = canvas.new({
"name": "ND",
"size": [1024, 1024],
"view": [1024, 1024],
"mipmapping": 1
});
nd_display.main.addPlacement({"node": "ND.screen"});
var group = nd_display.main.createGroup();
NDCpt.newMFD(group);
NDCpt.update();
print("ND Canvas Initialized!");
}); # fdm-initialized listener callback
var showNd = func() {
# The optional second arguments enables creating a window decoration
var dlg = canvas.Window.new([400, 400], "dialog");
dlg.setCanvas( nd_display["main"] );
}

View file

@ -1,249 +0,0 @@
var nd_display = {};
setlistener("sim/signals/fdm-initialized", func() {
setprop("instrumentation/efis/nd/display-mode", "ARC");
setprop("instrumentation/efis/inputs/tfc", 1);
setprop("instrumentation/efis/inputs/wpt", 0);
setprop("instrumentation/efis/inputs/wxr", 0);
setprop("instrumentation/efis/inputs/sta", 0);
setprop("instrumentation/efis/inputs/arpt", 0);
setprop("instrumentation/efis/mfd/true-north", 0);
var toggle_listeners = {
# 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_ndb': {path: '/inputs/NDB', value:0, type:'BOOL'},
'toggle_stations': {path: '/inputs/sta', value:0, type:'BOOL'},
'toggle_vor': {path: '/inputs/VORD', value:0, type:'BOOL'},
'toggle_cstr': {path: '/inputs/CSTR', 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: '/input/lh-vor-adf',value:0, type:'INT'},
'toggle_rh_vor_adf': {path: '/input/rh-vor-adf',value:0, type:'INT'},
'toggle_display_mode': {path: '/nd/canvas-display-mode', value:'NAV', 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_track_heading': {path: '/trk-selected', value:0, type:'BOOL'},
'toggle_fplan': {path: '/nd/route-manager-active', value:0, type: 'BOOL'}, # flight plan active
'toggle_lnav': {path: '/nd/lnav', value:0, type: 'BOOL'}, # LNAV active
'toggle_vnav': {path: '/nd/vnav', value:0, type: 'BOOL'}, # VNAV active
'toggle_wpt_idx': {path: '/inputs/plan-wpt-index', value: -1, type: 'INT'},# WPT Index to be used in PLAN
'toggle_plan_loop': {path: '/nd/plan-mode-loop', value: 0, type: 'INT'}, # Not used
'toggle_app_mode': {path: '/nd/app-mode', value:'', type: 'STRING'}, # Approach mode string (ie. 'ILS APP')
'toggle_cur_td': {path: '/nd/current-td', value: 0, type: 'INT'}, # Top of Desc dist. along route
'toggle_cur_tc': {path: '/nd/current-tc', value: 0, type: 'INT'}, # Top of Climb dist. along route
'toggle_cur_sc': {path: '/nd/current-sc', value: 0, type: 'INT'}, # Start of Climb dist. along route
'toggle_cur_ed': {path: '/nd/current-ed', value: 0, type: 'INT'}, # End of Desc dist. along route
'toggle_cur_sd': {path: '/nd/current-sd', value: 0, type: 'INT'}, # Start of Desc dist. along route
'toggle_cur_ec': {path: '/nd/current-ec', value: 0, type: 'INT'}, # End of Climb dist. along route
'toggle_lvl_off_at': {path: '/nd/level-off-at', value: 0, type: 'INT'}, # Level-off point along route
'toggle_man_spd': {path: '/nd/managed-spd', value: 0, type: 'INT'}, # Managed Speed Mode
'toggle_athr': {path: '/it-autoflight/output/athr', value: 0, type: 'INT'}, # Auto-thrust engaged
'toggle_spd_point_100': {path: '/nd/spd-change-raw-100', value: 0, type: 'INT'}, # Speed limit change point FL100
'toggle_spd_point_140': {path: '/nd/spd-change-raw-140', value: 0, type: 'INT'}, # Speed limit change point FL140
'toggle_spd_point_250': {path: '/nd/spd-change-raw-250', value: 0, type: 'INT'}, # Speed limit change point FL250
'toggle_spd_point_260': {path: '/nd/spd-change-raw-260', value: 0, type: 'INT'}, # Speed limit change point FL260
'toggle_nav1_frq': {path: '/nd/nav1_frq', value: 0, type: 'INT'}, # Nav1 Freq. Listener
'toggle_nav2_frq': {path: '/nd/nav2_frq', value: 0, type: 'INT'}, # Nav2 Freq. Listener
'toggle_adf1_frq': {path: '/nd/adf1_frq', value: 0, type: 'INT'}, # ADF1 Freq. Listener
'toggle_adf2_frq': {path: '/nd/adf2_frq', value: 0, type: 'INT'}, # ADF2 Freq. Listener
'toggle_hold_init': {path: '/nd/hold_init', value: 0, type: 'INT'}, # HOLD pattern init Listener
'toggle_hold_update': {path: '/nd/hold_update', value: 0, type: 'INT'}, # HOLD pattern update Listener
'toggle_hold_wp': {path: '/nd/hold_wp', value: '', type: 'STRING'}, # HOLD pattern waypoint
'toggle_route_num': {path: '/nd/route_num', value: 0, type: 'INT'}, # Route waypoint count
'toggle_cur_wp': {path: '/nd/cur_wp', value: 0, type: 'INT'}, # Current Waypoint (TO Waypoint) index
'toggle_ap1': {path: '/nd/ap1', value: '', type: 'STRING'}, # AP1 engaged
'toggle_ap2': {path: '/nd/ap2', value: '', type: 'STRING'}, # AP2 engaged
'toggle_dep_rwy': {path: '/nd/dep_rwy', value: '', type: 'STRING'}, # Departure runway
'toggle_dest_rwy': {path: '/nd/dest_rwy', value: '', type: 'STRING'}, # Destination runway
};
var ND = canvas.NavDisplay;
var NDCpt = ND.new("instrumentation/efis", toggle_listeners, 'Airbus');
nd_display.main = canvas.new({
"name": "ND",
"size": [1024, 1024],
"view": [1024, 1024],
"mipmapping": 1
});
nd_display.main.addPlacement({"node": "ND.screen"});
var group = nd_display.main.createGroup();
NDCpt.newMFD(group);
NDCpt.update();
setprop("instrumentation/efis/inputs/plan-wpt-index", -1);
print("ND Canvas Initialized!");
}); # fdm-initialized listener callback
# Create Listeners to update the ND, change the property map values to fit
# the properties you use in your own aircraft
var property_map = {
des_apt: "/autopilot/route-manager/destination/airport",
dep_apt: "/autopilot/route-manager/departure/airport",
des_rwy: "/autopilot/route-manager/destination/runway",
dep_rwy: "/autopilot/route-manager/departure/runway",
fplan_active: 'autopilot/route-manager/active',
athr: '/it-autoflight/output/athr',
cur_wp: "/autopilot/route-manager/current-wp",
vnav_node: "/autopilot/route-manager/vnav/",
spd_node: "/autopilot/route-manager/spd/",
holding: "/flight-management/hold",
holding_points: "/flight-management/hold/points",
adf1_frq: 'instrumentation/adf/frequencies/selected-khz',
adf2_frq: 'instrumentation/adf[1]/frequencies/selected-khz',
nav1_frq: 'instrumentation/nav/frequencies/selected-mhz',
nav2_frq: 'instrumentation/nav[1]/frequencies/selected-mhz',
lat_ctrl: '/it-autoflight/output/lat',
ver_ctrl: "/it-autoflight/output/lat",
spd_ctrl: "flight-management/control/spd-ctrl",
};
setlistener("instrumentation/efis/nd/display-mode", func{
var canvas_mode = "instrumentation/efis/nd/canvas-display-mode";
var nd_centered = "instrumentation/efis/inputs/nd-centered";
var mode = getprop("instrumentation/efis/nd/display-mode");
var cvs_mode = 'NAV';
var centered = 1;
if(mode == 'ILS'){
cvs_mode = 'APP';
}
elsif(mode == 'VOR') {
cvs_mode = 'VOR';
}
elsif(mode == 'NAV'){
cvs_mode = 'MAP';
}
elsif(mode == 'ARC'){
cvs_mode = 'MAP';
centered = 0;
}
elsif(mode == 'PLAN'){
cvs_mode = 'PLAN';
}
setprop(canvas_mode, cvs_mode);
setprop(nd_centered, centered);
});
setlistener(property_map.fplan_active, func{
var actv = getprop(property_map.fplan_active);
setprop('instrumentation/efis/nd/route-manager-active', actv);
});
setlistener(property_map.athr, func{
var athr = getprop(property_map.athr);
setprop('instrumentation/efis/nd/athr', (athr == '1'));
});
setlistener(property_map.ver_ctrl, func{
var verctrl = getprop(property_map.ver_ctrl);
setprop('instrumentation/efis/nd/vnav', (verctrl == 'fmgc'));
});
setlistener(property_map.spd_ctrl, func{
var spdctrl = getprop(property_map.spd_ctrl);
setprop('instrumentation/efis/nd/managed-spd', (spdctrl == 'fmgc'));
});
setlistener(property_map.lat_ctrl, func{
var latctrl = getprop(property_map.lat_ctrl);
setprop('instrumentation/efis/nd/lnav', (latctrl == '1'));
});
setlistener("/instrumentation/mcdu/f-pln/disp/first", func{
var first = getprop("/instrumentation/mcdu/f-pln/disp/first");
if(typeof(first) == 'nil') first = -1;
if(getprop('autopilot/route-manager/route/num') == 0) first = -1;
setprop("instrumentation/efis/inputs/plan-wpt-index", first);
});
setlistener('/instrumentation/efis/nd/terrain-on-nd', func{
var terr_on_hd = getprop('/instrumentation/efis/nd/terrain-on-nd');
var alpha = 1;
if(terr_on_hd) alpha = 0.5;
nd_display.main.setColorBackground(0,0,0,alpha);
});
setlistener('instrumentation/nav/frequencies/selected-mhz', func{
var mhz = getprop('instrumentation/nav/frequencies/selected-mhz');
if(mhz == nil) mhz = 0;
setprop('/instrumentation/efis/nd/nav1_frq', mhz);
});
setlistener('instrumentation/nav[1]/frequencies/selected-mhz', func{
var mhz = getprop('instrumentation/nav[1]/frequencies/selected-mhz');
if(mhz == nil) mhz = 0;
setprop('/instrumentation/efis/nd/nav2_frq', mhz);
});
setlistener('instrumentation/adf/frequencies/selected-khz', func{
var khz = getprop('instrumentation/adf/frequencies/selected-khz');
if(khz == nil) khz = 0;
setprop('/instrumentation/efis/nd/adf1_frq', khz);
});
setlistener('instrumentation/adf[1]/frequencies/selected-khz', func{
var khz = getprop('instrumentation/adf[1]/frequencies/selected-khz');
if(khz == nil) khz = 0;
setprop('/instrumentation/efis/nd/adf2_frq', khz);
});
setlistener('flight-management/hold/init', func{
var init = getprop('flight-management/hold/init');
if(init == nil) init = 0;
setprop('/instrumentation/efis/nd/hold_init', init);
});
setlistener("/flight-management/hold/wp", func{
var wpid = getprop("/flight-management/hold/wp");
if(wpid == nil) wpid = '';
setprop('/instrumentation/efis/nd/hold_wp', wpid);
});
setlistener('autopilot/route-manager/route/num', func{
var num = getprop('autopilot/route-manager/route/num');
setprop('/instrumentation/efis/nd/route_num', num);
});
setlistener(property_map.cur_wp, func(){
var curwp = getprop('autopilot/route-manager/current-wp');
setprop('/instrumentation/efis/nd/cur_wp',curwp);
});
setlistener("/flight-management/control/ap1-master", func(){
var ap1 = getprop("/flight-management/control/ap1-master");
setprop('/instrumentation/efis/nd/ap1',ap1);
});
setlistener("/flight-management/control/ap2-master", func(){
var ap2 = getprop("/flight-management/control/ap2-master");
setprop('/instrumentation/efis/nd/ap2',ap2);
});
setlistener("/autopilot/route-manager/departure/runway", func(){
var rwy = getprop("/autopilot/route-manager/departure/runway");
setprop('/instrumentation/efis/nd/dep_rwy',rwy);
});
setlistener("/autopilot/route-manager/destination/runway", func(){
var rwy = getprop("/autopilot/route-manager/destination/runway");
setprop('/instrumentation/efis/nd/dest_rwy',rwy);
});
var showNd = func() {
# The optional second arguments enables creating a window decoration
var dlg = canvas.Window.new([400, 400], "dialog");
dlg.setCanvas( nd_display["main"] );
}

View file

@ -1,34 +1,30 @@
<!--
MD-11 Navigation display
-->
<?xml version="1.0"?>
<PropertyList>
<path>ND_L.ac</path>
<!-- ND left dimmer -->
<animation>
<type>material</type>
<object-name>ND.screen</object-name>
<emission>
<red>1.0</red>
<green>1.0</green>
<blue>1.0</blue>
<factor-prop>/controls/lighting/ndl-norm</factor-prop>
</emission>
</animation>
<animation>
<type>pick</type>
<object-name>ND.screen</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>libraries.showNd();</script>
</binding>
</action>
</animation>
<path>res/ND.ac</path>
<!--animation>
<type>select</type>
<object-name>ND.screen</object-name>
<condition>
<and>
<property>/systems/unused/something</property>
</and>
</condition>
</animation-->
<animation>
<type>pick</type>
<object-name>ND.screen</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>canvas_nd.showNd();</script>
</binding>
</action>
</animation>
</PropertyList>

View file

@ -1,34 +1,30 @@
<!--
MD-11 Navigation display
-->
<?xml version="1.0"?>
<PropertyList>
<path>ND_R.ac</path>
<!-- ND Right Dimmer -->
<animation>
<type>material</type>
<object-name>ND.screen</object-name>
<emission>
<red>1.0</red>
<green>1.0</green>
<blue>1.0</blue>
<factor-prop>/controls/lighting/ndr-norm</factor-prop>
</emission>
</animation>
<animation>
<type>pick</type>
<object-name>ND.screen</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>libraries.showNd();</script>
</binding>
</action>
</animation>
<path>res/ND_R.ac</path>
<!--animation>
<type>select</type>
<object-name>ND_R.screen</object-name>
<condition>
<and>
<property>/systems/unused/something</property>
</and>
</condition>
</animation-->
<animation>
<type>pick</type>
<object-name>ND_R.screen</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>canvas_nd.showNd('right');</script>
</binding>
</action>
</animation>
</PropertyList>

View file

@ -0,0 +1,39 @@
# A3XX ND Implementation
var get_local_path = func(file){
var aircraft_dir = split('/', getprop("/sim/aircraft-dir"))[-1];
return "Aircraft/" ~ aircraft_dir ~ "/Models/Instruments/ND/canvas/"~ file;
};
var version = getprop('sim/version/flightgear');
var v = split('.', version);
version = num(v[0]~'.'~v[1]);
var SymbolLayer = canvas.SymbolLayer;
var SingleSymbolLayer = canvas.SingleSymbolLayer;
var MultiSymbolLayer = canvas.MultiSymbolLayer;
var NavaidSymbolLayer = canvas.NavaidSymbolLayer;
var Symbol = canvas.Symbol;
var Group = canvas.Group;
var Path = canvas.Path;
var DotSym = canvas.DotSym;
var Map = canvas.Map;
var SVGSymbol = canvas.SVGSymbol;
var LineSymbol = canvas.LineSymbol;
var StyleableCacheable = canvas.StyleableCacheable;
var SymbolCache32x32 = canvas.SymbolCache32x32;
var SymbolCache = canvas.SymbolCache;
var Text = canvas.Text;
if(version < 3.2){
io.include('canvas_compat.nas');
}
io.include('ND_config.nas');
io.include('framework/canvas.nas');
io.include('framework/navdisplay.nas');
io.include('framework/MapDrivers.nas');
io.include('loaders.nas');
io.include('helpers.nas');
io.include('style.nas');

View file

@ -0,0 +1,105 @@
var A3XXRouteDriver = {
new: func(){
var m = {
parents: [A3XXRouteDriver],
};
m.init();
return m;
},
init: func(){
me.update();
},
update: func(){
me.flightplan = flightplan();
},
getNumberOfFlightPlans: func(){1},
getFlightPlanType: func(fpNum){'current'},
getFlightPlan: func(fpNum){me.flightplan},
getPlanSize: func(fpNum){me.flightplan.getPlanSize()},
getWP: func(fpNum, idx){me.flightplan.getWP(idx)},
getPlanModeWP: func(plan_wp_idx){me.flightplan.getWP(plan_wp_idx)},
hasDiscontinuity: func(fpNum, wptID){0},
getListeners: func(){[]},
shouldUpdate: func 1
};
var MultiA3XXRouteDriver = {
parents: [A3XXRouteDriver],
new: func(){
var m = {
parents: [MultiA3XXRouteDriver],
_flightplans: [],
currentFlightPlan: 0
};
m.init();
return m;
},
addFlightPlan: func(type, plan){
append(me._flightplans, {
type: type,
flightplan: plan
});
},
removeFlightPlanAtIndex: func(idx){
var sz = size(me._flightplans);
if(idx < sz){
if(sz == 1)
me._flightplans = [];
elsif(sz == 2 and idx == 0)
me._flightplans = [me._flightplans[1]];
elsif(sz == 2 and idx == 1)
pop(me._flightplans);
else {
var subv_l = subvec(me._flightplans, 0, idx);
var subv_r = subvec(me._flightplans, idx + 1);
me._flightplans = subv_l ~ subv_r;
}
}
me.triggerSignal('fp-added');
},
removeFlightPlanOfType: func(type){
var new_vec = [];
foreach(var fp; me._flightplans){
if(fp['type'] != type)
append(new_vec, fp);
}
me._flightplans = new_vec;
me.triggerSignal('fp-removed');
},
getNumberOfFlightPlans: func(){
size(me._flightplans);
},
getFlightPlanType: func(fpNum){
if(fpNum >= size(me._flightplans)) return nil;
var fp = me._flightplans[fpNum];
return fp.type;
},
getFlightPlan: func(fpNum){
if(fpNum >= size(me._flightplans)) return nil;
return me._flightplans[fpNum];
},
getPlanSize: func(fpNum){
if(fpNum >= size(me._flightplans)) return 0;
return me._flightplans[fpNum].getPlanSize();
},
getWP: func(fpNum, idx){
if(fpNum >= size(me._flightplans)) return nil;
var fp = me._flightplans[fpNum].getPlanSize();
return fp.getWP(idx);
},
getPlanModeWP: func(idx){
if(me.currentFlightPlan >= size(me._flightplans)) return nil;
var fp = me._flightplans[me.currentFlightPlan];
return fp.getWP(idx);
},
triggerSignal: func(signal){
setprop(me.signalPath(signal));
},
signalPath: func(signal){
'autopilot/route-manager/signals/rd-'~ signal;
},
getListeners: func(){[
me.getSignal('fp-added'),
me.getSignal('fp-removed')
]}
};

View file

@ -0,0 +1,150 @@
var ND_AIRBUS_SUPPORT = contains(canvas.NDStyles, 'Airbus_v2');
if(!ND_AIRBUS_SUPPORT){
io.include('A3XX_ND.nas');
}# else {
# io.include('ND_config.nas');
#}
io.include('A3XX_ND_drivers.nas');
canvas.NDStyles['Airbus'].options.defaults.route_driver = A3XXRouteDriver.new();
var nd_display = {};
setlistener("sim/signals/fdm-initialized", func() {
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_ndb': {path: '/inputs/NDB', value:0, type:'BOOL'},
'toggle_stations': {path: '/inputs/sta', value:0, type:'BOOL'},
'toggle_vor': {path: '/inputs/VORD', value:0, type:'BOOL'},
'toggle_dme': {path: '/inputs/DME', value:0, type:'BOOL'},
'toggle_cstr': {path: '/inputs/CSTR', 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: '/input/lh-vor-adf',value:0, type:'INT'},
'toggle_rh_vor_adf': {path: '/input/rh-vor-adf',value:0, type:'INT'},
'toggle_display_mode': {path: '/nd/canvas-display-mode', value:'NAV', type:'STRING'},
'toggle_display_type': {path: '/mfd/display-type', value:'LCD', type:'STRING'},
'toggle_true_north': {path: '/mfd/true-north', value:1, type:'BOOL'},
'toggle_track_heading': {path: '/trk-selected', value:0, type:'BOOL'},
'toggle_wpt_idx': {path: '/inputs/plan-wpt-index', value: -1, type: 'INT'},
'toggle_plan_loop': {path: '/nd/plan-mode-loop', value: 0, type: 'INT'},
'toggle_weather_live': {path: '/mfd/wxr-live-enabled', value: 0, type: 'BOOL'},
'toggle_chrono': {path: '/inputs/CHRONO', value: 0, type: 'INT'},
'toggle_xtrk_error': {path: '/mfd/xtrk-error', value: 0, type: 'BOOL'},
'toggle_trk_line': {path: '/mfd/trk-line', value: 0, type: 'BOOL'},
# add new switches here
};
# get a handle to the NavDisplay in canvas namespace (for now), see $FG_ROOT/Nasal/canvas/map/navdisplay.mfd
var ND = canvas.NavDisplay;
## TODO: We want to support multiple independent ND instances here!
# foreach(var pilot; var pilots = [ {name:'cpt', path:'instrumentation/efis',
# name:'fo', path:'instrumentation[1]/efis']) {
##
# set up a new ND instance, under 'instrumentation/efis' and use the
# myCockpit_switches hash to map control properties
var NDCpt = ND.new("instrumentation/efis", myCockpit_switches, 'Airbus');
var NDFo = ND.new("instrumentation/efis[1]", myCockpit_switches, 'Airbus');
nd_display.main = canvas.new({
"name": "ND",
"size": [1024, 1024],
"view": [1024, 1024],
"mipmapping": 1
});
nd_display.right = canvas.new({
"name": "ND",
"size": [1024, 1024],
"view": [1024, 1024],
"mipmapping": 1
});
nd_display.main.addPlacement({"node": "ND.screen"});
nd_display.right.addPlacement({"node": "ND_R.screen"});
var group = nd_display.main.createGroup();
NDCpt.newMFD(group);
NDCpt.update();
var group_r = nd_display.right.createGroup();
NDFo.newMFD(group_r);
NDFo.update();
setprop("instrumentation/efis/inputs/plan-wpt-index", -1);
setprop("instrumentation/efis[1]/inputs/plan-wpt-index", -1);
print("ND Canvas Initialized!");
}); # fdm-initialized listener callback
for(i = 0; i < 2; i = i + 1){
setlistener("instrumentation/efis["~i~"]/nd/display-mode", func(node){
var par = node.getParent().getParent();
var idx = par.getIndex();
var canvas_mode = "instrumentation/efis["~idx~"]/nd/canvas-display-mode";
var nd_centered = "instrumentation/efis["~idx~"]/inputs/nd-centered";
var mode = getprop("instrumentation/efis["~idx~"]/nd/display-mode");
var cvs_mode = 'NAV';
var centered = 1;
if(mode == 'ILS'){
cvs_mode = 'APP';
}
elsif(mode == 'VOR') {
cvs_mode = 'VOR';
}
elsif(mode == 'NAV'){
cvs_mode = 'MAP';
}
elsif(mode == 'ARC'){
cvs_mode = 'MAP';
centered = 0;
}
elsif(mode == 'PLAN'){
cvs_mode = 'PLAN';
}
setprop(canvas_mode, cvs_mode);
setprop(nd_centered, centered);
});
}
#setlistener("/instrumentation/mcdu/f-pln/disp/first", func{
#var first = getprop("/instrumentation/mcdu/f-pln/disp/first");
#if(typeof(first) == 'nil') first = -1;
#if(getprop('autopilot/route-manager/route/num') == 0) first = -1;
#setprop("instrumentation/efis/inputs/plan-wpt-index", first);
#setprop("instrumentation/efis[1]/inputs/plan-wpt-index", first);
#});
setlistener('/instrumentation/efis/nd/terrain-on-nd', func{
var terr_on_hd = getprop('/instrumentation/efis/nd/terrain-on-nd');
var alpha = 1;
if(terr_on_hd) alpha = 0.5;
nd_display.main.setColorBackground(0,0,0,alpha);
});
setlistener('/flight-management/control/capture-leg', func(n){
var capture_leg = n.getValue();
setprop("instrumentation/efis/mfd/xtrk-error", capture_leg);
setprop("instrumentation/efis[1]/mfd/xtrk-error", capture_leg);
setprop("instrumentation/efis/mfd/trk-line", capture_leg);
setprop("instrumentation/efis[1]/mfd/trk-line", capture_leg);
}, 0, 0);
var showNd = func(nd = nil) {
if(nd == nil) nd = 'main';
# The optional second arguments enables creating a window decoration
var dlg = canvas.Window.new([400, 400], "dialog");
dlg.setCanvas( nd_display[nd] );
}

View file

@ -0,0 +1,21 @@
canvas.NDConfig = {
properties: {
des_apt: "/autopilot/route-manager/destination/airport",
dep_apt: "/autopilot/route-manager/departure/airport",
des_rwy: "/autopilot/route-manager/destination/runway",
dep_rwy: "/autopilot/route-manager/departure/runway",
fplan_active: 'autopilot/route-manager/active',
athr: '/it-autoflight/output/athr',
cur_wp: "/autopilot/route-manager/current-wp",
vnav_node: "/autopilot/route-manager/vnav/",
spd_node: "/autopilot/route-manager/spd/",
holding: "/flight-management/hold",
holding_points: "/flight-management/hold/points",
adf1_frq: 'instrumentation/adf/frequencies/selected-khz',
adf2_frq: 'instrumentation/adf[1]/frequencies/selected-khz',
nav1_frq: 'instrumentation/nav/frequencies/selected-mhz',
nav2_frq: 'instrumentation/nav[1]/frequencies/selected-mhz',
lat_ctrl: 'flight-management/control/lat-ctrl',
ver_ctrl: "flight-management/control/ver-ctrl",
}
};

View file

@ -0,0 +1,355 @@
var _MP_dbg_lvl = "info";
#var _MP_dbg_lvl = "alert";
#io.include('Nasal/canvas/MapStructure.nas');
var makedie = func(prefix) func(msg) globals.die(prefix~" "~msg);
var __die = makedie("MapStructure");
var _arg2valarray = func
{
var ret = arg;
while ( typeof(ret) == "vector"
and size(ret) == 1 and typeof(ret[0]) == "vector" )
ret = ret[0];
return ret;
}
var assert_m = func(hash, member)
if (!contains(hash, member))
die("required field not found: '"~member~"'");
var assert_ms = func(hash, members...)
foreach (var m; members)
if (m != nil) assert_m(hash, m);
##
# Combine a specific hash with a default hash, e.g. for
# options/df_options and style/df_style in a SymbolLayer.
#
var default_hash = func(opt, df) {
if (opt != nil and typeof(opt)=='hash') {
if (df != nil and opt != df and !isa(opt, df)) {
if (contains(opt, "parents"))
opt.parents ~= [df];
else
opt.parents = [df];
}
return opt;
} else return df;
}
var try_aux_method = func(obj, method_name) {
var name = "<test%"~id(caller(0)[0])~">";
call(compile("obj."~method_name~"()", name), nil, var err=[]); # try...
#debug.dump(err);
if (size(err)) # ... and either leave caght or rethrow
if (err[1] != name)
die(err[0]);
}
Group.setColor = func(r,g,b, excl = nil){
var children = me.getChildren();
foreach(var e; children){
var do_skip = 0;
if(excl != nil){
foreach(var cl; excl){
if(isa(e, cl)){
do_skip = 1;
continue;
}
}
}
if(!do_skip)
e.setColor(r,g,b);
}
}
Symbol._new = func(m) {
#m.style = m.layer.style;
#m.options = m.layer.options;
if (m.controller != nil) {
temp = m.controller.new(m,m.model);
if (temp != nil)
m.controller = temp;
}
else __die("Symbol._new(): default controller not found");
};
Symbol.del = func() {
if (me.controller != nil)
me.controller.del(me, me.model);
try_aux_method(me.model, "del");
};
SymbolLayer.findsym = func(model, del=0) {
forindex (var i; me.list) {
var e = me.list[i];
#print("List["~i~"]");
#debug.dump(e);
if (Symbol.Controller.equals(e.model, model)) {
if (del) {
# Remove this element from the list
# TODO: maybe C function for this? extend pop() to accept index?
var prev = subvec(me.list, 0, i);
var next = subvec(me.list, i+1);
me.list = prev~next;
#return 1;
}
return e;
}
}
return nil;
};
# to add support for additional ghosts, just append them to the vector below, possibly at runtime:
var supported_ghosts = ['positioned','Navaid','Fix','flightplan-leg','FGAirport'];
var is_positioned_ghost = func(obj) {
var gt = ghosttype(obj);
foreach(var ghost; supported_ghosts) {
if (gt == ghost) return 1; # supported ghost was found
}
return 0; # not a known/supported ghost
};
Symbol.Controller.equals = func(l, r, p=nil) {
if (l == r) return 1;
if (p == nil) {
var ret = Symbol.Controller.equals(l, r, l);
if (ret != nil) return ret;
if (contains(l, "parents")) {
foreach (var p; l.parents) {
var ret = Symbol.Controller.equals(l, r, p);
if (ret != nil) return ret;
}
}
die("Symbol.Controller: no suitable equals() found! Of type: "~typeof(l));
} else {
if (typeof(p) == 'ghost')
if ( is_positioned_ghost(p) )
return l.id == r.id;
else
die("Symbol.Controller: bad/unsupported ghost of type '"~ghosttype(l)~"' (see MapStructure.nas Symbol.Controller.getpos() to add new ghosts)");
if (typeof(p) == 'hash'){
# Somewhat arbitrary convention:
# * l.equals(r) -- instance method, i.e. uses "me" and "arg[0]"
# * parent._equals(l,r) -- class method, i.e. uses "arg[0]" and "arg[1]"
if (contains(p, "equals"))
return l.equals(r);
}
if (contains(p, "_equals"))
return p._equals(l,r);
}
return nil; # scio correctum est
};
canvas.LineSymbol = {
parents:[Symbol],
element_id: nil,
needs_update: 1,
# Static/singleton:
makeinstance: func(name, hash) {
if (!isa(hash, LineSymbol))
die("LineSymbol: OOP error");
return Symbol.add(name, hash);
},
# For the instances returned from makeinstance:
new: func(group, model, controller=nil) {
if (me == nil) die("Need me reference for LineSymbol.new()");
if (typeof(model) != 'vector') die("LineSymbol.new(): need a vector of points");
var m = {
parents: [me],
group: group,
#layer: layer,
model: model,
controller: controller == nil ? me.df_controller : controller,
element: group.createChild(
"path", me.element_id
),
};
append(m.parents, m.element);
Symbol._new(m);
m.init();
return m;
},
# Non-static:
draw: func() {
if (!me.needs_update) return;
#printlog(_MP_dbg_lvl, "redrawing a LineSymbol "~me.layer.type);
me.element.reset();
var cmds = [];
var coords = [];
var cmd = Path.VG_MOVE_TO;
foreach (var m; me.model) {
var (lat,lon) = me.controller.getpos(m);
append(coords,"N"~lat);
append(coords,"E"~lon);
append(cmds,cmd);
cmd = Path.VG_LINE_TO;
}
me.element.setDataGeo(cmds, coords);
me.element.update(); # this doesn't help with flickering, it seems
},
del: func() {
printlog(_MP_dbg_lvl, "LineSymbol.del()");
me.deinit();
call(Symbol.del, nil, me);
me.element.del();
},
# Default wrappers:
init: func() me.draw(),
deinit: func(),
update: func() {
if (me.controller != nil) {
if (!me.controller.update(me, me.model)) return;
elsif (!me.controller.isVisible(me.model)) {
me.element.hide();
return;
}
} else
me.element.show();
me.draw();
},
}; # of LineSymbol
Path.addSegmentGeo = func(cmd, coords...)
{
var coords = _arg2valarray(coords);
var num_coords = me.num_coords[cmd];
if( size(coords) != num_coords )
debug.warn
(
"Invalid number of arguments (expected " ~ num_coords ~ ")"
);
else
{
me.setInt("cmd[" ~ (me._last_cmd += 1) ~ "]", cmd);
for(var i = 0; i < num_coords; i += 1)
me.set("coord-geo[" ~ (me._last_coord += 1) ~ "]", coords[i]);
}
return me;
}
Path.arcGeo = func(cmd, rx,ry,unk,lat,lon){
if(cmd < 18 and cmd > 24){
debug.warn("Invalid command " ~ cmd);
return me;
}
else
{
me.setInt("cmd[" ~ (me._last_cmd += 1) ~ "]", cmd);
#for(var i = 0; i < num_coords; i += 1)
me.setDouble("coord[" ~ (me._last_coord += 1) ~ "]", rx);
me.setDouble("coord[" ~ (me._last_coord += 1) ~ "]", ry);
me.setDouble("coord[" ~ (me._last_coord += 1) ~ "]", unk);
me.setDouble("coord-geo[N" ~ (me._last_coord += 1) ~ "]", lat);
me.setDouble("coord-geo[E" ~ (me._last_coord += 1) ~ "]", lat);
}
return me;
}
SymbolLayer.onRemoved = func(model) {
#print('onRemoved');
#debug.dump(model);
var sym = me.findsym(model, 1);
if (sym == nil) die("model not found");
#print(typeof(model.del));
#call(func sym.del, nil, var err = []);
sym.del();
#print('ERR CHK');
#debug.dump(err);
# ignore errors
# TODO: ignore only missing member del() errors? and only from the above line?
# Note: die(err[0]) rethrows it; die(err[0]~"") does not.
}
Map.addLayer = func(factory, type_arg=nil, priority=nil){
if(contains(me.layers, type_arg))
print("addLayer() warning: overwriting existing layer:", type_arg);
# print("addLayer():", type_arg);
# Argument handling
if (type_arg != nil)
var type = factory.get(type_arg);
else var type = factory;
var the_layer = me.layers[type_arg]= type.new(me);
the_layer.map = me;
if (priority == nil)
priority = type.df_priority;
if (priority != nil)
me.layers[type_arg].setInt("z-index", priority);
return me;
}
Map.getLat = func me.get("ref-lat");
Map.getLon = func me.get("ref-lon");
Map.getHdg = func me.get("hdg");
Map.getAlt = func me.get("altitude");
Map.getRange = func me.get("range");
Map.getLatLon = func [me.get("ref-lat"), me.get("ref-lon")];
Map.getPosCoord = func {
var (lat, lon) = (me.get("ref-lat"),
me.get("ref-lon"));
var alt = me.get("altitude");
if (lat == nil or lon == nil) {
if (contains(me, "coord")) {
debug.warn("canvas.Map: lost ref-lat and/or ref-lon source");
}
return nil;
}
if (!contains(me, "coord")) {
me.coord = geo.Coord.new();
var m = me;
me.coord.update = func m.getPosCoord();
}
me.coord.set_latlon(lat,lon,alt or 0);
return me.coord;
}
SymbolLayer.new = func(group, controller=nil) {
var m = {
parents: [me],
map: group,
group: group.createChild("group", me.id), # TODO: the id is not properly set, but would be useful for debugging purposes (VOR, FIXES, NDB etc)
list: [],
};
m.searcher = geo.PositionedSearch.new(me.searchCmd, me.onAdded, me.onRemoved, m);
# FIXME: hack to expose type of layer:
if (caller(1)[1] == Map.addLayer) {
var this_type = caller(1)[0].type_arg;
if (this_type != nil)
m.group.set("symbol-layer-type", this_type);
}
if (controller == nil)
#controller = SymbolLayer.Controller.new(me.type, m);
controller = me.df_controller;
assert_m(controller, "parents");
if (controller.parents[0] == SymbolLayer.Controller)
controller = controller.new(m);
assert_m(controller, "parents");
assert_m(controller.parents[0], "parents");
if (controller.parents[0].parents[0] != SymbolLayer.Controller)
die("OOP error");
m.controller = controller;
m.update();
return m;
};
canvas.SingleSymbolLayer = {
parents: [SymbolLayer]
};
canvas.MultiSymbolLayer = {
parents: [SymbolLayer]
};
canvas.NavaidSymbolLayer = {
parents: [canvas.MultiSymbolLayer]
};

View file

@ -0,0 +1,116 @@
canvas.RouteDriver = {
new: func(){
var m = {
parents: [canvas.RouteDriver],
};
m.init();
return m;
},
init: func(){
me.update();
},
update: func(){
me.flightplan = flightplan();
},
getNumberOfFlightPlans: func(){1},
getFlightPlanType: func(fpNum){'active'},
getFlightPlan: func(fpNum){me.flightplan},
getPlanSize: func(fpNum){me.flightplan.getPlanSize()},
getWP: func(fpNum, idx){me.flightplan.getWP(idx)},
getListeners: func(){[]},
getPlanModeWP: func(plan_wp_idx){me.flightplan.getWP(plan_wp_idx)},
hasDiscontinuity: func(fpNum, wpt){0},
getHoldPattern: func(fpNum, wpt){nil},
getHoldPatterns: func(fpNum){[]},
shouldUpdate: func 1,
shouldDisplayWP: func(fpNum, idx) 1,
getCurrentWPIdx: func(fpNum) getprop('autopilot/route-manager/current-wp'),
getTimeConstraint: func (fpNum, wp_idx) {nil}
};
canvas.MultiRouteDriver = {
parents: [canvas.RouteDriver],
new: func(){
var m = {
parents: [MultiRouteDriver],
_flightplans: [],
currentFlightPlan: 0
};
m.init();
return m;
},
addFlightPlan: func(type, plan){
append(me._flightplans, {
type: type,
flightplan: plan
});
},
removeFlightPlanAtIndex: func(idx){
var sz = size(me._flightplans);
if(idx < sz){
if(sz == 1)
me._flightplans = [];
elsif(sz == 2 and idx == 0)
me._flightplans = [me._flightplans[1]];
elsif(sz == 2 and idx == 1)
pop(me._flightplans);
else {
var subv_l = subvec(me._flightplans, 0, idx);
var subv_r = subvec(me._flightplans, idx + 1);
me._flightplans = subv_l ~ subv_r;
}
}
me.triggerSignal('fp-added');
},
removeFlightPlanOfType: func(type){
var new_vec = [];
foreach(var fp; me._flightplans){
if(fp['type'] != type)
append(new_vec, fp);
}
me._flightplans = new_vec;
me.triggerSignal('fp-removed');
},
getNumberOfFlightPlans: func(){
size(me._flightplans);
},
getFlightPlanType: func(fpNum){
if(fpNum >= size(me._flightplans)) return nil;
var fp = me._flightplans[fpNum];
return fp.type;
},
getFlightPlan: func(fpNum){
if(fpNum >= size(me._flightplans)) return nil;
return me._flightplans[fpNum];
},
getPlanSize: func(fpNum){
if(fpNum >= size(me._flightplans)) return 0;
return me._flightplans[fpNum].getPlanSize();
},
getWP: func(fpNum, idx){
if(fpNum >= size(me._flightplans)) return nil;
var fp = me._flightplans[fpNum];
return fp.getWP(idx);
},
getPlanModeWP: func(idx){
if(me.currentFlightPlan >= size(me._flightplans)) return nil;
var fp = me._flightplans[me.currentFlightPlan];
return fp.getWP(idx);
},
triggerSignal: func(signal){
setprop(me.signalPath(signal));
},
signalPath: func(signal){
'autopilot/route-manager/signals/rd-'~ signal;
},
getListeners: func(){[
me.getSignal('fp-added'),
me.getSignal('fp-removed')
]},
getCurrentWPIdx: func(fpNum) {
var fp = me.getFlightPlan(fpNum);
var wp = fp.getWP();
if (wp == nil) return -1;
return wp.index;
}
};

View file

@ -0,0 +1,303 @@
var assert_m = canvas.assert_m;
# --------------------------------
# From FGDATA/Nasal/canvas/api.nas
# --------------------------------
# Recursively get all children of class specified by first param
canvas.Group.getChildrenOfType = func(type, array = nil){
var children = array;
if(children == nil)
children = [];
var my_children = me.getChildren();
if(typeof(type) != 'vector')
type = [type];
foreach(var c; my_children){
foreach(var t; type){
if(isa(c, t)){
append(children, c);
}
}
if(isa(c, canvas.Group)){
c.getChildrenOfType(type, children);
}
}
return children;
};
# Set color to children of type Path and Text. It is possible to optionally
# specify which types of children should be affected by passing a vector as
# the last agrument, ie. my_group.setColor(1,1,1,[Path]);
canvas.Group.setColor = func(){
var color = arg;
var types = [Path, Text];
var arg_c = size(color);
if(arg_c > 1 and typeof(color[-1]) == 'vector'){
types = color[-1];
color = subvec(color, 0, arg_c - 1);
}
var children = me.getChildrenOfType(types);
if(typeof(color) == 'vector'){
var first = color[0];
if(typeof(first) == 'vector')
color = first;
}
foreach(var c; children)
c.setColor(color);
};
canvas.Map.addLayer = func(factory, type_arg=nil, priority=nil, style=nil, opts=nil, visible=1)
{
if(contains(me.layers, type_arg))
printlog("warn", "addLayer() warning: overwriting existing layer:", type_arg);
var options = opts;
# Argument handling
if (type_arg != nil) {
var layer = factory.new(type:type_arg, group:me, map:me, style:style, options:options, visible:visible);
var type = factory.get(type_arg);
var key = type_arg;
} else {
var layer = factory.new(group:me, map:me, style:style, options:options, visible:visible);
var type = factory;
var key = factory.type;
}
me.layers[type_arg] = layer;
if (priority == nil)
priority = type.df_priority;
if (priority != nil)
layer.group.setInt("z-index", priority);
return layer; # return new layer to caller() so that we can directly work with it, i.e. to register event handlers (panning/zooming)
};
# -----------------------------------------
# From FGDATA/Nasal/canvas/MapStructure.nas
# -----------------------------------------
var opt_member = func(h,k) {
if (contains(h, k)) return h[k];
if (contains(h, "parents")) {
var _=h.parents;
for (var i=0;i<size(_);i+=1){
var v = opt_member(_[i], k);
if (v != nil) return v;
}
}
return nil;
};
# Symbol
canvas.Symbol.formattedString = func(frmt, model_props){
if(me.model == nil) return frmt;
var args = [];
foreach(var prop; model_props){
if(contains(me.model, prop)){
var val = me.model[prop];
var tp = typeof(val);
if(tp != 'scalar'){
val = '';
#printlog("warn", "formattedString: invalid type for "~prop~" (" ~ tp ~ ")");
} else {
append(args, val);
}
}
}
return call(sprintf, [frmt] ~ args);
};
canvas.Symbol.getOption = func(name, default = nil){
var opt = me.options;
if(opt == nil)
opt = me.layer.options;
if(opt == nil) return default;
var val = opt_member(opt, name);
if(val == nil) return default;
return val;
};
canvas.Symbol.getStyle = func(name, default = nil){
var st = me.style;
if(st == nil)
st = me.layer.style;
if(st == nil) return default;
var val = opt_member(st, name);
if(typeof(val) == 'func'){
val = (call(val,[],me));
}
if(val == nil) return default;
return val;
};
canvas.Symbol.getLabelFromModel = func(default_val = nil){
if(me.model == nil) return default_val;
if(default_val == nil and contains(me.model, 'id'))
default_val = me.model.id;
var label_content = me.getOption('label_content');
if(label_content == nil) return default_val;
if(typeof(label_content) == 'scalar')
label_content = [label_content];
var format_s = me.getOption('label_format');
var label = '';
if(format_s == nil){
format_s = "%s";
}
return me.formattedString(format_s, label_content);
};
canvas.Symbol.callback = func(name, args...){
name = name ~'_callback';
var f = me.getOption(name);
if(typeof(f) == 'func'){
return call(f, args, me);
}
};
# DotSym
canvas.DotSym.update = func() {
if (me.controller != nil) {
if (!me.controller.update(me, me.model)) return;
elsif (!me.controller.isVisible(me.model)) {
me.element.hide();
return;
}
} else
me.element.show();
me.draw();
if(me.getOption('disable_position', 0)) return; # << CHECK FOR OPTION 'disable_position'
var pos = me.controller.getpos(me.model);
if (size(pos) == 2)
pos~=[nil]; # fall through
if (size(pos) == 3)
var (lat,lon,rotation) = pos;
else __die("DotSym.update(): bad position: "~debug.dump(pos));
# print(me.model.id, ": Position lat/lon: ", lat, "/", lon);
me.element.setGeoPosition(lat,lon);
if (rotation != nil)
me.element.setRotation(rotation);
};
# SVGSymbol
canvas.SVGSymbol.init = func() {
me.callback('init_before');
var opt_path = me.getStyle('svg_path');
if(opt_path != nil)
me.svg_path = opt_path;
if (!me.cacheable) {
if(me.svg_path != nil and me.svg_path != '')
canvas.parsesvg(me.element, me.svg_path);
# hack:
if (var scale = me.layer.style['scale_factor'])
me.element.setScale(scale);
if ((var transl = me.layer.style['translate']) != nil)
me.element.setTranslation(transl);
} else {
__die("cacheable not implemented yet!");
}
me.callback('init_after');
me.draw();
};
canvas.SVGSymbol.draw = func{
me.callback('draw');
};
# SymbolLayer
canvas.SymbolLayer._new = func(m, style, controller, options) {
# print("SymbolLayer setup options:", m.options!=nil);
m.style = default_hash(style, m.df_style);
m.options = default_hash(options, m.df_options);
if (controller == nil)
controller = m.df_controller;
assert_m(controller, "parents");
if (controller.parents[0] == SymbolLayer.Controller)
controller = controller.new(m);
assert_m(controller, "parents");
assert_m(controller.parents[0], "parents");
if (controller.parents[0].parents[0] != SymbolLayer.Controller)
__die("MultiSymbolLayer: OOP error");
if(options != nil){ # << CHECK FOR CONFIGURABLE LISTENERS
var listeners = opt_member(controller, 'listeners');
var listen = opt_member(options, 'listen');
if (listen != nil and listeners != nil){
var listen_tp = typeof(listen);
if(listen_tp != 'vector' and listen_tp != 'scalar')
__die("Options 'listen' cannot be a "~ listen_tp);
if(typeof(listen) == 'scalar')
listen = [listen];
foreach(var node_name; listen){
var node = opt_member(options, node_name);
if(node == nil)
node = node_name;
append(controller.listeners,
setlistener(node, func call(m.update,[],m),0,0));
}
}
}
m.controller = controller;
};
# LineSymbol
canvas.LineSymbol.new = func(group, layer, model, controller=nil) {
if (me == nil) __die("Need me reference for LineSymbol.new()");
if (typeof(model) != 'vector') {
if(typeof(model) == 'hash'){
if(!contains(model, 'path'))
canvas.__die("LineSymbol.new(): model hash requires path");
}
else canvas.__die("LineSymbol.new(): need a vector of points or a hash");
}
var m = {
parents: [me],
group: group,
layer: layer,
model: model,
controller: controller == nil ? me.df_controller : controller,
element: group.createChild(
"path", me.element_id
),
};
append(m.parents, m.element);
canvas.Symbol._new(m);
m.init();
return m;
};
# Non-static:
canvas.LineSymbol.draw = func() {
me.callback('draw_before');
if (!me.needs_update) return;
#printlog(_MP_dbg_lvl, "redrawing a LineSymbol "~me.layer.type);
me.element.reset();
var cmds = [];
var coords = [];
var cmd = canvas.Path.VG_MOVE_TO;
var path = me.model;
if(typeof(path) == 'hash'){
path = me.model.path;
if(path == nil)
canvas.__die("LineSymbol model requires a 'path' member (vector)");
}
foreach (var m; path) {
if(size(keys(m)) >= 2){
var (lat,lon) = me.controller.getpos(m);
append(coords,"N"~lat);
append(coords,"E"~lon);
append(cmds,cmd);
cmd = canvas.Path.VG_LINE_TO;
} else {
cmd = canvas.Path.VG_MOVE_TO;
}
}
me.element.setDataGeo(cmds, coords);
me.element.update(); # this doesn't help with flickering, it seems
me.callback('draw_after');
};

View file

@ -0,0 +1,582 @@
# Override FGDATA/Nasal/canvas/map/navdisplay.mfd
var default_hash = canvas.default_hash;
var _MP_dbg_lvl = canvas._MP_dbg_lvl;
var assert_m = canvas.assert_m;
var wxr_live_tree = "/instrumentation/wxr";
canvas.NavDisplay.set_switch = func(s, v) {
var switch = me.efis_switches[s];
if(switch == nil) return nil;
var path = me.efis_path ~ switch.path ;
#print(s,":Getting switch prop:", path);
setprop( path, v );
};
canvas.NavDisplay.get_nav_path = func (type, idx) {
var name = (type == 'dme' ? type : 'nav');
var path = 'instrumentation/%s[%d]/';
var indexes = me.radio_cfg[type];
if (indexes != nil) {
idx = indexes[idx];
}
return sprintf(path, name, idx);
};
canvas.NavDisplay.newMFD = func(canvas_group, parent=nil, nd_options=nil, update_time=0.05)
{
if (me.inited) die("MFD already was added to scene");
me.range_dependant_layers = [];
me.always_update_layers = {};
me.inited = 1;
me.update_timer = maketimer(update_time, func me.update() );
me.nd = canvas_group;
me.canvas_handle = parent;
me.df_options = nil;
if(contains(me.nd_style, 'options'))
me.df_options = me.nd_style.options;
nd_options = default_hash(nd_options, me.df_options);
me.options = nd_options;
me.route_driver = nil;
if(contains(me.options, 'route_driver')){
me.route_driver = me.options.route_driver;
}
elsif(contains(me.options, 'defaults')){
if(contains(me.options.defaults, 'route_driver'))
me.route_driver = me.options.defaults.route_driver;
}
me.radio_cfg = me.options['radio'];
if (me.radio_cfg == nil) me.radio_cfg = {};
# load the specified SVG file into the me.nd group and populate all sub groups
canvas.parsesvg(me.nd, me.nd_style.svg_filename, {'font-mapper': me.nd_style.font_mapper});
me.symbols = {}; # storage for SVG elements, to avoid namespace pollution (all SVG elements end up here)
foreach(var feature; me.nd_style.features ) {
me.symbols[feature.id] = me.nd.getElementById(feature.id).updateCenter();
if(contains(feature.impl,'init')) feature.impl.init(me.nd, feature); # call The element's init code (i.e. updateCenter)
}
### this is the "old" method that's less flexible, we want to use the style hash instead (see above)
# because things are much better configurable that way
# now look up all required SVG elements and initialize member fields using the same name to have a convenient handle
foreach(var element; ["dmeLDist","dmeRDist","dmeL","dmeR","vorL","vorR","vorLId","vorRId",
"status.wxr","status.wpt","status.sta","status.arpt"])
me.symbols[element] = me.nd.getElementById(element);
# load elements from vector image, and create instance variables using identical names, and call updateCenter() on each
# anything that needs updatecenter called, should be added to the vector here
#
foreach(var element; ["staArrowL2","staArrowR2","staFromL2","staToL2","staFromR2","staToR2",
"hdgTrk","trkInd","hdgBug","HdgBugCRT","TrkBugLCD","HdgBugLCD","curHdgPtr",
"HdgBugCRT2","TrkBugLCD2","HdgBugLCD2","hdgBug2","selHdgLine","selHdgLine2","curHdgPtr2",
"staArrowL","staArrowR","staToL","staFromL","staToR","staFromR"] )
me.symbols[element] = me.nd.getElementById(element).updateCenter();
me.map = me.nd.createChild("map","map")
.set("clip", "rect(124, 1024, 1024, 0)")
.set("screen-range", 700)
.set('z-index',-1);
me.update_sub(); # init some map properties based on switches
var vor1_path = me.get_nav_path('vor', 0);
var vor2_path = me.get_nav_path('vor', 1);
# predicate for the draw controller
var is_tuned = func(freq) {
var nav1=getprop(vor1_path~ "frequencies/selected-mhz");
var nav2=getprop(vor1_path~ "frequencies/selected-mhz");
if (freq == nav1 or freq == nav2) return 1;
return 0;
}
# another predicate for the draw controller
var get_course_by_freq = func(freq) {
if (freq == getprop(vor1_path~ "frequencies/selected-mhz"))
return getprop(vor1_path~ "radials/selected-deg");
else
return getprop(vor2_path~ "radials/selected-deg");
}
var get_current_position = func {
delete(caller(0)[0], "me"); # remove local me, inherit outer one
return [
me.aircraft_source.get_lat(), me.aircraft_source.get_lon()
];
}
# a hash with controller callbacks, will be passed onto draw routines to customize behavior/appearance
# the point being that draw routines don't know anything about their frontends (instrument or GUI dialog)
# so we need some simple way to communicate between frontend<->backend until we have real controllers
# for now, a single controller hash is shared by most layers - unsupported callbacks are simply ignored by the draw files
#
var controller = {
parents: [canvas.Map.Controller],
_pos: nil, _time: nil,
is_tuned:is_tuned,
get_tuned_course:get_course_by_freq,
get_position: get_current_position,
new: func(map) return { parents:[controller], map:map },
should_update_all: func {
# TODO: this is just copied from aircraftpos.controller,
# it really should be moved to somewhere common and reused
# and extended to fully differentiate between "static"
# and "volatile" layers.
var pos = me.map.getPosCoord();
if (pos == nil) return 0;
var time = systime();
if (me._pos == nil)
me._pos = geo.Coord.new(pos);
else {
var dist_m = me._pos.direct_distance_to(pos);
# 2 NM until we update again
if (dist_m < 2 * NM2M) return 0;
# Update at most every 4 seconds to avoid excessive stutter:
elsif (time - me._time < 4) return 0;
}
#print("update aircraft position");
var (x,y,z) = pos.xyz();
me._pos.set_xyz(x,y,z);
me._time = time;
return 1;
},
};
me.map.setController(controller);
###
# set up various layers, controlled via callbacks in the controller hash
# revisit this code once Philosopher's "Smart MVC Symbols/Layers" work is committed and integrated
# helper / closure generator
var make_event_handler = func(predicate, layer) func predicate(me, layer);
me.layers={}; # storage container for all ND specific layers
# look up all required layers as specified per the NDStyle hash and do the initial setup for event handling
var default_opts = me.options != nil and contains(me.options, 'defaults') ? me.options.defaults : nil;
foreach(var layer; me.nd_style.layers) {
if(layer['disabled']) continue; # skip this layer
#print("newMFD(): Setting up ND layer:", layer.name);
var the_layer = nil;
if(!layer['isMapStructure']) # set up an old INEFFICIENT and SLOW layer
the_layer = me.layers[layer.name] = canvas.MAP_LAYERS[layer.name].new( me.map, layer.name, controller );
else {
printlog(_MP_dbg_lvl, "Setting up MapStructure-based layer for ND, name:", layer.name);
var opt = me.options != nil and me.options[layer.name] != nil ? me.options[layer.name] :nil;
if(opt == nil and contains(layer, 'options'))
opt = layer.options;
if(opt != nil and default_opts != nil)
opt = default_hash(opt, default_opts);
#elsif(default_opts != nil)
# opt = default_opts;
var style = nil;
if(contains(layer, 'style'))
style = layer.style;
#print("Options is: ", opt!=nil?"enabled":"disabled");
#debug.dump(opt);
me.map.addLayer(
factory: canvas.SymbolLayer,
type_arg: layer.name,
opts: opt,
visible:0,
style: style,
priority: layer['z-index']
);
#me.map.addLayer(canvas.SymbolLayer, layer.name, layer['z-index'], style, opt, 0);
the_layer = me.layers[layer.name] = me.map.getLayer(layer.name);
if(opt != nil and contains(opt, 'range_dependant')){
if(opt.range_dependant)
append(me.range_dependant_layers, the_layer);
}
if(contains(layer, 'always_update'))
me.always_update_layers[layer.name] = layer.always_update;
if (1) (func {
var l = layer;
var _predicate = l.predicate;
l.predicate = func {
var t = systime();
call(_predicate, arg, me);
printlog(_MP_dbg_lvl, "Took "~((systime()-t)*1000)~"ms to update layer "~l.name);
}
})();
}
# now register all layer specific notification listeners and their corresponding update predicate/callback
# pass the ND instance and the layer handle to the predicate when it is called
# so that it can directly access the ND instance and its own layer (without having to know the layer's name)
var event_handler = make_event_handler(layer.predicate, the_layer);
foreach(var event; layer.update_on) {
# this handles timers
if (typeof(event)=='hash' and contains(event, 'rate_hz')) {
#print("FIXME: navdisplay.mfd timer handling is broken ATM");
var job=me.addtimer(1/event.rate_hz, event_handler);
job.start();
}
# and this listeners
else
# print("Setting up subscription:", event, " for ", layer.name, " handler id:", id(event_handler) );
me.listen_switch(event, event_handler);
} # foreach event subscription
# and now update/init each layer once by calling its update predicate for initialization
event_handler();
} # foreach layer
#print("navdisplay.mfd:ND layer setup completed");
# start the update timer, which makes sure that the update() will be called
me.update_timer.start();
# TODO: move this to RTE.lcontroller ?
me.listen("/autopilot/route-manager/current-wp", func(activeWp) {
canvas.updatewp( activeWp.getValue() );
});
};
canvas.NavDisplay.update_sub = func(){
# Variables:
var userLat = me.aircraft_source.get_lat();
var userLon = me.aircraft_source.get_lon();
var userGndSpd = me.aircraft_source.get_gnd_spd();
var userVSpd = me.aircraft_source.get_vspd();
var dispLCD = me.get_switch('toggle_display_type') == "LCD";
# Heading update
var userHdgMag = me.aircraft_source.get_hdg_mag();
var userHdgTru = me.aircraft_source.get_hdg_tru();
var userTrkMag = me.aircraft_source.get_trk_mag();
var userTrkTru = me.aircraft_source.get_trk_tru();
if(me.get_switch('toggle_true_north')) {
var userHdg=userHdgTru;
me.userHdg=userHdgTru;
var userTrk=userTrkTru;
me.userTrk=userTrkTru;
} else {
var userHdg=userHdgMag;
me.userHdg=userHdgMag;
var userTrk=userTrkMag;
me.userTrk=userTrkMag;
}
# this should only ever happen when testing the experimental AI/MP ND driver hash (not critical)
# or when an error occurs (critical)
if (!userHdg or !userTrk or !userLat or !userLon) {
print("aircraft source invalid, returning !");
return;
}
if (me.aircraft_source.get_gnd_spd() < 80) {
userTrk = userHdg;
me.userTrk=userHdg;
}
if((me.in_mode('toggle_display_mode', ['MAP']) and me.get_switch('toggle_display_type') == "CRT")
or (me.get_switch('toggle_track_heading') and me.get_switch('toggle_display_type') == "LCD"))
{
userHdgTrk = userTrk;
me.userHdgTrk = userTrk;
userHdgTrkTru = userTrkTru;
me.symbols.hdgTrk.setText("TRK");
} else {
userHdgTrk = userHdg;
me.userHdgTrk = userHdg;
userHdgTrkTru = userHdgTru;
me.symbols.hdgTrk.setText("HDG");
}
# First, update the display position of the map
var oldRange = me.map.getRange();
var pos = {
lat: nil, lon: nil,
alt: nil, hdg: nil,
range: nil,
};
# reposition the map, change heading & range:
var pln_wpt_idx = getprop(me.efis_path ~ "/inputs/plan-wpt-index");
if(me.in_mode('toggle_display_mode', ['PLAN']) and pln_wpt_idx >= 0) {
if(me.route_driver != nil){
var wp = me.route_driver.getPlanModeWP(pln_wpt_idx);
if(wp != nil){
pos.lat = wp.wp_lat;
pos.lon = wp.wp_lon;
} else {
pos.lat = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/latitude-deg");
pos.lon = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/longitude-deg");
}
} else {
pos.lat = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/latitude-deg");
pos.lon = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/longitude-deg");
}
} else {
pos.lat = userLat;
pos.lon = userLon;
}
if(me.in_mode('toggle_display_mode', ['PLAN'])) {
pos.hdg = 0;
pos.range = me.rangeNm()*2
} else {
pos.range = me.rangeNm(); # avoid this here, use a listener instead
pos.hdg = userHdgTrkTru;
}
if(me.options != nil and (var pos_callback = me.options['position_callback']) != nil)
pos_callback(me, pos);
call(me.map.setPos, [pos.lat, pos.lon], me.map, pos);
if(pos.range != oldRange){
foreach(l; me.range_dependant_layers){
l.update();
}
}
};
canvas.NavDisplay.update = func() # FIXME: This stuff is still too aircraft specific, cannot easily be reused by other aircraft
{
var _time = systime();
# Disables WXR Live if it's not enabled. The toggle_weather_live should be common to all
# ND instances.
var wxr_live_enabled = getprop(wxr_live_tree~'/enabled');
if(wxr_live_enabled == nil or wxr_live_enabled == '')
wxr_live_enabled = 0;
me.set_switch('toggle_weather_live', wxr_live_enabled);
call(me.update_sub, nil, nil, caller(0)[0]); # call this in the same namespace to "steal" its variables
# MapStructure update!
if (me.map.controller.should_update_all()) {
me.map.update();
} else {
# TODO: ugly list here
# FIXME: use a VOLATILE layer helper here that handles TFC, APS, WXR etc ?
var update_layers = me.always_update_layers;
me.map.update(func(layer) contains(update_layers, layer.type));
}
# Other symbol update
# TODO: should be refactored!
var translation_callback = nil;
if(me.options != nil)
translation_callback = me.options['translation_callback'];
if(typeof(translation_callback) == 'func'){
var trsl = translation_callback(me);
me.map.setTranslation(trsl.x, trsl.y);
} else {
if(me.in_mode('toggle_display_mode', ['PLAN']))
me.map.setTranslation(512,512);
elsif(me.get_switch('toggle_centered'))
me.map.setTranslation(512,565);
else
me.map.setTranslation(512,824);
}
var vor1_path = me.get_nav_path('vor', 0);
var vor2_path = me.get_nav_path('vor', 1);
var dme1_path = me.get_nav_path('dme', 0);
var dme2_path = me.get_nav_path('dme', 1);
if(me.get_switch('toggle_rh_vor_adf') == 1) {
me.symbols.vorR.setText("VOR R");
me.symbols.vorR.setColor(0.195,0.96,0.097);
me.symbols.dmeR.setText("DME");
me.symbols.dmeR.setColor(0.195,0.96,0.097);
if(getprop(vor2_path~ "in-range"))
me.symbols.vorRId.setText(getprop(vor2_path~ "nav-id"));
else
me.symbols.vorRId.setText(getprop(vor2_path~ "frequencies/selected-mhz-fmt"));
me.symbols.vorRId.setColor(0.195,0.96,0.097);
if(getprop(dme2_path~ "in-range"))
me.symbols.dmeRDist.setText(sprintf("%3.1f",getprop(dme2_path~ "indicated-distance-nm")));
else me.symbols.dmeRDist.setText(" ---");
me.symbols.dmeRDist.setColor(0.195,0.96,0.097);
} elsif(me.get_switch('toggle_rh_vor_adf') == -1) {
me.symbols.vorR.setText("ADF R");
me.symbols.vorR.setColor(0,0.6,0.85);
me.symbols.dmeR.setText("");
me.symbols.dmeR.setColor(0,0.6,0.85);
if((var navident=getprop("instrumentation/adf[1]/ident")) != "")
me.symbols.vorRId.setText(navident);
else me.symbols.vorRId.setText(sprintf("%3d",getprop("instrumentation/adf[1]/frequencies/selected-khz")));
me.symbols.vorRId.setColor(0,0.6,0.85);
me.symbols.dmeRDist.setText("");
me.symbols.dmeRDist.setColor(0,0.6,0.85);
} else {
me.symbols.vorR.setText("");
me.symbols.dmeR.setText("");
me.symbols.vorRId.setText("");
me.symbols.dmeRDist.setText("");
}
# Hide heading bug 10 secs after change
var vhdg_bug = getprop("autopilot/settings/heading-bug-deg") or 0;
var hdg_bug_active = getprop("autopilot/settings/heading-bug-active");
if (hdg_bug_active == nil)
hdg_bug_active = 1;
if((me.in_mode('toggle_display_mode', ['MAP']) and me.get_switch('toggle_display_type') == "CRT")
or (me.get_switch('toggle_track_heading') and me.get_switch('toggle_display_type') == "LCD"))
{
me.symbols.trkInd.setRotation(0);
me.symbols.curHdgPtr.setRotation((userHdg-userTrk)*D2R);
me.symbols.curHdgPtr2.setRotation((userHdg-userTrk)*D2R);
}
else
{
me.symbols.trkInd.setRotation((userTrk-userHdg)*D2R);
me.symbols.curHdgPtr.setRotation(0);
me.symbols.curHdgPtr2.setRotation(0);
}
if(!me.in_mode('toggle_display_mode', ['PLAN']))
{
var hdgBugRot = (vhdg_bug-userHdgTrk)*D2R;
me.symbols.selHdgLine.setRotation(hdgBugRot);
me.symbols.hdgBug.setRotation(hdgBugRot);
me.symbols.hdgBug2.setRotation(hdgBugRot);
me.symbols.selHdgLine2.setRotation(hdgBugRot);
}
var staPtrVis = !me.in_mode('toggle_display_mode', ['PLAN']);
if((me.in_mode('toggle_display_mode', ['MAP']) and me.get_switch('toggle_display_type') == "CRT")
or (me.get_switch('toggle_track_heading') and me.get_switch('toggle_display_type') == "LCD"))
{
var vorheading = userTrkTru;
var adfheading = userTrkMag;
}
else
{
var vorheading = userHdgTru;
var adfheading = userHdgMag;
}
if(getprop(vor1_path~ "heading-deg") != nil)
var nav0hdg=getprop(vor1_path~ "heading-deg") - vorheading;
if(getprop(vor2_path~ "heading-deg") != nil)
var nav1hdg=getprop(vor2_path~ "heading-deg") - vorheading;
var adf0hdg=getprop("instrumentation/adf/indicated-bearing-deg");
var adf1hdg=getprop("instrumentation/adf[1]/indicated-bearing-deg");
if(!me.get_switch('toggle_centered'))
{
if(me.in_mode('toggle_display_mode', ['PLAN']))
me.symbols.trkInd.hide();
else
me.symbols.trkInd.show();
if((getprop(vor1_path~ "in-range") and me.get_switch('toggle_lh_vor_adf') == 1)) {
me.symbols.staArrowL.setVisible(staPtrVis);
me.symbols.staToL.setColor(0.195,0.96,0.097);
me.symbols.staFromL.setColor(0.195,0.96,0.097);
me.symbols.staArrowL.setRotation(nav0hdg*D2R);
}
elsif(getprop("instrumentation/adf/in-range") and (me.get_switch('toggle_lh_vor_adf') == -1)) {
me.symbols.staArrowL.setVisible(staPtrVis);
me.symbols.staToL.setColor(0,0.6,0.85);
me.symbols.staFromL.setColor(0,0.6,0.85);
me.symbols.staArrowL.setRotation(adf0hdg*D2R);
} else {
me.symbols.staArrowL.hide();
}
if((getprop(vor2_path~ "in-range") and me.get_switch('toggle_rh_vor_adf') == 1)) {
me.symbols.staArrowR.setVisible(staPtrVis);
me.symbols.staToR.setColor(0.195,0.96,0.097);
me.symbols.staFromR.setColor(0.195,0.96,0.097);
me.symbols.staArrowR.setRotation(nav1hdg*D2R);
} elsif(getprop("instrumentation/adf[1]/in-range") and (me.get_switch('toggle_rh_vor_adf') == -1)) {
me.symbols.staArrowR.setVisible(staPtrVis);
me.symbols.staToR.setColor(0,0.6,0.85);
me.symbols.staFromR.setColor(0,0.6,0.85);
me.symbols.staArrowR.setRotation(adf1hdg*D2R);
} else {
me.symbols.staArrowR.hide();
}
me.symbols.staArrowL2.hide();
me.symbols.staArrowR2.hide();
me.symbols.curHdgPtr2.hide();
me.symbols.HdgBugCRT2.hide();
me.symbols.TrkBugLCD2.hide();
me.symbols.HdgBugLCD2.hide();
me.symbols.selHdgLine2.hide();
me.symbols.curHdgPtr.setVisible(staPtrVis);
me.symbols.HdgBugCRT.setVisible(staPtrVis and !dispLCD);
if(me.get_switch('toggle_track_heading'))
{
me.symbols.HdgBugLCD.hide();
me.symbols.TrkBugLCD.setVisible(staPtrVis and dispLCD);
}
else
{
me.symbols.TrkBugLCD.hide();
me.symbols.HdgBugLCD.setVisible(staPtrVis and dispLCD);
}
me.symbols.selHdgLine.setVisible(staPtrVis and hdg_bug_active);
} else {
me.symbols.trkInd.hide();
if((getprop(vor1_path~ "in-range") and me.get_switch('toggle_lh_vor_adf') == 1)) {
me.symbols.staArrowL2.setVisible(staPtrVis);
me.symbols.staFromL2.setColor(0.195,0.96,0.097);
me.symbols.staToL2.setColor(0.195,0.96,0.097);
me.symbols.staArrowL2.setRotation(nav0hdg*D2R);
} elsif(getprop("instrumentation/adf/in-range") and (me.get_switch('toggle_lh_vor_adf') == -1)) {
me.symbols.staArrowL2.setVisible(staPtrVis);
me.symbols.staFromL2.setColor(0,0.6,0.85);
me.symbols.staToL2.setColor(0,0.6,0.85);
me.symbols.staArrowL2.setRotation(adf0hdg*D2R);
} else {
me.symbols.staArrowL2.hide();
}
if((getprop(vor2_path~ "in-range") and me.get_switch('toggle_rh_vor_adf') == 1)) {
me.symbols.staArrowR2.setVisible(staPtrVis);
me.symbols.staFromR2.setColor(0.195,0.96,0.097);
me.symbols.staToR2.setColor(0.195,0.96,0.097);
me.symbols.staArrowR2.setRotation(nav1hdg*D2R);
} elsif(getprop("instrumentation/adf[1]/in-range") and (me.get_switch('toggle_rh_vor_adf') == -1)) {
me.symbols.staArrowR2.setVisible(staPtrVis);
me.symbols.staFromR2.setColor(0,0.6,0.85);
me.symbols.staToR2.setColor(0,0.6,0.85);
me.symbols.staArrowR2.setRotation(adf1hdg*D2R);
} else {
me.symbols.staArrowR2.hide();
}
me.symbols.staArrowL.hide();
me.symbols.staArrowR.hide();
me.symbols.curHdgPtr.hide();
me.symbols.HdgBugCRT.hide();
me.symbols.TrkBugLCD.hide();
me.symbols.HdgBugLCD.hide();
me.symbols.selHdgLine.hide();
me.symbols.curHdgPtr2.setVisible(staPtrVis);
me.symbols.HdgBugCRT2.setVisible(staPtrVis and !dispLCD);
if(me.get_switch('toggle_track_heading'))
{
me.symbols.HdgBugLCD2.hide();
me.symbols.TrkBugLCD2.setVisible(staPtrVis and dispLCD);
}
else
{
me.symbols.TrkBugLCD2.hide();
me.symbols.HdgBugLCD2.setVisible(staPtrVis and dispLCD);
}
me.symbols.selHdgLine2.setVisible(staPtrVis and hdg_bug_active);
}
## run all predicates in the NDStyle hash and evaluate their true/false behavior callbacks
## this is in line with the original design, but normally we don't need to getprop/poll here,
## using listeners or timers would be more canvas-friendly whenever possible
## because running setprop() on any group/canvas element at framerate means that the canvas
## will be updated at frame rate too - wasteful ... (check the performance monitor!)
foreach(var feature; me.nd_style.features ) {
# for stuff that always needs to be updated
if (contains(feature.impl, 'common')) feature.impl.common(me);
# conditional stuff
if(!contains(feature.impl, 'predicate')) continue; # no conditional stuff
if ( var result=feature.impl.predicate(me) )
feature.impl.is_true(me, result); # pass the result to the predicate
else
feature.impl.is_false( me, result ); # pass the result to the predicate
}
## update the status flags shown on the ND (wxr, wpt, arpt, sta)
# this could/should be using listeners instead ...
me.symbols['status.wxr'].setVisible( me.get_switch('toggle_weather') and me.in_mode('toggle_display_mode', ['MAP']));
me.symbols['status.wpt'].setVisible( me.get_switch('toggle_waypoints') and me.in_mode('toggle_display_mode', ['MAP']));
me.symbols['status.arpt'].setVisible( me.get_switch('toggle_airports') and me.in_mode('toggle_display_mode', ['MAP']));
me.symbols['status.sta'].setVisible( me.get_switch('toggle_stations') and me.in_mode('toggle_display_mode', ['MAP']));
# Okay, _how_ do we hook this up with FGPlot?
printlog(_MP_dbg_lvl, "Total ND update took "~((systime()-_time)*100)~"ms");
setprop("/instrumentation/navdisplay["~ canvas.NavDisplay.id ~"]/update-ms", systime() - _time);
};

View file

@ -0,0 +1,139 @@
var SymbolPainter = {
aircraft_dir: nil,
getOpts: func(opts){
if(opts == nil) opts = {};
var defOpts = {id:nil,color:nil,scale:1,create_group:0,update_center:0};
if(contains(opts, 'id'))
defOpts.id = opts.id;
if(contains(opts, 'color'))
defOpts.color = opts.color;
if(contains(opts, 'scale'))
defOpts.scale = opts.scale;
if(contains(opts, 'create_group'))
defOpts.create_group = opts.create_group;
if(contains(opts, 'update_center'))
defOpts.update_center = opts.update_center;
return defOpts;
},
getAircraftDir: func(){
if(me.aircraft_dir == nil)
me.aircraft_dir = split('/', getprop("/sim/aircraft-dir"))[-1];
return me.aircraft_dir;
},
svgPath: func(file){
return "Aircraft/" ~ me.getAircraftDir() ~ "/Models/Instruments/ND/canvas/res/"~file;
},
drawFIX : func(grp, opts = nil){
var icon_fix = nil;
opts = me.getOpts(opts);
var sym_id = opts.id;
if(sym_id != nil)
icon_fix = grp.createChild("path", sym_id);
else
icon_fix = grp.createChild("path");
var color = opts.color;
if(color == nil){
color = {
r: 0.69,
g: 0,
b: 0.39
};
}
var scale = opts.scale;
if(scale == nil) scale = 0.8;
icon_fix.moveTo(-10,0)
.lineTo(0,-17)
.lineTo(10,0)
.lineTo(0,17)
.close()
.setStrokeLineWidth(3)
.setColor(color.r,color.g,color.b)
.setScale(scale,scale);
return icon_fix;
},
drawVOR: func(grp, opts = nil){
opts = me.getOpts(opts);
if(opts.create_group){
var sym_id = opts.id;
if(sym_id != nil)
grp = grp.createChild("group", sym_id);
else
grp = grp.createChild("group");
}
var svg_path = me.svgPath('airbus_vor.svg');
canvas.parsesvg(grp, svg_path);
var scale = opts.scale;
if(scale == nil) scale = 0.8;
grp.setScale(scale,scale);
if(opts.update_center)
grp.setTranslation(-24 * scale,-24 * scale);
if(!contains(grp, 'setColor')){
grp.setColor = func {
var layer1 = grp.getElementById('layer1');
if(layer1 == nil) return;
var children = layer1.getChildren();
foreach(var c; children){
if(isa(c, canvas.Path))
c.setColor(arg);
}
};
}
return grp;
},
drawNDB: func(grp, opts = nil){
var icon_ndb = nil;
opts = me.getOpts(opts);
var sym_id = opts.id;
if(sym_id != nil)
icon_ndb = grp.createChild("path", sym_id);
else
icon_ndb = grp.createChild("path");
var color = opts.color;
var color = opts.color;
if(color == nil){
color = {
r: 0.69,
g: 0,
b: 0.39
};
}
var scale = opts.scale;
if(scale == nil) scale = 0.8;
icon_ndb.moveTo(-15,15)
.lineTo(0,-15)
.lineTo(15,15)
.close()
.setStrokeLineWidth(3)
.setColor(color.r,color.g,color.b)
.setScale(scale,scale);
return icon_ndb;
},
drawAirport: func(grp, opts = nil){
opts = me.getOpts(opts);
if(opts.create_group){
var sym_id = opts.id;
if(sym_id != nil)
grp = grp.createChild("group", sym_id);
else
grp = grp.createChild("group");
}
var svg_path = me.svgPath('airbus_airport.svg');
canvas.parsesvg(grp, svg_path);
var scale = opts.scale;
if(scale == nil) scale = 0.8;
grp.setScale(scale,scale);
if(opts.update_center)
grp.setTranslation(-24 * scale,-24 * scale);
return grp;
},
draw: func(type, grp, opts = nil){
if(type == 'VOR' or type == 'vor')
return me.drawVOR(grp, opts);
elsif(type == 'NDB' or type == 'ndb')
return me.drawNDB(grp, opts);
elsif(type == 'ARPT' or type == 'arpt')
return me.drawAirport(grp, opts);
else
return me.drawFIX(grp, opts);
}
};

View file

@ -0,0 +1,83 @@
var version = getprop('sim/version/flightgear');
var v = split('.', version);
version = num(v[0]~'.'~v[1]);
setlistener("/nasal/canvas/loaded", func() {
####### LOAD FILES #######
#print("loading files");
(func {
var aircraft_root = getprop("/sim/aircraft-dir");
var load = func(file, name) {
#print("Loading ..." ~ file);
if (name == nil)
var name = split("/", file)[-1];
if (substr(name, size(name)-4) == ".draw")
name = substr(name, 0, size(name)-5);
#print("reading file");
var code = io.readfile(file);
#print("compiling file");
# This segfaults for some reason:
#var code = call(compile, [code], var err=[]);
var code = call(func compile(code, file), [code], var err=[]);
if (size(err)) {
#print("handling error");
if (substr(err[0], 0, 12) == "Parse error:") { # hack around Nasal feature
var e = split(" at line ", err[0]);
if (size(e) == 2)
err[0] = string.join("", [e[0], "\n at ", file, ", line ", e[1], "\n "]);
}
for (var i = 1; (var c = caller(i)) != nil; i += 1)
err ~= subvec(c, 2, 2);
debug.printerror(err);
return;
}
#print("calling code");
call(code, nil, nil, var hash = {});
#debug.dump(keys(hash));
return hash;
};
var load_deps = func(name) {
print('Loading MapStructure Layer: '~ name);
load(aircraft_root~"/Models/Instruments/ND/map/"~name~".lcontroller", name);
load(aircraft_root~"/Models/Instruments/ND/map/"~name~".symbol", name);
if(version < 3.2)
load(aircraft_root~"/Models/Instruments/ND/map/"~name~".scontroller", name);
}
#foreach( var name; ['APS','ALT-profile','SPD-profile','RTE','WPT','DECEL','NDB'] )
#load_deps( name );
var dep_names = [
# With these extensions, in this order:
"lcontroller",
"symbol",
"scontroller",
"controller",
];
var map_root = aircraft_root~"/Models/Instruments/ND/canvas/map/";
var files = directory(map_root);
var deps = {};
foreach (var d; dep_names) deps[d] = [];
foreach(var f; files){
var ext = size(var s=split(".", f)) > 1 ? s[-1] : nil;
foreach (var d; dep_names) {
if (ext == d) {
append(deps[d], f);
break
}
}
}
foreach (var d; dep_names) {
foreach (var f; deps[d]) {
var name = split(".", f)[0];
load(map_root~f, name);
}
}
})();
}, 1);

View file

@ -0,0 +1,112 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'HOLD';
var parents = [canvas.SymbolLayer.Controller];
var __self__ = caller(0)[0];
canvas.SymbolLayer.Controller.add(name, __self__);
canvas.SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
#debug.dump(layer.parents);
layer.searcher._equals = func(a,b) a.id == b.id;
#append(m.listeners, setlistener(layer.options.fplan_active, func m.layer.update() ));
#m.addVisibilityListener();
var driver = opt_member(m.layer.options, 'route_driver');
if(driver == nil){
driver = RouteDriver.new();
}
# var driver_listeners = driver.getListeners();
# foreach(var listener; driver_listeners){
# append(m.listeners, setlistener(listener, func m.layer.update()));
# }
m.route_driver = driver;
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
var driver = me.route_driver;
if(!driver.shouldUpdate()) return [];
driver.update();
var results = [];
var planCount = driver.getNumberOfFlightPlans();
var cur_fp = flightplan();
var cur_wp = cur_fp.getWP();
var next_wp = nil;
if (cur_wp != nil)
next_wp = cur_fp.getWP(cur_wp.index + 1);
var range = me.map.getRange();
if (range == nil) range = 0;
for(var idx = 0; idx < planCount; idx += 1){
var patterns = me.route_driver.getHoldPatterns(idx);
if (typeof(patterns) == 'vector') {
foreach (var pattern; patterns) {
var wp = pattern['wp'];
if (wp == nil) continue;
var wp_id = wp.id;
var wp_idx = wp.index;
var node = pattern['node'];
if (node == nil) continue;
var pointsNode = node.getNode('points');
var pointNode = nil;
if(pointsNode != nil)
pointNode = pointsNode.getNode('point', 0);
if (pointNode == nil) continue;
var r = pattern['crs'];
var d = pattern['dist'];
var t = pattern['turn'];
if (r == nil or d == nil or t == nil) continue;
var active = node.getValue('active') == 1;
var fpId = pattern['fpId'];
var type = 'hold_symbol';
var sfx = '-inactive';
if (fpId == 'active' or fpId == 'temporary') {
if (range <= 160) {
if ((cur_wp != nil and cur_wp.index == wp_idx) or
(next_wp != nil and next_wp.index == wp_idx)) {
type = 'pattern';
sfx = '';
}
}
}
var lat = wp.wp_lat;
var lon = wp.wp_lon;
var model = {
parents: [geo.Coord],
id: wp_id~r~d~t~sfx,
pos: {lat: lat, lon: lon},
type: type,
latlon: func(){
return [
me.pos.lat,
me.pos.lon
];
},
radial: r,
dist: d,
turn: t,
fpId: fpId,
equals: func(o){me.id == o.id}
};
append(results, model);
}
}
}
return results;
}

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'HOLD';
var parents = [canvas.Symbol.Controller];
var __self__ = caller(0)[0];
canvas.Symbol.Controller.add(name, __self__);
canvas.Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = canvas.SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,124 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'HOLD';
var parents = [canvas.DotSym];
var __self__ = caller(0)[0];
canvas.DotSym.makeinstance( name, __self__ );
#canvas.SymbolLayer.get(name).df_style = {
# radius: 13,
#};
var element_type = "group";
var draw_pattern = func(dist, turn, from_point = -1){
var pattern = me.element.createChild("path", 'hold-pattern');
pattern.set("z-index",4);
var w = (dist * 2) / math.pi;
var h = dist * 70;
var r = w / 2;
var perp1 = 70;
var perp2 = -70;
if (turn == 'L') {
perp1 = -70;
perp2 = 70;
}
if (turn == 'R')
pattern.arcSmallCW(r,r,0,70 * w,0);
else
pattern.arcSmallCCW(r,r,0,-70 * w,0);
pattern.line(0,h);
if (turn == 'R')
pattern.arcSmallCW(r,r,0,-70 * w,0);
else
pattern.arcSmallCCW(r,r,0,70 * w,0);
pattern.line(0,-h).
setStrokeLineWidth(5).
setColor(me.active_color);
return pattern;
};
var draw_hold_sym = func(turn){
var hold_symbol = me.element.createChild("group", 'hold-symbol');
var svg = get_local_path("res/airbus_hold"~turn~".svg");
canvas.parsesvg(hold_symbol, svg);
hold_symbol.setTranslation(-32,-64).set('z-index', 4);
return hold_symbol;
}
var init = func {
var type = me.model.type;
var dist = me.model.dist;
var turn = me.model.turn;
me.active_color = me.getStyle('active_color',
me.getOption('active_route_color',
[0.4,0.7,0.4]));
me.inactive_color = me.getStyle('inactive_color',
me.getOption('inactive_route_color',
[0.95,0.95,0.21]));
if(type == 'pattern'){
me.hold_pattern = me.draw_pattern(dist, turn);
me.hold_symbol = nil;
} else {
#print('CREATING HOLD SYM');
me.hold_pattern = nil;
me.hold_symbol = me.draw_hold_sym(turn);
}
}
var draw = func{
var type = me.model.type;
var map = me.layer.map;
var pos = map.getPos();
#print('DRAW HOLD '~ type);
if(type == 'pattern'){
var dist = me.model.dist;
var turn = me.model.turn;
if(me.hold_symbol != nil){
me.hold_symbol.hide();
}
if(me.hold_pattern == nil)
me.hold_pattern = me.draw_pattern(dist, turn);
if(me.hold_pattern == nil) return;
var radial = me.model.radial;
if(radial != nil){
var hdg = pos[2];
if(hdg == nil) hdg = 0;
radial -= hdg;
if(radial < 0) radial = 360 + radial;
me.element.setRotation(radial*D2R);
}
var rng = pos[3];
#print("CANVAS: Map RNG: " ~ rng);
if(rng == nil) rng = 10;
rng = 10 / rng;
#print("CANVAS: Hold Scale: " ~ rng);
me.element.setScale(rng,rng);
me.hold_pattern.setStrokeLineWidth(5 * (1/rng));
var lat_ctrl = getprop(me.getOption('lat_ctrl'));
var lnav = (lat_ctrl == me.getOption('lat_ctrl_managed','fmgc'));
var fp_actv = getprop(me.getOption('fplan_active'));
var fpId = me.model.fpId;
#print('HOLD ' ~ lnav ~ ',' ~ fp_actv);
var is_tmpy = (fpId == 'temporary');
if(!lnav or !fp_actv or is_tmpy)
me.hold_pattern.setStrokeDashArray([32, 16]);
else
me.hold_pattern.setStrokeDashArray([1,0]);
if(!fp_actv or is_tmpy)
me.hold_pattern.setColor(me.inactive_color);
else
me.hold_pattern.setColor(me.active_color);
} else {
var turn = me.model.turn;
if(me.hold_pattern != nil){
me.hold_pattern.hide();
}
if(me.hold_symbol == nil)
me.hold_symbol = me.draw_hold_sym(turn);
me.hold_symbol.show();
me.element.setScale(1,1);
me.element.setRotation(0);
}
}

View file

@ -0,0 +1,47 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'ALT-profile';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: { # default configuration options
fplan_active: "/autopilot/route-manager/active",
vnav_node: "/autopilot/route-manager/vnav/",
types: ["tc", "td", "ec", "ed","sc", "sd"],
}
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(a,b) a.getName() == b.getName();
append(m.listeners, setlistener(layer.options.fplan_active,
func m.layer.update() ));
m.addVisibilityListener();
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
var results = [];
var symNode = props.globals.getNode(me.layer.options.vnav_node);
if (symNode != nil)
foreach (var t; me.layer.options.types) {
var n = symNode.getNode(t);
if (n != nil)
append(results, n);
}
return results;
}

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'ALT-profile';
var parents = [Symbol.Controller];
var __self__ = caller(0)[0];
Symbol.Controller.add(name, __self__);
Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,51 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'ALT-profile';
var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
SymbolLayer.get(name).df_style = {
radius: 13,
};
var element_type = "group";
var init = func {
var name = me.model.getName();
var svg_path = me.getOption('svg_path');
if(svg_path != nil){
var grp = me.element.createChild("group", name);
if(typeof(svg_path) == 'scalar'){
canvas.parsesvg(me.element, svg_path);
}
else{ #need hash
if(!contains(svg_path, name))
die('ALT-Profile: no SVG Path for '~ name);
var path = svg_path[name];
canvas.parsesvg(me.element, path);
}
} else {
var disptext = chr(string.toupper(name[0]))~"/"~chr(string.toupper(name[1]));
var radius = me.style.radius;
me.element.createChild("path")
.setStrokeLineWidth(5)
.moveTo(-radius, 0)
.arcLargeCW(radius, radius, 0, 2 * radius, 0)
.arcLargeCW(radius, radius, 0, -2 * radius, 0)
.setColor(0.195,0.96,0.097);
me.element.createChild("text")
.setDrawMode( canvas.Text.TEXT )
.setText(disptext)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setFontSize(28)
.setTranslation(25,35)
.setColor(0.195,0.96,0.097);
}
me.callback('init_after');
}
var draw = func{
me.callback('draw');
}

View file

@ -0,0 +1,26 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'APS';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [SingleSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_style: {},
});
# N.B.: if used, this SymbolLayer should be updated every frame
# by the Map Controller, or as often as the position is changed.
var new = func(layer) {
var __model = layer.map.getPosCoord();
#debug.dump(typeof(layer.options));
if(layer.options != nil and contains(layer.options, 'model'))
__model = layer.options.model;
return {
parents: [__self__],
_model: __model,
};
};
var del = func;

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'APS';
var parents = [canvas.Symbol.Controller];
var __self__ = caller(0)[0];
canvas.Symbol.Controller.add(name, __self__);
canvas.Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = canvas.SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,19 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'APS';
var parents = [SVGSymbol];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var svg_path = "Nasal/canvas/map/Images/boeingAirplane.svg";
var element_id = "airplane";
# Rotate with the main aircraft.
# Will have to be adapted if intended for use with other aircraft
# (but one could simply copy the layer for that).
var draw = func {
var rot = getprop("/orientation/heading-deg");
rot -= me.layer.map.getHdg();
me.element.setRotation(rot*D2R);
};

View file

@ -0,0 +1,47 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'APT';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_style: {
line_width: 3,
scale_factor: 1,
debug: 1,
color_default: [0,0.6,0.85],
label_font_color:[0,0.6,0.85],
label_font_size: 28,
text_offset: [17,35],
svg_path: nil
},
});
var a_instance = nil;
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
m.addVisibilityListener();
return m;
};
var del = func() {
#print(name,".lcontroller.del()");
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
#print("Running query:", name);
var range = me.map.getRange();
if (range == nil) return;
return positioned.findAirportsWithinRange(me.map.getPosCoord(), range);
};

View file

@ -0,0 +1,16 @@
# Class things:
var name = 'APT';
var parents = [Symbol.Controller];
var __self__ = caller(0)[0];
Symbol.Controller.add(name, __self__);
Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = SymbolLayer.Controller.registry[name];
var isActive = func(model) LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
var getpos = func(model){
[model.lat, model.lon];
}

View file

@ -0,0 +1,44 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'APT';
var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var element_type = "group"; # we want a group, becomes "me.element"
var icon_apt = nil;
var text_apt = nil;
# add the draw routine from airports-nd.draw here
var init = func {
var icon_apt = nil;
var style = me.layer.style;
var svg_path = style.svg_path;
if(svg_path != nil){
canvas.parsesvg(me.element, svg_path);
} else {
icon_apt = me.element.createChild("path", name ~ " icon" )
.moveTo(-17,0)
.arcSmallCW(17,17,0,34,0)
.arcSmallCW(17,17,0,-34,0)
.close()
.setColor(style.color_default)
.setStrokeLineWidth(style.line_width);
}
var text = me.getLabelFromModel();
if(text == nil){
text = me.model.id;
}
var text_apt = me.element.createChild("text", name ~ " label")
.setDrawMode( canvas.Text.TEXT )
.setTranslation(style.text_offset)
.setText(text)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setColor(style.label_font_color)
.setFontSize(style.label_font_size);
# FIXME: this applies scale to the whole group, better do this separately for each element?
me.element.setScale(style.scale_factor);
};
var draw = func;

View file

@ -0,0 +1,71 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'DEBUG';
var parents = [canvas.SymbolLayer.Controller];
var __self__ = caller(0)[0];
canvas.SymbolLayer.Controller.add(name, __self__);
canvas.SymbolLayer.add(name, {
parents: [canvas.MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: {
update_t : 'autopilot/route-manager/debug/update_t',
listen: ['update_t']
},
df_style: {
default_color: [1,0,0],
}
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(a,b) a.equals(b);
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
var result = [];
#return result;
var node = me['node'];
if (node == nil) {
node = props.globals.getNode('autopilot/route-manager/debug/', 1);
me.node = node;
}
var points = me.node.getNode('points', 1).getChildren();
#var count = getprop('autopilot/route-manager/debug/num') or 0;
var count = size(points);
#print('Map DEBUG: querying '~ count ~' results.');
for(var idx = 0; idx < count; idx += 1){
var point = points[idx];
#var id = getprop('autopilot/route-manager/debug/point['~idx~']/id');
#var lat = getprop('autopilot/route-manager/debug/point['~idx~']/lat');
#var lon = getprop('autopilot/route-manager/debug/point['~idx~']/lon');
var id = point.getValue('id');
var lat = point.getValue('lat');
var lon = point.getValue('lon');
if (id == nil or id == '') continue;
#print('Map DEBUG: found '~ id ~' debug point.');
var model = {
id: id,
lat: lat,
lon: lon,
equals: func(o){
me.id == o.id and me.lat == o.lat and me.lon == o.lon
}
};
append(result, model);
}
return result;
}

View file

@ -0,0 +1,29 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'DEBUG';
var parents = [canvas.DotSym];
var __self__ = caller(0)[0];
canvas.DotSym.makeinstance( name, __self__ );
var element_type = "group";
var init = func {
me.text_wps = me.element.createChild("text", "dbg-text-" ~ me.model.id)
.setDrawMode( canvas.Text.TEXT )
.setText(me.model.id)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setFontSize(28)
.setTranslation(25,15)
.setColor(1,0,0);
me.text_alt = nil;
me.sym = me.element.createChild("path").
setStrokeLineWidth(4).
moveTo(-16,0).
arcSmallCW(16,16,0,32,0).
arcSmallCW(16,16,0,-32,0).
setColor(1,0,0);
}
var draw = func{
}

View file

@ -0,0 +1,37 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'DECEL';
var parents = [canvas.SymbolLayer.Controller];
var __self__ = caller(0)[0];
canvas.SymbolLayer.Controller.add(name, __self__);
canvas.SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options : { # default configuration options
decel_node: "/autopilot/route-manager/vnav/decel/"
}
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(a,b) a.getName() == b.getName();
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
var results = [];
var symNode = props.globals.getNode(me.layer.options.decel_node);
if (symNode != nil and symNode.getValue('longitude-deg') != nil)
append(results, symNode);
return results;
}

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'DECEL';
var parents = [canvas.Symbol.Controller];
var __self__ = caller(0)[0];
canvas.Symbol.Controller.add(name, __self__);
canvas.Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = canvas.SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,32 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'DECEL';
var parents = [canvas.DotSym];
var __self__ = caller(0)[0];
canvas.DotSym.makeinstance( name, __self__ );
#canvas.SymbolLayer.get(name).df_style = {
# radius: 13,
#};
var element_type = "group";
var init = func {
var svg_path = me.getStyle('svg_path');
if(svg_path == nil)
svg_path = get_local_path('res/airbus_decel.svg');
me.decel_grp = me.element.createChild("group","decel");
canvas.parsesvg(me.decel_grp, svg_path);
me.decel_grp.set('z-index', 5);
}
var draw = func{
if(me.decel_grp != nil){
var spd_ctrl = getprop(me.options.spd_ctrl);
var spd_managed = (spd_ctrl == me.options.managed_val);
if(spd_managed)
me.decel_grp.setColor(me.style.managed_color);
else
me.decel_grp.setColor(me.style.selected_color);
}
}

View file

@ -0,0 +1,152 @@
# See: http://wiki.flightgear.org/MapStructure
# This layer is currently being restructured to better support 1) styling, 2) LOD and 3) caching of instanced symbols
# The corresponding APIs in MapStructure.nas and api.nas should probably be extended acccordingly
#
# We can look into adapting the other layers once we have a single use-case that works properly - including styling, LOD and caching -
# at that point, the framework should have evolved sufficiently.
#
# It would probably be a good idea to incrementally port some other layers and provide the corresponding helpers/APIs, to reduce the amount
# of specialized/identical code in the .symbol files.
#
# Class things:
var name = 'DME';
var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var element_type = "group"; # we want a group, becomes "me.element"
var timer = nil;
###
# symbols (canvas groups) managed by this file
#
var icon_dme = nil;
var scale_animation = 1;
var animate = func {
if (me.scale_animation >= 1)
me.scale_animation -= .5;
else
me.scale_animation += .5;
me.element.setScale( me.scale_animation );
}
var del = func {
# me.timer.stop();
}
# CachedElement
# StyleAttribute
# Styleable
# RangeAwareElement
# var DMEIcon = StyleableElement.new( [{color:IconColor}, ] );
###
# FIXME: these should probably be part of MapStructure itself
# TODO: Need to come up with a StyleableElement class for this sort of stuff
var apply_styling = func {
# add all styleable groups here
# no need to do this whenever draw is called - typically, attributes won't change at all - so this is kinda redundant
var current_color = me.icon_dme.getColor();
var required_color = nil;
if (typeof(me.map.controller["is_tuned"]) == 'func' and me.map.controller.is_tuned(me.model.frequency/100))
#TODO: once we support caching/instancing, we cannot just change the symbol like this - we need to use a different symbol from the cache instead
# which is why these things need to be done ONCE during init to set up a cache entry for each symbol variation to come up with a corresponding raster image
# TODO: API-wise it would make sense to maintain a vector of required keys, so that the style hash can be validated in the ctor of the layer
# to ensure that all mandatory fields are supplied
required_color = canvas._getColor( me.layer.style.color_tuned);
else
required_color = canvas._getColor( me.layer.style.color_default);
if (current_color != required_color) {
# print("Setting color!");
# TODO: this is where we would select another cached symbol
me.icon_dme.setColor( required_color );
}
# else print("Not changing color (unnecessary)");
# debug.dump(me.layer.style);
}
###
# NOTE: This is only applied during initialization
# TODO: expose via addLayer/style param
# TODO: also needs to be aware of current range, so that proper LOD handling can be implemented
var apply_scale = func {
# add all symbols here that need scaling
me.icon_dme.setScale( me.layer.style.scale_factor );
}
###
# draw routines must be called here to create a lookup table
# with different symbols, based on styling (colors etc)
# because we can no longer change instanced symbols later on
# as they will be shared, so we need one cache entry for each
# variation in style
var init_cache = func {
}
##
# init is done separately to prepare support for caching (instanced symbols)
#
var init = func {
# debug.dump(me.layer.style);
var draw_func = me.getOption('draw_dme');
if(typeof(draw_func) == 'func'){
me.icon_dme = draw_func(me);
} else {
me.icon_dme = me.element.createChild("path")
.moveTo(-15,0)
.line(-12.5,-7.5)
.line(7.5,-12.5)
.line(12.5,7.5)
.lineTo(7.5,-12.5)
.line(12.5,-7.5)
.line(7.5,12.5)
.line(-12.5,7.5)
.lineTo(15,0)
.lineTo(7.5,12.5)
.vert(14.5)
.horiz(-14.5)
.vert(-14.5)
.close()
.setStrokeLineWidth( me.layer.style.line_width );
}
# finally scale the symbol as requested, this is done last so that people can override this when creating the layer
me.apply_scale();
if(me.getOption('draw_text', 0)){
me.dme_text = me.element.createChild("text")
.setDrawMode( canvas.Text.TEXT )
.setText(me.model.id)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setFontSize(28)
.setColor(me.getStyle('text_color', [1,1,1]))
.setTranslation(me.getStyle('translation', [45,25]));
}
if (me.layer.style.animation_test) {
me.timer = maketimer(0.33, func me.animate() );
me.timer.start();
}
me.draw();
}
##
# this method is REQUIRED
# check if the current station is tuned or not - and style the symbol accordingly (color)
var draw = func {
me.apply_styling();
};

View file

@ -0,0 +1,31 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'FIX';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [NavaidSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
query_type:'fix',
};
m.addVisibilityListener();
return m;
};
var del = func() {
printlog(_MP_dbg_lvl, "VOR.lcontroller.del()");
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = NavaidSymbolLayer.make('fix');

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'FIX';
var parents = [Symbol.Controller];
var __self__ = caller(0)[0];
Symbol.Controller.add(name, __self__);
Symbol.registry[ name ].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = SymbolLayer.Controller.registry[ name ];
var isActive = func(model) LayerController.a_instance.isActive(model);
var query_range = func()
die( name~".scontroller.query_range /MUST/ be provided by implementation" );

View file

@ -0,0 +1,60 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'FIX';
var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
SymbolLayer.get(name).df_style = {
line_width: 3,
scale_factor: 1,
font: "LiberationFonts/LiberationSans-Regular.ttf",
font_color: [0,0,0],
font_size: 28,
color: [0, 0.6, 0.85],
show_labels: 1,
};
var element_type = "group"; # we want a group, becomes "me.element"
##
# used during initialization to populate the symbol cache with a FIX symbol
#
var drawFIX = func(group) {
group.createChild("path")
.moveTo(-15,15)
.lineTo(0,-15)
.lineTo(15,15)
.close()
.setStrokeLineWidth(line_width)
.setColor(color);
}
var _name = name;
var init = func {
# initialize the cached fix symbol
var draw_fn = me.getOption('draw_function');
if(typeof(draw_fn) != 'func')
draw_fn = drawFIX;
debug.dump(name);
var cache = StyleableCacheable.new(
name:_name,
draw_func: draw_fn,
cache: SymbolCache32x32,
draw_mode: SymbolCache.DRAW_CENTERED,
relevant_keys: ["line_width", "color"]
);
cache.render(me.element, me.style).setScale(me.style.scale_factor);
var txt_offset = me.getStyle('text_offset', [17, 35]);
var txt_color = me.getStyle('text_color', [0,0.6,0.85]);
# non-cached stuff:
if (me.style.show_labels){
me.text_fix = me.newText(me.model.id).
setScale(me.style.scale_factor).
setTranslation(txt_offset).
setColor(txt_color);
}
}
var draw = func {me.callback('draw');};

View file

@ -0,0 +1,32 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'NDB';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [NavaidSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_style: {},
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
query_type:'ndb',
};
m.addVisibilityListener();
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = NavaidSymbolLayer.make('ndb');

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'NDB';
var parents = [Symbol.Controller];
var __self__ = caller(0)[0];
Symbol.Controller.add(name, __self__);
Symbol.registry[ name ].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = SymbolLayer.Controller.registry[ name ];
var isActive = func(model) LayerController.a_instance.isActive(model);
var query_range = func()
die( name~".scontroller.query_range /MUST/ be provided by implementation" );

View file

@ -0,0 +1,7 @@
# See: http://wiki.flightgear.org/MapStructure
DotSym.makeinstance('NDB', {
parents: [SVGSymbol],
svg_path: "/gui/dialogs/images/ndb_symbol.svg",
#cacheable: 1,
});

View file

@ -0,0 +1,100 @@
# See: http://wiki.flightgear.org/MapStructure
# TODO: this layer doesn't make sense to support for AI/MP traffic, because we don't currently have access to flightplan/routing info
# that also applies to other layers like WPT or even navaid layers that handle station tuning based on local radio settings
#
# Class things:
var name = 'RTE';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: { # default configuration options
active_node: "/autopilot/route-manager/active",
current_wp_node: "/autopilot/route-manager/current-wp",
wp_num: "/autopilot/route-manager/route/num",
display_inactive_rte: 0
}
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(l,r) 0; # TODO: create model objects instead?
append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ), setlistener(layer.options.wp_num, func m.layer.update() ));
m.addVisibilityListener();
var driver = opt_member(m.layer.options, 'route_driver');
if(driver == nil){
driver = RouteDriver.new();
}
var driver_listeners = driver.getListeners();
foreach(var listener; driver_listeners){
append(m.listeners, setlistener(listener, func m.layer.update()));
}
m.route_driver = driver;
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var last_result = [];
var searchCmd = func {
# FIXME: do we return the active route even if it isn't active?
printlog(_MP_dbg_lvl, "Running query: ", name);
var plans = [];
var driver = me.route_driver;
if(!driver.shouldUpdate()) return me.last_result;
driver.update();
# http://wiki.flightgear.org/Nasal_Flightplan
var planCount = driver.getNumberOfFlightPlans();
for(var idx = 0; idx < planCount; idx += 1){
#var fp = driver.getFlightPlan(idx);
var fpSize = driver.getPlanSize(idx);
if(fpSize < 2) continue;
var type = driver.getFlightPlanType(idx);
if(type == nil) type = 'active';
if (!getprop(me.layer.options.active_node) and
type == 'active' and
!me.layer.options.display_inactive_rte) fpSize = 0;
var coords = [];
var discontinuity = 0;
for (var i=0; i<fpSize; i += 1) {
var leg = driver.getWP(idx, i);
if(leg == nil) continue;
var path = nil;
if(discontinuity)
path = [{},{lon:leg.wp_lon, lat:leg.wp_lat}];
else
path = leg.path();
if(i == (fpSize - 1) and !discontinuity){# WORKAROUND FOR FG BUG
var ltype = leg.wp_type;
var path_l = size(path);
if(ltype != 'runway' and path_l >= 2)
path = subvec(path, 0, 1) ~ subvec(path, path_l - 1, 1);
}
coords ~= path;
discontinuity = driver.hasDiscontinuity(idx, leg);
}
append(plans, {
id: type,
#name: type,
type: type,
path: coords,
#size: fpSize,
equals: func(o){
me.id == o.id# and me.size == o.size
}
});
}
me.last_result = plans;
return plans;
};

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'RTE';
var parents = [canvas.Symbol.Controller];
var __self__ = caller(0)[0];
canvas.Symbol.Controller.add(name, __self__);
canvas.Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = canvas.SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,46 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'RTE';
var parents = [LineSymbol];
var __self__ = caller(0)[0];
LineSymbol.makeinstance( name, __self__ );
SymbolLayer.get(name).df_style = { # style to use by default
line_width: 5,
color: [1,0,1]
};
var getLineStyle = func(property, df_val){
var type = nil;
if(typeof(me.model) == 'hash'){
type = me.model.type;
}
if(type != nil and type != 'active'){
var base_prop = property;
property = property~'_'~type;
me.getStyle(property, me.getStyle(base_prop, df_val));
} else {
me.getStyle(property, df_val);
}
};
var setRouteStyle = func{
var df_style = SymbolLayer.get(name).df_style;
var dash = me.getLineStyle('line_dash', []);
var color = me.getLineStyle('color', df_style.color);
var line_width = me.getLineStyle('line_width', df_style.line_width);
me.element.setColor(color)
.setStrokeLineWidth(line_width);
if(typeof(dash) == 'vector')
me.element.setStrokeDashArray(dash);
};
var init = func {
me.setRouteStyle();
};
#var draw = func {
# me.setRouteStyle();
#};

View file

@ -0,0 +1,105 @@
# See: http://wiki.flightgear.org/MapStructure
var name = 'RWY-profile';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: { # default configuration options
disable_position: 1,
dep_rwy: '/autopilot/route-manager/departure/runway',
dest_rwy: '/autopilot/route-manager/destination/runway',
dep_arpt: '/autopilot/route-manager/departure/airport',
dest_arpt: '/autopilot/route-manager/destination/airport'
}
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(l,r) {l.equals(r)}; # TODO: create model objects instead?
#append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ));
#m.addVisibilityListener();
var driver = opt_member(m.layer.options, 'route_driver');
if(driver == nil){
driver = RouteDriver.new();
}
var driver_listeners = driver.getListeners();
foreach(var listener; driver_listeners){
append(m.listeners, setlistener(listener, func m.layer.update()));
}
m.route_driver = driver;
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var FPRunwayModel = {
new: func(apt, rwy){
var m = {
parents: [FPRunwayModel],
id: rwy.id,
lat: rwy.lat,
lon: rwy.lon,
length: rwy.length,
width: rwy.width,
heading: rwy.heading,
airport_id: apt.id
};
return m;
},
latlon: func(){
return [
me.lat,
me.lon
];
},
equals: func(o){me.id == o.id and me.airport_id == o.airport_id}
};
var searchCmd = func {
#var desApt = airportinfo(getprop(me.layer.options.dest_arpt));
#var depApt = airportinfo(getprop(me.layer.options.dep_arpt));
#if(desApt == nil and depApt == nil)
# return [];
var res = [];
var desRwy = nil;
var depRwy = nil;
var driver = me.route_driver;
if(!driver.shouldUpdate()) return res;
driver.update();
var fpcount = driver.getNumberOfFlightPlans();
for(var i = 0; i < fpcount; i += 1){
if(!driver.shouldUpdate()) continue;
var fp = driver.getFlightPlan(i);
var depApt = fp.departure;
if(depApt != nil){
var depRwy = fp.departure_runway;
if(depRwy != nil){
var model = FPRunwayModel.new(depApt, depRwy);
append(res, model);
}
}
var desApt = fp.destination;
if(desApt != nil){
var desRwy = fp.destination_runway;
if(desRwy != nil){
var model = FPRunwayModel.new(desApt, desRwy);
append(res, model);
}
}
}
return res;
};

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'RWY-profile';
var parents = [canvas.Symbol.Controller];
var __self__ = caller(0)[0];
canvas.Symbol.Controller.add(name, __self__);
canvas.Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = canvas.SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,93 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'RWY-profile';
var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var element_type = "group";
var style = { # style to use by default
zoom: 20,
color: [1,1,1],
center_line_len: 0.75,
line_width: 3
};
SymbolLayer.get(name).df_style = style;
#var already_drawn = 0;
var init = func {
#if(me.already_drawn) return;
var lat = me.model.lat;
var lon = me.model.lon;
var rwyhdg = me.model.heading;
var width = me.model.width;
var length = me.model.length;
var group = me.element;
var ctr_len = length * me.getStyle('center_line_len', 0.75);
var crds = [];
var coord = geo.Coord.new();
width = width * me.getStyle('zoom', 20); # Else rwy is too thin to be visible
var line_w = me.getStyle('line_width', 3);
var color = me.getStyle('color', [1,1,1]);
coord.set_latlon(lat, lon);
coord.apply_course_distance(rwyhdg, -(ctr_len / 2));
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
coord.apply_course_distance(rwyhdg, (ctr_len));
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
icon_rwy = group.createChild("path", "rwy-cl")
.setStrokeLineWidth(line_w)
.setDataGeo([2,4],crds)
.setColor(color);
#.setStrokeDashArray([10, 20, 10, 20, 10]);
#icon_rwy.hide();
var crds = [];
coord.set_latlon(lat, lon);
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
coord.apply_course_distance(rwyhdg + 90, width/2);
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
coord.apply_course_distance(rwyhdg, length);
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
icon_rwy = group.createChild("path", "rwy")
.setStrokeLineWidth(line_w)
.setDataGeo([2,4,4],crds)
.setColor(color);
var crds = [];
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
coord.apply_course_distance(rwyhdg - 90, width);
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
coord.apply_course_distance(rwyhdg, -length);
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
coord.apply_course_distance(rwyhdg + 90, width / 2);
append(crds,"N"~coord.lat());
append(crds,"E"~coord.lon());
icon_rwy = group.createChild("path", "rwy")
.setStrokeLineWidth(line_w)
.setDataGeo([2,4,4,4],crds)
.setColor(color);
};
var draw = func{}
#var update = func() {
# if (me.controller != nil) {
# if (!me.controller.update(me, me.model)) return;
# elsif (!me.controller.isVisible(me.model)) {
# me.element.hide();
# return;
# }
# } else
# me.element.show();
# me.draw();
#}

View file

@ -0,0 +1,51 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'SPD-profile';
var parents = [canvas.SymbolLayer.Controller];
var __self__ = caller(0)[0];
var _options = { # default configuration options
alts: [100,140,250,260,'wp']
};
canvas.SymbolLayer.Controller.add(name, __self__);
canvas.SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: _options
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
#map: layer.map,
listeners: [],
};
layer.searcher._equals = func(a,b) a.getName() == b.getName();
#append(m.listeners, setlistener(layer.options.fplan_active, func m.layer.update() ));
#m.addVisibilityListener();
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
var results = [];
var spdNode = props.globals.getNode(me.layer.options.spd_node);
if (spdNode != nil) {
var limits = spdNode.getChildren();
foreach (var limit; limits) {
#t = 'spd-change-point' ~ '-' ~ alt;
#print('SPD-Controller, search for '~t);
#var n = spdNode.getNode(t);
if (limit != nil and limit.getValue('longitude-deg') != nil){
#print('SPD-Controller -> Append');
append(results, limit);
}
}
}
return results;
}

View file

@ -0,0 +1,12 @@
# Class things:
var name = 'SPD-profile';
var parents = [canvas.Symbol.Controller];
var __self__ = caller(0)[0];
canvas.Symbol.Controller.add(name, __self__);
canvas.Symbol.registry[name].df_controller = __self__;
var new = func(model) ; # this controller doesn't need an instance
var LayerController = canvas.SymbolLayer.Controller.registry[name];
var isActive = func(model) {return 1};#LayerController.a_instance.isActive(model);
var query_range = func()
die(name~".scontroller.query_range /MUST/ be provided by implementation");
#var model = props.globals.getNode('/position');

View file

@ -0,0 +1,40 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'SPD-profile';
var parents = [canvas.SVGSymbol];
var __self__ = caller(0)[0];
canvas.DotSym.makeinstance( name, __self__ );
#canvas.SymbolLayer.get(name).df_style = {
# radius: 13,
#};
var element_type = "group";
var svg_path = get_local_path('res/airbus_spd_limit.svg');
var spd_sym = nil;
#var init = func {
# var name = me.model.getName();
# #var radius = me.style.radius;
# var sym_group = me.element.createChild("group", name);
# sym_group.set("z-index",5);
# var color = me.getStyle('color');
# var spd_path = sym_group.createChild("path").
# setStrokeLineWidth(3).
# moveTo(-17,0).
# arcSmallCW(17,17,0,34,0).
# arcSmallCW(17,17,0,-34,0).
# setColor(color).
# setColorFill(color).
# set("z-index",5);
#}
var draw = func{
# var name = me.model.getName();
# var sym_group = me.element.getElementById(name);
# sym_group.set('z-index', 5);
if(me.spd_sym == nil){
me.spd_sym = me.getElementById("airbus-spd-sym");
me.spd_sym.setTranslation(-24, -24).set('z-index', 5);
}
}

View file

@ -0,0 +1,62 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name ='VOR-airbus';
var parents = [SymbolLayer.Controller];
var __self__ = caller(0)[0];
SymbolLayer.Controller.add(name, __self__);
SymbolLayer.add(name, {
parents: [NavaidSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: {
vor1_frq: 'instrumentation/nav/frequencies/selected-mhz',
vor2_frq: 'instrumentation/nav[1]/frequencies/selected-mhz'
},
df_style: {
scale: 1
}
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
active_vors: [],
navNs: props.globals.getNode("instrumentation").getChildren("nav"),
listeners: [],
query_type:'vor',
};
setsize(m.active_vors, size(m.navNs));
foreach (var navN; m.navNs) {
append(m.listeners, setlistener(
navN.getNode("frequencies/selected-mhz"),
func m.changed_freq()
));
}
#call(debug.dump, keys(layer));
m.changed_freq(update:0);
m.addVisibilityListener();
return m;
};
var del = func() {
printlog(_MP_dbg_lvl, name,".lcontroller.del()");
foreach (var l; me.listeners)
removelistener(l);
};
# Controller methods
var isActive = func(model) {
var my_freq = model.frequency/100;
foreach (var freq; me.active_vors)
if (freq == my_freq) return 1;
return 0;
};
var changed_freq = func(update=1) {
#debug.dump(me.active_vors);
foreach (var navN; me.navNs)
me.active_vors[ navN.getIndex() ] = navN.getValue("frequencies/selected-mhz");
if (update) me.layer.update();
};
var searchCmd = NavaidSymbolLayer.make('vor');

View file

@ -0,0 +1,43 @@
# Class things:
var name = 'VOR-airbus';
var parents = [SVGSymbol];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var element_type = "group"; # we want a group, becomes "me.element"
var text_vor = nil;
var svg_path = get_local_path('res/airbus_vor.svg');
var vor_sym = nil;
var draw = func{
if(me.vor_sym == nil)
me.vor_sym = me.element.getElementById("airbus-vor-sym");
me.vor_sym.setTranslation(-24,-24);
if(me.text_vor == nil){
var transl = me.getStyle('translation', [25,10]);
var text_color = me.getStyle('text_color', [1,1,1]);
me.text_vor = me.element.createChild("text")
.setDrawMode( canvas.Text.TEXT )
.setText(me.model.id)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setFontSize(28)
.setColor(text_color)
.setTranslation(transl);
}
var frq = me.model.frequency;
if(frq != nil){
var dfcolor = me.getStyle('color', [0.9,0,0.47]);
var tuned_color = me.getStyle('tuned_color', [0,0.62,0.84]);
frq = frq / 100;
var vor1_frq = getprop(me.options.vor1_frq);
var vor2_frq = getprop(me.options.vor2_frq);
if(vor1_frq == frq or vor2_frq == frq){
me.element.setColor(tuned_color);
} else {
me.element.setColor(dfcolor);
}
}
me.text_vor.setColor(me.getStyle('text_color', [1,1,1]));
}

View file

@ -0,0 +1,137 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'WPT-airbus';
var parents = [canvas.SymbolLayer.Controller];
var __self__ = caller(0)[0];
canvas.SymbolLayer.Controller.add(name, __self__);
canvas.SymbolLayer.add(name, {
parents: [canvas.MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: { # default configuration options
fix_symbol: func(group){
group.createChild('path')
.moveTo(-10,0)
.lineTo(0,-17)
.lineTo(10,0)
.lineTo(0,17)
.close()
.setStrokeLineWidth(3)
.setColor(1,1,1)
.setScale(1);
},
vor_symbol: 'Nasal/canvas/map/Airbus/Images/airbus_vor.svg',
airport_symbol: 'Nasal/canvas/map/Airbus/Images/airbus_airport.svg',
ndb_symbol: func(group){
group.createChild('path')
.moveTo(-15,15)
.lineTo(0,-15)
.lineTo(15,15)
.close()
.setStrokeLineWidth(3)
#.setColor(0.69,0,0.39)
#.setTranslation(-24, -24),
.setScale(1,1);
}
},
df_style: {
active_wp_color: [0.4,0.7,0.4],
current_wp_color: [1,1,1],
translation: {
'airport': [-24,-24],
'vor': [-24,-24]
}
},
toggle_cstr: 0
});
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(a,b) a.equals(b);
var driver = opt_member(m.layer.options, 'route_driver');
if(driver == nil){
driver = RouteDriver.new();
}
var driver_listeners = driver.getListeners();
foreach(var listener; driver_listeners){
append(m.listeners, setlistener(listener, func m.layer.update()));
}
m.route_driver = driver;
return m;
};
var del = func() {
foreach (var l; me.listeners)
removelistener(l);
};
var WPTModel = {
new: func(fp, idx) {
var m = { parents:[WPTModel] };
var wp = fp.getWP(idx);
m.id = wp.id;
m.name = wp.wp_name;
m.alt = wp.alt_cstr;
m.spd = wp.speed_cstr;
m.type = wp.wp_type;
(m.lat,m.lon) = (wp.wp_lat,wp.wp_lon);
var is_rwy = (m.type == 'runway');
var id_len = size(m.id);
if(!is_rwy and id_len < 5){
if(id_len == 4 and airportinfo(m.id) != nil)
m.navtype = 'airport';
else {
var navaid = nil;
foreach(var t; ['vor', 'ndb']){
navaid = navinfo(m.lat, m.lon, t, m.id);
if(navaid != nil and size(navaid)){
m.navtype = t;
break;
}
}
if(navaid == nil or !size(navaid)) m.navtype = 'fix';
}
} else {
m.navtype = (is_rwy ? 'rwy' : 'fix');
}
m.wp = wp;
idx = wp.index;
m.idx = idx;
m.is_departure = (idx == 0 and is_rwy);
m.is_destination = (idx > 0 and is_rwy);
return m;
},
equals: func(other) {
# this is set on symbol init, so use this for equality...
me.name == other.name and me.alt == other.alt and
me.type == other.type and me.idx == other.idx and
me.navtype == other.navtype
},
};
var searchCmd = func {
var driver = me.route_driver;
if(!driver.shouldUpdate()) return [];
driver.update();
var result = [];
var planCount = driver.getNumberOfFlightPlans();
for(var idx = 0; idx < planCount; idx += 1){
var fp = driver.getFlightPlan(idx);
if(fp == nil) continue;
var fpSize = fp.getPlanSize(idx);
for (var i = 0; i < fpSize; i+=1){
if(!driver.shouldUpdate()) return[];
append(result, WPTModel.new(fp, i));
}
}
return result;
}

View file

@ -0,0 +1,137 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'WPT-airbus';
var parents = [canvas.DotSym];
var __self__ = caller(0)[0];
canvas.DotSym.makeinstance( name, __self__ );
var element_type = "group";
var init = func {
var name = me.model.name;
var alt = me.model.alt;
var spd = me.model.spd;
var wp_group = me.element;
me.alt_path = nil;
var colors = [
'wp_color',
'current_wp_color',
'constraint_color',
'active_constraint_color',
'missed_constraint_color'
];
foreach(col; colors){
me[col] = me.getStyle(col, me.getOption(col));
}
var idLen = size(me.model.id);
var draw_sym = nil;
var navtype = me.model.navtype;
if (navtype == nil) navtype = 'fix';
if(navtype == 'airport')
draw_sym = me.options.airport_symbol;
elsif(navtype == 'vor')
draw_sym = me.options.vor_symbol;
elsif(navtype == 'ndb')
draw_sym = me.options.ndb_symbol;
else
draw_sym = me.options.fix_symbol;
me.wp_sym = me.element.createChild('group', 'wp-'~ me.model.idx);
if(typeof(draw_sym) == 'func')
draw_sym(me.wp_sym);
elsif(typeof(draw_sym) == 'scalar')
canvas.parsesvg(me.wp_sym, draw_sym);
var translation = me.getStyle('translation', {});
if(contains(translation, navtype)){
me.wp_sym.setTranslation(translation[navtype]);
}
me.text_wps = wp_group.createChild("text", "wp-text-" ~ me.model.idx)
.setDrawMode( canvas.Text.TEXT )
.setText(me.model.name)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setFontSize(28)
.setTranslation(25,15)
.setColor(1,1,1);
me.text_alt = nil;
if(alt > 0 or spd > 0){
var cstr_txt = "\n";
if(alt > 0){
if(alt > 10000)
cstr_txt ~= sprintf('FL%3.0f', int(alt / 100));
else
cstr_txt ~= sprintf('%4.0f', int(alt));
}
if(spd > 0){
if(alt > 0) cstr_txt ~= "\n";
if(spd <= 1)
cstr_txt ~= sprintf('%1.2fM', spd);
else
cstr_txt ~= sprintf('%3.0fKT', int(spd));
}
me.text_alt = wp_group.createChild("text", "wp-alt-text-" ~ me.model.idx)
.setDrawMode( canvas.Text.TEXT )
.setText(cstr_txt)
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
.setFontSize(28)
.setTranslation(25,15);
}
}
var draw = func{
var wp_group = me.element;
var alt = me.model.alt;
var i = me.model.idx;
var vnav_actv = getprop(me.options.ver_ctrl) == me.options.managed_val;
var curwp = getprop(me.options.current_wp);
if(alt > 0){
var wp_d = me.model.wp.distance_along_route;
var lvl_off_at = getprop(me.options.level_off_alt);
if(lvl_off_at == nil) lvl_off_at = 0;
if(me.alt_path == nil){
me.alt_path = wp_group.createChild("path").
setStrokeLineWidth(4).
moveTo(-22,0).
arcSmallCW(22,22,0,44,0).
arcSmallCW(22,22,0,-44,0);
}
if(vnav_actv){
if(lvl_off_at and (lvl_off_at - wp_d) > 0.5 and curwp == i)
me.alt_path.setColor(me.missed_constraint_color);
else
me.alt_path.setColor(me.active_constraint_color);
}
else
me.alt_path.setColor(me.constraint_color);
if(me.layer.toggle_cstr)
me.alt_path.show();
else
me.alt_path.hide();
} else {
if(me.alt_path != nil) me.alt_path.hide();
}
wp_group.set("z-index",4);
#var sym = me.element.getElementById('wp-' ~ me.model.idx);
if(alt > 0 and me.text_alt != nil){
if(vnav_actv)
me.text_alt.setColor(me.active_constraint_color);
else
me.text_alt.setColor(me.constraint_color);
}
if(i == curwp) {
me.wp_sym.setColor(me.current_wp_color);
me.text_wps.setColor(me.current_wp_color);
} else {
me.wp_sym.setColor(me.wp_color);
me.text_wps.setColor(me.wp_color);
}
if(me.model.is_departure or me.model.is_destination){
var prop = (me.model.is_departure ? 'departure' : 'destination');
var rwy = getprop("/autopilot/route-manager/"~prop~"/runway");
if(rwy != nil and size(rwy) > 0){
me.wp_sym.hide();
} else {
me.wp_sym.show();
}
}
}

View file

@ -0,0 +1,72 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'WXR_live';
var parents = [canvas.SymbolLayer.Controller];
var __self__ = caller(0)[0];
canvas.SymbolLayer.Controller.add(name, __self__);
canvas.SymbolLayer.add(name, {
parents: [canvas.MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_options: { # default configuration options
viewport_radius: 670
}
});
var wxr_tree = "/instrumentation/wxr";
var new = func(layer) {
var m = {
parents: [__self__],
layer: layer,
map: layer.map,
listeners: [],
};
layer.searcher._equals = func(l,r) l.equals(r);
m.addVisibilityListener();
var aircraft_dir = split('/', getprop("/sim/aircraft-dir"))[-1];
var saved_conf = getprop("/sim/fg-home") ~ "/Export/wxr_api.xml";
var df_conf = getprop("/sim/fg-root") ~ "/Aircraft/" ~ aircraft_dir ~
"/Models/Instruments/ND/canvas/wxr_api.xml";
if(io.stat(saved_conf) != nil)
io.read_properties(saved_conf, wxr_tree);
else
io.read_properties(df_conf, wxr_tree);
return m;
};
var del = func() {
#print(name~".lcontroller.del()");
foreach (var l; me.listeners)
removelistener(l);
};
var searchCmd = func {
if(me.map.getRange() == nil) return [];
var api_key = getprop(wxr_tree~"/api-key");
if(!api_key or api_key == '' or api_key == 'YOUR API KEY')
return [];
var lat = getprop(wxr_tree~"/center/latitude-deg");
var lon = getprop(wxr_tree~"/center/longitude-deg");
if(lat == nil or lon == nil) {
var pos = geo.aircraft_position();
lat = pos.lat();
lon = pos.lon();
}
var result = geo.Coord.new();
result.set_latlon(lat, lon);
result.rangeNm = me.map.getRange();
result.key = api_key;
result.res = getprop(wxr_tree~"/resolution");
result.ltype = getprop(wxr_tree~"/layer-type");
result.smooth = getprop(wxr_tree~"/smooth");
result.fetchRad = getprop(wxr_tree~"/fetch-radius");
result.equals = func(r){
me.ltype == r.ltype and me.fetchRad == r.fetchRad and
me.lat == r.lat and me.lon == r.lon
};
return [result];
};

View file

@ -0,0 +1,114 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'WXR_live';
var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var element_type = "group";
var getWXRImageFilePath = func(){
var home = getprop('sim/fg-home');
var aircraft = getprop('sim/aircraft');
var idx = me.layer.getCanvas()._node.getIndex();
return home ~ '/Export/' ~ aircraft ~ '-wxr-'~me.ltype~'-'~idx~'.png';
};
var getWXRAPIUrl = func(lat, lon){
var res = me.res;
if(me.ltype == "radar"){
return "http://api.wunderground.com/api/"~me.key~
"/radar/image.png?centerlat="~lat~"&centerlon="~lon~
"&radius="~me.fetchRad~"&width="~res~"&height="~res~
"&smooth="~me.smooth;
} else {
return nil;
}
};
var fetchWXRMap = func(size){
if(me.fetching) return;
var pos = geo.aircraft_position();
var lat = pos.lat();
var lon = pos.lon();
var url = me.getWXRAPIUrl(lat, lon);
var filePath = me.getWXRImageFilePath();
if(url == nil) {
print(me.name~': No URL!');
return;
}
me.fetching = 1;
http.save(url, filePath)
.fail(func(){
print(me.name~': Download failed!');
me.wxlayer.hide();
})
.done(func(){
var sz = size * 2;
var transl = -size;
me.wxlayer.hide();
me.wxlayer.setFile(filePath)
.setSize(sz, sz)
.setTranslation(transl, transl);
me.wxlayer.show();
me.last_request = getprop("/sim/time/elapsed-sec");
})
.always(func(){
setprop("/instrumentation/wxr/center/latitude-deg", lat);
setprop("/instrumentation/wxr/center/longitude-deg", lon);
me.fetching = 0;
print("[WXR] Live Layer Request: "~url); # Debugging
});
};
var init = func {
#print('WXR init');
me.fetching = 0;
me.key = me.model.key; # API Key from Wunderground API Subscription
me.res = me.model.res; # Resolution of image to fetch (default 2048)
me.ltype = me.model.ltype; # Layer Type - radar, satellite
me.smooth = me.model.smooth; # If we should fetch a smoothened image or the original
me.fetchRad = me.model.fetchRad; # Radius of radar layer to fetch
me.range = me.model.rangeNm; # Range of Navigation Display
me.viewport_radius = me.getOption('viewport_radius', 670);
me.wxlayer = me.element.createChild("image").set("z-index", -100).hide();
me.last_request = -210;
me.update_interval = 240;
var r_scaled = (me.fetchRad*me.viewport_radius)/me.range;
me.fetchWXRMap(r_scaled);
};
var draw = func {
var range = me.layer.map.getRange(); # Range of Navigation Display
var update_size = (range != me.range);
me.range = range;
me.fetchRad = me.model.fetchRad; # Radius of radar layer to fetch
#var r_scaled = (me.fetchRad*670)/me.range;
var r_scaled = (me.fetchRad*me.viewport_radius)/me.range;
var hdg = me.layer.map.getHdg();
var rot = 0 - hdg;
if(rot < 0) rot = 360 + rot;
me.element.setRotation(rot*D2R);
if(update_size){
print('WXR draw range:'~ me.range);
print('Update size: '~r_scaled~'x2 = '~(r_scaled*2));
me.wxlayer.hide();
me.wxlayer.setSize(2*r_scaled, 2*r_scaled)
.setTranslation(-r_scaled, -r_scaled);
me.wxlayer.show();
}
if(getprop("/sim/time/elapsed-sec") - me.last_request > me.update_interval) {
#print('Fetching WXR map...');
me.key = me.model.key; # API Key from Wunderground API Subscription
me.res = me.model.res; # Resolution of image to fetch (default 2048)
me.ltype = me.model.ltype; # Layer Type - radar, satellite
me.smooth = me.model.smooth; # If we should fetch a smoothened image or the original
me.fetchWXRMap(r_scaled);
}
};

View file

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="87.8438"
height="108.844"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="boeingAirplane.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.9598"
inkscape:cx="19.8149"
inkscape:cy="54.088"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1366"
inkscape:window-height="716"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-364.652,-344.745)">
<g
id="airplane"
transform="translate(364.652,346.745)"
inkscape:label="#g3781">
<path
id="apl_path"
d="m 44.0787,102 0,-90 M 84,38 l -78,0 M 63,90 l -38,0"
style="fill:none;stroke:#f2f235;stroke-width:3.9685px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -0,0 +1,236 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="airbusNDNoMap.svg"
inkscape:version="0.48.5 r10040"
xml:space="preserve"
id="svg5180"
height="1024"
width="1024"
version="1.1"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:window-width="1280"
inkscape:window-height="706"
id="namedview102"
showgrid="false"
inkscape:zoom="0.36"
inkscape:cx="-20.989482"
inkscape:cy="346.41432"
inkscape:window-x="14"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="layer3"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-grids="false"
inkscape:snap-to-guides="false"
showguides="true"
inkscape:guide-bbox="true"><sodipodi:guide
id="guide3155"
orientation="0,1"
position="512,200" /><sodipodi:guide
id="guide3167"
orientation="1,0"
position="512,811.5" /><sodipodi:guide
id="guide3177"
orientation="-0.5,-0.86602541"
position="512,200" /><sodipodi:guide
id="guide3179"
orientation="-0.866025,-0.5"
position="512,200" /><sodipodi:guide
position="512,465"
orientation="0,1"
id="guide4003" /><sodipodi:guide
orientation="-0.5,0.8660254"
position="512,200"
id="guide3537" /><sodipodi:guide
orientation="-0.8660254,0.5"
position="512,200"
id="guide3545" /><sodipodi:guide
orientation="-0.17364818,-0.98480775"
position="512,200"
id="guide3547" /></sodipodi:namedview><metadata
id="metadata5186"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title><dc:creator><cc:Agent><dc:title>Gijs de Rooy</dc:title></cc:Agent></dc:creator><cc:license
rdf:resource="" /></cc:Work></rdf:RDF></metadata><defs
id="defs5184"><marker
style="overflow:visible"
id="TriangleOutL"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="TriangleOutL"><path
transform="scale(0.8)"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
id="path3957" /></marker><marker
style="overflow:visible;"
id="Arrow2Lend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Lend"><path
transform="scale(1.1) rotate(180) translate(1,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
id="path3836" /></marker><clipPath
id="clipPath3177"><path
id="path3179"
d="m 109.44,459.54 194.4,0 0,-216 -194.4,0 0,216 z" /></clipPath><clipPath
id="clipPath3133"><path
id="path3135"
d="m 44.64,520.2 324,0 0,-6.24 -324,0 0,6.24 z" /></clipPath><clipPath
id="clipPath3109"><path
id="path3111"
d="m 44.64,36 324,0 0,-10.08 -324,0 0,10.08 z" /></clipPath><clipPath
id="clipPath3095"><path
id="path3097"
d="m 44.64,36 324,0 0,-10.08 -324,0 0,10.08 z" /></clipPath><clipPath
id="clipPath3071"><path
id="path3073"
d="m 44.64,561.24 324,0 0,-4.32 -324,0 0,4.32 z" /></clipPath><clipPath
id="clipPath3035"><path
id="path3037"
d="m 44.64,594 324,0 0,-28.8 -324,0 0,28.8 z" /></clipPath><clipPath
id="clipPath3019"><path
id="path3021"
d="m 44.64,594 324,0 0,-28.8 -324,0 0,28.8 z" /></clipPath><clipPath
id="clipPath4462"
clipPathUnits="userSpaceOnUse"><path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path4464"
d="m 246.487,713.178 0,-420 c 0,0 -0.334,-50 50,-50 l 375,0 c 50.242,0 50,50 50,50 l 0,420 c 0,0 0.359,50 -50,50 l -375,0 c -50.233,0 -50,-50 -50,-50 z"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></clipPath></defs><g
style="display:inline"
inkscape:label="base"
id="layer3"
inkscape:groupmode="layer"><text
inkscape:label="#text7243"
sodipodi:linespacing="125%"
id="gs"
y="53.306854"
x="101.87437"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#32f519;fill-opacity:1;stroke:none;display:inline;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
xml:space="preserve"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
sodipodi:role="line"
id="tspan4097">---</tspan></text>
<text
xml:space="preserve"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#32f519;fill-opacity:1;stroke:none;display:inline;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
x="248.49673"
y="53.306854"
id="tas"
sodipodi:linespacing="125%"
inkscape:label="#text7243"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
sodipodi:role="line"
id="tspan4099">---</tspan></text>
<text
xml:space="preserve"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ededed;fill-opacity:1;stroke:none;display:inline;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
x="38.276394"
y="53.306854"
id="gsLbl"
sodipodi:linespacing="125%"
inkscape:label="#text7243"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
style="font-size:36px"
sodipodi:role="line"
id="tspan3817"
x="38.276394"
y="53.306854">GS</tspan></text>
<text
inkscape:label="#text7243"
sodipodi:linespacing="125%"
id="tasLbl"
y="53.306854"
x="170.17084"
style="font-size:36px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ededed;fill-opacity:1;stroke:none;display:inline;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"
xml:space="preserve"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
y="53.306854"
x="170.17084"
id="tspan3821"
sodipodi:role="line"
style="font-size:36px">TAS</tspan></text>
<text
xml:space="preserve"
style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans"
x="309.88889"
y="579.33337"
id="text4101"
sodipodi:linespacing="125%"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
sodipodi:role="line"
id="tspan4103"
x="309.88889"
y="579.33337">NO MAP AVAIL</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4105"
y="283.33337"
x="513.88892"
style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;font-family:Sans;-inkscape-font-specification:Sans"
xml:space="preserve"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><tspan
sodipodi:role="line"
id="tspan4109"
x="513.88892"
y="283.33337">HDG</tspan></text>
</g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="PLAN"
style="display:inline"><g
style="display:inline"
id="planArcs"
inkscape:label="#g3956"
transform="matrix(1.02827,0,0,1.0306342,-14.7256,-31.455079)"
inkscape:export-filename="/Users/artix/projects/FlightGear/Aircrafts/A330-200/Models/Instruments/ND/canvas/res/airbusNDNoMap.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"><path
style="fill:none;stroke:#ff0000;stroke-width:3.99999905000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
d="M 542,956.688 C 767.783,941.437 946.219,753.462 946.219,523.812 946.219,294.164 767.783,106.188 542,90.9375 522,90.94783 502,90.95817 482,90.9685 256.534,106.544 78.4688,294.391 78.4688,523.812 c 0,229.423 178.0652,417.237 403.5312,432.813 20,0.021 40,0.042 60,0.063 z"
transform="matrix(0.972507,0,0,0.972507,14.3208,28.3815)"
id="path3171"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccscc" /><path
sodipodi:nodetypes="csccscc"
inkscape:connector-curvature="0"
id="path3232"
d="M 483.06917,746.91246 C 380.39674,732.55923 301.36207,644.41995 301.36207,537.79234 c 0,-106.62762 79.0337,-194.79705 181.7071,-209.1493 19.45014,-0.0304 38.90028,-0.061 58.35042,-0.0914 102.99141,14.06829 182.34506,102.38748 182.34506,209.24072 0,106.8542 -79.35365,195.14228 -182.34506,209.21154 -11.39099,3.20745 -45.79654,1.82775 -58.35042,-0.0914"
style="fill:none;stroke:#ff0000;stroke-width:3.89002705000000004;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:32, 16" /></g></g></svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg3090"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="Nuovo documento 10">
<defs
id="defs3092" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8.6118945"
inkscape:cx="24.13482"
inkscape:cy="21.929539"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1256"
inkscape:window-height="677"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata3095">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g3120"
transform="translate(0.81282928,-0.3483554)">
<g
id="g3110">
<rect
style="fill:#af0063;stroke:#af0063"
id="rect3106"
width="31.128778"
height="1.1431472"
x="7.7382278"
y="-24.606066"
transform="scale(1,-1)" />
<rect
transform="matrix(0,-1,-1,0,0,0)"
y="-23.874191"
x="-39.598881"
height="1.1431472"
width="31.128778"
id="rect3108"
style="fill:#af0063;stroke:#af0063" />
</g>
<g
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-10.169774,23.516978)"
id="g3114">
<rect
transform="scale(1,-1)"
y="-24.606066"
x="7.7382278"
height="1.1431472"
width="31.128778"
id="rect3116"
style="fill:#af0063;stroke:#af0063" />
<rect
style="fill:#af0063;stroke:#af0063"
id="rect3118"
width="31.128778"
height="1.1431472"
x="-39.598881"
y="-23.874191"
transform="matrix(0,-1,-1,0,0,0)" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg2985"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="airbus_decel.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.3"
inkscape:cx="-12.902798"
inkscape:cy="24.002241"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="665"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
sodipodi:type="arc"
style="fill:none;stroke:#af0063;stroke-width:1.47335875;stroke-miterlimit:4;stroke-dasharray:none"
id="path5312"
sodipodi:cx="24.069767"
sodipodi:cy="23.581396"
sodipodi:rx="17.55814"
sodipodi:ry="16.976744"
d="m 41.627907,23.581396 a 17.55814,16.976744 0 1 1 -35.1162798,0 17.55814,16.976744 0 1 1 35.1162798,0 z"
transform="matrix(1.3347658,0,0,1.3804934,-7.6915012,-8.9902419)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#af0063;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
x="24.799843"
y="38.763"
id="text6082"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan6084"
x="24.799843"
y="38.763">D</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg2985"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="airbus_ec.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.27"
inkscape:cx="11.14417"
inkscape:cy="15.800695"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="665"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,16)">
<g
id="ec_symbol"
style="stroke:#af0063;stroke-opacity:1"
transform="matrix(1.4141414,0,0,1.4141414,-2.4444435,-18.040404)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path2993"
d="m 2.9285709,34.185715 12.3428571,-12.685716 30.514286,0 -4.8,-7.542856"
style="fill:none;stroke:#af0063;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#af0063;stroke-width:2.4000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 45.785714,21.561266 -4.8,7.542856"
id="path3094"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg2985"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="airbus_ed.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.27"
inkscape:cx="20.916465"
inkscape:cy="8.2105622"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1280"
inkscape:window-height="707"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,16)">
<g
id="ed_symbol"
transform="matrix(1.4141414,0,0,-1.4141414,-2.4444435,50.040404)"
style="stroke:#118eff;stroke-opacity:1">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path2993"
d="m 2.9285709,34.185715 12.3428571,-12.685716 30.514286,0 -4.8,-7.542856"
style="fill:none;stroke:#118eff;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#118eff;stroke-width:2.4000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 45.785714,21.561266 -4.8,7.542856"
id="path3094"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg6263"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="airbus_hold_r.svg">
<defs
id="defs6265" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="11.363636"
inkscape:cy="39.272727"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="64"
inkscape:window-height="64"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata6268">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
d="m 38,58 l 0,-38 a 10,10 0 1 1 -20,0 l -5,-7 m5,7 l 8,-2"
id="path7043"
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:55.40000153;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg6263"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="airbus_holdL.svg">
<defs
id="defs6265" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="11.363636"
inkscape:cy="36.978476"
inkscape:current-layer="svg6263"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1280"
inkscape:window-height="703"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata6268">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="matrix(-1,0,0,1,59,0)">
<path
d="m 38,58 0,-38 a 10,10 0 1 1 -20,0 l -5,-7 m 5,7 8,-2"
id="path7043"
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:55.40000153;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg2985"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="airbus_sc.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.3"
inkscape:cx="-5.4609374"
inkscape:cy="24.002241"
inkscape:current-layer="Layer 1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="665"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="Layer 1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,16)">
<path
style="fill:#none;stroke:#ffffff;stroke-width:2.71867251px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.3593362,25.441164 c 57.6349168,0 44.8142078,0 44.8142078,0 L 59.060855,7.743855 62.640664,20.38479 M 45.871697,8.415439 59.720683,6.558836"
id="sc_symbol"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg2985"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="airbus_sd.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.3"
inkscape:cx="-8.8230046"
inkscape:cy="24.039449"
inkscape:current-layer="Layer 1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="665"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="Layer 1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,16)">
<path
style="fill:#none;stroke:#ffffff;stroke-width:2.71867251px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.3593362,6.558836 c 57.6349168,0 44.8142078,0 44.8142078,0 l 12.887311,17.697308 3.579809,-12.640933 m -16.768967,11.96935 13.848986,1.856603"
id="sd_symbol"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 111 KiB

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg2985"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="airbus_tc.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.27"
inkscape:cx="14.464853"
inkscape:cy="15.800695"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="665"
inkscape:window-x="93"
inkscape:window-y="92"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,16)">
<g
id="tc_symbol"
transform="matrix(1.4141414,0,0,1.4141414,-2.4444435,-18.040404)">
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path2993"
d="m 2.9285709,34.185715 12.3428571,-12.685716 30.514286,0 -4.8,-7.542856"
style="fill:none;stroke:#118eff;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
style="fill:none;stroke:#118eff;stroke-width:2.4000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 45.785714,21.561266 -4.8,7.542856"
id="path3094"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
id="svg2985"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="airbus_td.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.3"
inkscape:cx="-39.646984"
inkscape:cy="24.002241"
inkscape:current-layer="Layer 1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="665"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="Layer 1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,16)">
<path
style="fill:#none;stroke:#ffffff;stroke-width:2.71867251px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.3593362,6.558836 c 57.6349168,0 44.8142078,0 44.8142078,0 l 12.887311,17.697308 3.579809,-12.640933 m -16.768967,11.96935 13.848986,1.856603"
id="td_symbol"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50"
height="50"
id="svg3076"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="airbus-vor.svg">
<metadata
id="metadata3092">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3090" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1248"
inkscape:window-height="703"
id="namedview3088"
showgrid="false"
inkscape:zoom="1.6619718"
inkscape:cx="-33.09322"
inkscape:cy="71"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg3076" />
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<g
id="g3078"
inkscape:groupmode="layer"
transform="matrix(0.34013605,0,0,0.33783784,0.84746249,0.78240397)">
<title
id="title3080">Layer 1</title>
<g
id="svg_7">
<line
id="svg_3"
y2="71"
x2="142"
y1="71"
x1="112"
style="fill:none;stroke:#b00064;stroke-width:5" />
<circle
id="svg_2"
r="39.115215"
cy="71.5"
cx="71"
sodipodi:cx="71"
sodipodi:cy="71.5"
sodipodi:rx="39.115215"
sodipodi:ry="39.115215"
style="fill:none;stroke:#b00064;stroke-width:5"
d="m 110.11522,71.5 c 0,21.602737 -17.512483,39.11522 -39.11522,39.11522 -21.602737,0 -39.115215,-17.512483 -39.115215,-39.11522 0,-21.602737 17.512478,-39.115215 39.115215,-39.115215 21.602737,0 39.11522,17.512478 39.11522,39.115215 z" />
<line
id="svg_4"
y2="71"
x2="30"
y1="71"
x1="0"
style="fill:none;stroke:#b00064;stroke-width:5" />
<line
transform="matrix(0,1,-1,0,198,58)"
id="svg_5"
y2="128"
x2="85"
y1="128"
x1="55"
style="fill:none;stroke:#b00064;stroke-width:5" />
<line
id="svg_6"
transform="matrix(0,1,-1,0,85,-55)"
y2="15"
x2="85"
y1="15"
x1="55"
style="fill:none;stroke:#b00064;stroke-width:5" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg2985"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="airbus_vor.svg">
<defs
id="defs2987" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.7255132"
inkscape:cx="41.056088"
inkscape:cy="29.220813"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1197"
inkscape:window-height="667"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:window-maximized="0" />
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="airbus-vor-sym"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
sodipodi:type="arc"
style="fill:none;stroke:#af0063;stroke-width:1.57920909;stroke-miterlimit:4;stroke-dasharray:none"
id="path3014"
sodipodi:cx="28.214285"
sodipodi:cy="22.642857"
sodipodi:rx="10.5"
sodipodi:ry="10.214286"
d="m 38.714285,22.642857 a 10.5,10.214286 0 1 1 -21,0 10.5,10.214286 0 1 1 21,0 z"
transform="matrix(1.1857807,0,0,1.2189494,-9.1389546,-3.9914967)" />
<path
inkscape:connector-curvature="0"
id="path3084"
d="m 36.915889,23.738251 c 7.210196,0 9.210196,0 9.210196,0 l 0,0"
style="fill:none;stroke:#af0063;stroke-width:2.23682857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#af0063;stroke-width:2.22900009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 24.316735,1.1057656 c 0,7.8137242 0,7.8137242 0,7.8137242 l 0,2.0000002"
id="path3086"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
inkscape:connector-curvature="0"
id="path3088"
d="m 24.316735,35.872915 c 0,7.462294 0,9.462294 0,9.462294 l 0,0"
style="fill:none;stroke:#af0063;stroke-width:2.22900009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#af0063;stroke-width:2.23682857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 3.3195483,23.738251 c 7.2101957,0 7.2101957,0 7.2101957,0 l 2,0"
id="path4589"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<PropertyList>
<api-key type="string"></api-key>
<layer-type type="string">radar</layer-type>
<resolution type="int">2048</resolution>
<fetch-radius type="int">240</fetch-radius>
<smooth type="bool">true</smooth>
<enabled type="bool">false</enabled>
</PropertyList>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

View file

@ -4,16 +4,14 @@ OBJECT world
kids 1
OBJECT poly
name "ND.screen"
loc 0.002183 0.00101281 -1.84312e-005
data 10
ND.screenL
loc 0.000703464 0.00085881 7.61527e-005
texture "screen.png"
crease 30.000002
crease 30.000000
numvert 4
0 0.0788224 -0.0771343
0 -0.0733778 -0.0771343
0 -0.0733778 0.076915
0 0.0788224 0.076915
0.00169254 0.0788742 -0.0787579
0.00169254 -0.0731794 -0.0787579
0.00169254 -0.0731794 0.078523
0.00169254 0.0788742 0.078523
numsurf 1
SURF 0x0
mat 0

View file

@ -3,17 +3,15 @@ MATERIAL "buttonlights" rgb 1 1 1 amb 1 1 1 emis 1 1 1 spec 0.33 0.33 0.33 s
OBJECT world
kids 1
OBJECT poly
name "ND.screen"
loc 0.002183 0.00101281 -1.84312e-005
data 10
ND.screenR
name "ND_R.screen"
loc 0.000703464 0.00085881 7.61527e-005
texture "screen.png"
crease 30.000002
crease 30.000000
numvert 4
0 0.0788224 -0.0771343
0 -0.0733778 -0.0771343
0 -0.0733778 0.076915
0 0.0788224 0.076915
0.00169254 0.0788742 -0.0787579
0.00169254 -0.0731794 -0.0787579
0.00169254 -0.0731794 0.078523
0.00169254 0.0788742 0.078523
numsurf 1
SURF 0x0
mat 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View file

@ -0,0 +1,3 @@
AC3Db
OBJECT world
kids 0

View file

Before

Width:  |  Height:  |  Size: 629 B

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -4,6 +4,9 @@ setlistener("sim/signals/fdm-initialized", func {
setprop("/instrumentation/efis/nd/display-mode", "NAV");
setprop("/instrumentation/efis/mfd/pnl_mode-num", 2);
setprop("/instrumentation/efis/inputs/range-nm", 20);
setprop("/instrumentation/efis[1]/nd/display-mode", "NAV");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 2);
setprop("/instrumentation/efis[1]/inputs/range-nm", 20);
setprop("/controls/lighting/ndl-norm", "1");
setprop("/controls/lighting/ndr-norm", "1");
});
@ -62,3 +65,57 @@ var mode_dec = func {
}
}
# First Officer
var ctl2_func = func(md,val) {
if(md == "range") {
var rng = getprop("/instrumentation/efis[1]/inputs/range-nm");
if(val ==1){
rng = rng * 2;
if(rng > 640) rng = 640;
} else if(val = -1){
rng = rng / 2;
if(rng < 10) rng = 10;
}
setprop("/instrumentation/efis[1]/inputs/range-nm", rng);
}
}
var mode2_inc = func {
var mode = getprop("/instrumentation/efis[1]/nd/display-mode");
if (mode == "ILS") {
setprop("/instrumentation/efis[1]/nd/display-mode", "VOR");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 1);
} else if (mode == "VOR") {
setprop("/instrumentation/efis[1]/nd/display-mode", "NAV");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 2);
} else if (mode == "NAV") {
setprop("/instrumentation/efis[1]/nd/display-mode", "ARC");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 3);
} else if (mode == "ARC") {
setprop("/instrumentation/efis[1]/nd/display-mode", "PLAN");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 4);
} else {
return 0;
}
}
var mode2_dec = func {
var mode = getprop("/instrumentation/efis[1]/nd/display-mode");
if (mode == "PLAN") {
setprop("/instrumentation/efis[1]/nd/display-mode", "ARC");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 3);
} else if (mode == "ARC") {
setprop("/instrumentation/efis[1]/nd/display-mode", "NAV");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 2);
} else if (mode == "NAV") {
setprop("/instrumentation/efis[1]/nd/display-mode", "VOR");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 1);
} else if (mode == "VOR") {
setprop("/instrumentation/efis[1]/nd/display-mode", "ILS");
setprop("/instrumentation/efis[1]/mfd/pnl_mode-num", 0);
} else {
return 0;
}
}