A3XX: New independant improved NDs
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
680
Models/Instruments/ND/ND.bck.nas
Normal 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"] );
|
||||
}
|
||||
|
||||
|
|
@ -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"] );
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
39
Models/Instruments/ND/canvas/A3XX_ND.nas
Normal 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');
|
105
Models/Instruments/ND/canvas/A3XX_ND_drivers.nas
Normal 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')
|
||||
]}
|
||||
};
|
150
Models/Instruments/ND/canvas/ND.nas
Normal 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] );
|
||||
}
|
21
Models/Instruments/ND/canvas/ND_config.nas
Normal 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",
|
||||
}
|
||||
};
|
355
Models/Instruments/ND/canvas/canvas_compat.nas
Normal 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]
|
||||
};
|
||||
|
||||
|
116
Models/Instruments/ND/canvas/framework/MapDrivers.nas
Normal 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;
|
||||
}
|
||||
};
|
303
Models/Instruments/ND/canvas/framework/canvas.nas
Normal 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');
|
||||
};
|
||||
|
582
Models/Instruments/ND/canvas/framework/navdisplay.nas
Normal 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);
|
||||
};
|
139
Models/Instruments/ND/canvas/helpers.nas
Normal 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);
|
||||
}
|
||||
};
|
83
Models/Instruments/ND/canvas/loaders.nas
Normal 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);
|
112
Models/Instruments/ND/canvas/map.removed/HOLD.lcontroller
Normal 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;
|
||||
}
|
12
Models/Instruments/ND/canvas/map.removed/HOLD.scontroller
Normal 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');
|
124
Models/Instruments/ND/canvas/map.removed/HOLD.symbol
Normal 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);
|
||||
}
|
||||
}
|
47
Models/Instruments/ND/canvas/map/ALT-profile.lcontroller
Normal 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;
|
||||
}
|
||||
|
12
Models/Instruments/ND/canvas/map/ALT-profile.scontroller
Normal 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');
|
51
Models/Instruments/ND/canvas/map/ALT-profile.symbol
Normal 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');
|
||||
}
|
||||
|
26
Models/Instruments/ND/canvas/map/APS.lcontroller
Normal 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;
|
||||
|
12
Models/Instruments/ND/canvas/map/APS.scontroller
Normal 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');
|
19
Models/Instruments/ND/canvas/map/APS.symbol
Normal 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);
|
||||
};
|
||||
|
47
Models/Instruments/ND/canvas/map/APT.lcontroller
Normal 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);
|
||||
};
|
||||
|
16
Models/Instruments/ND/canvas/map/APT.scontroller
Normal 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];
|
||||
}
|
||||
|
44
Models/Instruments/ND/canvas/map/APT.symbol
Normal 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;
|
||||
|
71
Models/Instruments/ND/canvas/map/DEBUG.lcontroller
Normal 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;
|
||||
}
|
29
Models/Instruments/ND/canvas/map/DEBUG.symbol
Normal 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{
|
||||
|
||||
}
|
37
Models/Instruments/ND/canvas/map/DECEL.lcontroller
Normal 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;
|
||||
}
|
12
Models/Instruments/ND/canvas/map/DECEL.scontroller
Normal 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');
|
32
Models/Instruments/ND/canvas/map/DECEL.symbol
Normal 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);
|
||||
}
|
||||
}
|
152
Models/Instruments/ND/canvas/map/DME.symbol
Normal 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();
|
||||
};
|
||||
|
31
Models/Instruments/ND/canvas/map/FIX.lcontroller
Normal 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');
|
||||
|
12
Models/Instruments/ND/canvas/map/FIX.scontroller
Normal 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" );
|
||||
|
60
Models/Instruments/ND/canvas/map/FIX.symbol
Normal 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');};
|
32
Models/Instruments/ND/canvas/map/NDB.lcontroller
Normal 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');
|
||||
|
||||
|
12
Models/Instruments/ND/canvas/map/NDB.scontroller
Normal 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" );
|
||||
|
7
Models/Instruments/ND/canvas/map/NDB.symbol
Normal 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,
|
||||
});
|
||||
|
100
Models/Instruments/ND/canvas/map/RTE.lcontroller
Normal 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;
|
||||
};
|
||||
|
12
Models/Instruments/ND/canvas/map/RTE.scontroller
Normal 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');
|
46
Models/Instruments/ND/canvas/map/RTE.symbol
Normal 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();
|
||||
#};
|
||||
|
105
Models/Instruments/ND/canvas/map/RWY-profile.lcontroller
Normal 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;
|
||||
};
|
12
Models/Instruments/ND/canvas/map/RWY-profile.scontroller
Normal 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');
|
93
Models/Instruments/ND/canvas/map/RWY-profile.symbol
Normal 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();
|
||||
#}
|
51
Models/Instruments/ND/canvas/map/SPD-profile.lcontroller
Normal 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;
|
||||
}
|
12
Models/Instruments/ND/canvas/map/SPD-profile.scontroller
Normal 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');
|
40
Models/Instruments/ND/canvas/map/SPD-profile.symbol
Normal 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);
|
||||
}
|
||||
|
||||
}
|
62
Models/Instruments/ND/canvas/map/VOR-airbus.lcontroller
Normal 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');
|
43
Models/Instruments/ND/canvas/map/VOR-airbus.symbol
Normal 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]));
|
||||
}
|
137
Models/Instruments/ND/canvas/map/WPT-airbus.lcontroller
Normal 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;
|
||||
}
|
137
Models/Instruments/ND/canvas/map/WPT-airbus.symbol
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
72
Models/Instruments/ND/canvas/map/WXR_live.lcontroller
Normal 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];
|
||||
};
|
114
Models/Instruments/ND/canvas/map/WXR_live.symbol
Normal 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~"¢erlon="~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);
|
||||
}
|
||||
};
|
||||
|
70
Models/Instruments/ND/canvas/res/airbusAirplane.svg
Normal 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 |
2120
Models/Instruments/ND/canvas/res/airbusND.svg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
Models/Instruments/ND/canvas/res/airbusNDNoMap.png
Normal file
After Width: | Height: | Size: 50 KiB |
236
Models/Instruments/ND/canvas/res/airbusNDNoMap.svg
Normal 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 |
99
Models/Instruments/ND/canvas/res/airbus_airport.svg
Normal 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 |
77
Models/Instruments/ND/canvas/res/airbus_decel.svg
Normal 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 |
74
Models/Instruments/ND/canvas/res/airbus_ec.svg
Normal 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 |
74
Models/Instruments/ND/canvas/res/airbus_ed.svg
Normal 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 |
60
Models/Instruments/ND/canvas/res/airbus_holdL.svg
Normal 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 |
62
Models/Instruments/ND/canvas/res/airbus_holdR.svg
Normal 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 |
63
Models/Instruments/ND/canvas/res/airbus_sc.svg
Normal 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 |
63
Models/Instruments/ND/canvas/res/airbus_sd.svg
Normal 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 |
156
Models/Instruments/ND/canvas/res/airbus_spd_limit.svg
Normal file
After Width: | Height: | Size: 111 KiB |
73
Models/Instruments/ND/canvas/res/airbus_tc.svg
Normal 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 |
63
Models/Instruments/ND/canvas/res/airbus_td.svg
Normal 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 |
101
Models/Instruments/ND/canvas/res/airbus_vor.old.svg
Normal 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 |
90
Models/Instruments/ND/canvas/res/airbus_vor.svg
Normal 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 |
1784
Models/Instruments/ND/canvas/style.nas
Normal file
10
Models/Instruments/ND/canvas/wxr_api.xml
Normal 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>
|
BIN
Models/Instruments/ND/res/A320neo_symbols.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
Models/Instruments/ND/res/Main_Displays.png
Normal file
After Width: | Height: | Size: 5.5 MiB |
|
@ -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
|
|
@ -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
|
BIN
Models/Instruments/ND/res/airbus_symbols.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
Models/Instruments/ND/res/black.png
Normal file
After Width: | Height: | Size: 135 B |
BIN
Models/Instruments/ND/res/hsi2a.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
Models/Instruments/ND/res/hsiarc.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
Models/Instruments/ND/res/mask.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
Models/Instruments/ND/res/maskfull.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
3
Models/Instruments/ND/res/nd-empty.ac
Normal file
|
@ -0,0 +1,3 @@
|
|||
AC3Db
|
||||
OBJECT world
|
||||
kids 0
|
Before Width: | Height: | Size: 629 B After Width: | Height: | Size: 629 B |
BIN
Models/Instruments/ND/res/screen.png
Normal file
After Width: | Height: | Size: 629 B |
BIN
Models/Instruments/ND/res/symbols.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
Models/Instruments/ND/res/terrain-gradient.png
Normal file
After Width: | Height: | Size: 552 B |
17669
Models/Instruments/ND/res/terrain-map-pixel.ac
Normal file
BIN
Models/Instruments/ND/res/transparent.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
Models/Instruments/ND/res/wxecho.png
Normal file
After Width: | Height: | Size: 4 KiB |
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|