Boeing ND:
- add VOR, APP, PLAN and CTR modes. - add true/mag switch - display waypoint altitudes
This commit is contained in:
parent
a4e35e255a
commit
2b6964911f
12 changed files with 1677 additions and 264 deletions
|
@ -369,6 +369,5 @@ settimer(func {
|
|||
me.del();
|
||||
};
|
||||
}, 1);
|
||||
else print("MapStructure.nas: Testing code disabled, see $FG_ROOT/gui/dialogs/map-canvas.xml instead");
|
||||
}, 0); # end ugly module init timer hack
|
||||
|
||||
|
|
19
Nasal/canvas/map/airplane-symbol.draw
Normal file
19
Nasal/canvas/map/airplane-symbol.draw
Normal file
|
@ -0,0 +1,19 @@
|
|||
##
|
||||
# draw a single airplane symbol
|
||||
#
|
||||
|
||||
var draw_airplane_symbol = func (group, apl, controller=nil, lod=0) {
|
||||
var lat = apl.lat;
|
||||
var lon = apl.lon;
|
||||
var hdg = apl.hdg;
|
||||
|
||||
var airplane_grp = group.createChild("group","airplane");
|
||||
canvas.parsesvg(airplane_grp, "Nasal/canvas/map/boeingAirplane.svg");
|
||||
var aplSymbol = airplane_grp.getElementById("airplane");
|
||||
|
||||
aplSymbol.setTranslation(-45,-52)
|
||||
.setCenter(0,0);
|
||||
airplane_grp.setGeoPosition(lat, lon)
|
||||
.set("z-index",10)
|
||||
.setRotation(hdg*D2R);
|
||||
}
|
10
Nasal/canvas/map/airplane-symbol.layer
Normal file
10
Nasal/canvas/map/airplane-symbol.layer
Normal file
|
@ -0,0 +1,10 @@
|
|||
var AirplaneSymbolLayer = {};
|
||||
AirplaneSymbolLayer.new = func(group,name, controller) {
|
||||
var m=Layer.new(group, name, AirplaneSymbolModel);
|
||||
m._model._controller = controller; # set up the controller for the model !!!!!
|
||||
m.setDraw (func draw_layer(layer:m, callback: draw_airplane_symbol, lod:0) );
|
||||
return m;
|
||||
}
|
||||
|
||||
register_layer("airplaneSymbol", AirplaneSymbolLayer);
|
||||
|
12
Nasal/canvas/map/airplane-symbol.model
Normal file
12
Nasal/canvas/map/airplane-symbol.model
Normal file
|
@ -0,0 +1,12 @@
|
|||
var AirplaneSymbolModel = {};
|
||||
AirplaneSymbolModel.new = func make( LayerModel, AirplaneSymbolModel );
|
||||
|
||||
AirplaneSymbolModel.init = func {
|
||||
me._view.reset(); # wraps removeAllChildren() ATM
|
||||
|
||||
me.push( { lat: getprop("/position/latitude-deg"), lon : getprop("/position/longitude-deg"), hdg : getprop("/orientation/heading-deg") } );
|
||||
|
||||
me.notifyView();
|
||||
}
|
||||
|
||||
|
70
Nasal/canvas/map/boeingAirplane.svg
Normal file
70
Nasal/canvas/map/boeingAirplane.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="path3783"
|
||||
d="M 29.126,102.65 29.2323,93.5433 35.3622,85.2874 34.6535,58.0039 2.12598,76.3228 1.98425,65.9764 35.185,35.5394 35.3976,15.0945 42.378,2.01969 50.563,15.5197 50.315,35.4685 85.8543,65.6575 85.748,75.0118 52.3701,56.9409 52.0157,86.2441 58.748,93.6496 58.6417,103.5 44.0787,95.4921 z"
|
||||
style="fill:none;stroke:#ededed;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.3 KiB |
File diff suppressed because it is too large
Load diff
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 82 KiB |
|
@ -4,23 +4,15 @@ FixModel.new = func make( LayerModel, FixModel );
|
|||
FixModel.init = func {
|
||||
me._view.reset(); # wraps removeAllChildren() ATM
|
||||
|
||||
#fgcommand('profiler-start');
|
||||
#me._view._view.removeAllChildren(); # clear the "real" canvas drawables
|
||||
#fgcommand('profiler-stop');
|
||||
#me.clear();
|
||||
|
||||
#debug.dump( me._controller) ;
|
||||
#print("Query range is:", me._controller['query_range']() );
|
||||
|
||||
var results = positioned.findWithinRange( me._controller['query_range']()*2 ,"fix");
|
||||
var numNum = 0;
|
||||
foreach(result; results) {
|
||||
me.push(result);
|
||||
# Skip airport navaids (real thing makes distinction between high/low altitude fixes)
|
||||
if(string.match(result.id,"*[^0-9]")) {
|
||||
me.push(result);
|
||||
numNum = numNum + 1;
|
||||
}
|
||||
}
|
||||
|
||||
#print("query range was:", me._controller['query_range']()*2);
|
||||
#print("total fixes in results/model:", size(results));
|
||||
|
||||
me.notifyView();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -6,6 +6,4 @@ NavaidModel.init = func {
|
|||
foreach(var n; navaids)
|
||||
me.push(n);
|
||||
me.notifyView();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
# ==============================================================================
|
||||
# Boeing Navigation Display by Gijs de Rooy (currently specific to the 744)
|
||||
# Boeing Navigation Display by Gijs de Rooy
|
||||
# ==============================================================================
|
||||
|
||||
|
||||
|
@ -52,12 +52,10 @@ var NDStyles = {
|
|||
##
|
||||
|
||||
layers: [
|
||||
{ name:'fixes', update_on:['toggle_range','toggle_waypoints'], predicate: func(nd, layer) {
|
||||
{ name:'fixes', update_on:['toggle_range','toggle_waypoints','toggle_display_mode'], predicate: func(nd, layer) {
|
||||
# print("Running fixes predicate");
|
||||
var visible=nd.get_switch('toggle_waypoints');
|
||||
if(nd.rangeNm() <= 40 and visible and
|
||||
nd.get_switch('toggle_display_mode') == "MAP") {
|
||||
# print("fixes update requested!");
|
||||
var visible=nd.get_switch('toggle_waypoints') and nd.in_mode('toggle_display_mode', ['MAP']);
|
||||
if(nd.rangeNm() <= 40 and visible) {
|
||||
trigger_update( layer );
|
||||
} layer._view.setVisible(visible);
|
||||
|
||||
|
@ -69,7 +67,16 @@ var NDStyles = {
|
|||
# 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_range','toggle_display_mode'], predicate: func(nd, layer) {
|
||||
# print("Running fixes predicate");
|
||||
var visible=nd.get_switch('toggle_display_mode') == "PLAN";
|
||||
if (visible) {
|
||||
trigger_update( layer );
|
||||
} layer._view.setVisible(visible);
|
||||
|
||||
|
@ -78,54 +85,53 @@ var NDStyles = {
|
|||
|
||||
{ name:'airports-nd', update_on:['toggle_range','toggle_airports','toggle_display_mode'], predicate: func(nd, layer) {
|
||||
# print("Running airports-nd predicate");
|
||||
if (nd.rangeNm() <= 80 and
|
||||
nd.get_switch('toggle_display_mode') == "MAP" ) {
|
||||
trigger_update( layer ); # clear & redraw
|
||||
var visible = nd.get_switch('toggle_airports') and nd.in_mode('toggle_display_mode', ['MAP']);
|
||||
if (nd.rangeNm() <= 80 and visible) {
|
||||
trigger_update( layer ); # clear & redraw
|
||||
}
|
||||
layer._view.setVisible( nd.get_switch('toggle_airports') );
|
||||
layer._view.setVisible( visible);
|
||||
|
||||
}, # end of layer update predicate
|
||||
}, # end of airports layer
|
||||
|
||||
{ name:'vor', update_on:['toggle_range','toggle_stations','toggle_display_mode'], predicate: func(nd, layer) {
|
||||
# print("Running vor layer predicate");
|
||||
if(nd.rangeNm() <= 40 and
|
||||
nd.get_switch('toggle_stations') and
|
||||
nd.get_switch('toggle_display_mode') == "MAP"){
|
||||
var visible = nd.get_switch('toggle_stations') and nd.in_mode('toggle_display_mode', ['MAP']);
|
||||
if(nd.rangeNm() <= 40 and visible) {
|
||||
trigger_update( layer ); # clear & redraw
|
||||
}
|
||||
layer._view.setVisible( nd.get_switch('toggle_stations') );
|
||||
layer._view.setVisible( visible );
|
||||
}, # end of layer update predicate
|
||||
}, # end of VOR layer
|
||||
|
||||
{ name:'dme', update_on:['toggle_range','toggle_stations'], predicate: func(nd, layer) {
|
||||
if(nd.rangeNm() <= 40 and
|
||||
nd.get_switch('toggle_stations') and
|
||||
nd.get_switch('toggle_display_mode') == "MAP"){
|
||||
{ name:'dme', update_on:['toggle_range','toggle_stations','toggle_display_mode'], predicate: func(nd, layer) {
|
||||
var visible = nd.get_switch('toggle_stations') and nd.in_mode('toggle_display_mode', ['MAP']);
|
||||
if(nd.rangeNm() <= 40 and visible){
|
||||
trigger_update( layer ); # clear & redraw
|
||||
}
|
||||
layer._view.setVisible( nd.get_switch('toggle_stations') );
|
||||
layer._view.setVisible( visible );
|
||||
}, # end of layer update predicate
|
||||
}, # end of DME layer
|
||||
|
||||
{ name:'mp-traffic', update_on:['toggle_range','toggle_traffic'], predicate: func(nd, layer) {
|
||||
trigger_update( layer ); # clear & redraw
|
||||
layer._view.setVisible( 1 ); #nd.get_switch('toggle_traffic')
|
||||
layer._view.setVisible( nd.get_switch('toggle_traffic') );
|
||||
}, # 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") ) ;
|
||||
var visible = (nd.rangeNm() <= 40 and getprop("autopilot/route-manager/active") and nd.in_mode('toggle_display_mode', ['MAP','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) {
|
||||
trigger_update( layer ); # clear & redraw
|
||||
layer._view.setVisible( 1 ); #nd.get_switch('toggle_traffic')
|
||||
{ name:'route', update_on:['toggle_display_mode',], predicate: func(nd, layer) {
|
||||
var visible= (nd.in_mode('toggle_display_mode', ['MAP','PLAN']));
|
||||
if (visible) {
|
||||
trigger_update( layer ); # clear & redraw
|
||||
}
|
||||
layer._view.setVisible( visible );
|
||||
}, # end of layer update predicate
|
||||
}, # end of route layer
|
||||
|
||||
|
@ -229,7 +235,7 @@ var NDStyles = {
|
|||
{ id:'rangeArcs',
|
||||
impl: {
|
||||
init: func(nd,symbol),
|
||||
predicate: func(nd) (((nd.get_switch('toggle_display_mode') == "APP" or nd.get_switch('toggle_display_mode') == "VOR") and nd.get_switch('toggle_weather')) or nd.get_switch('toggle_display_mode') == "MAP"),
|
||||
predicate: func(nd) ((nd.in_mode('toggle_display_mode', ['APP','VOR']) and nd.get_switch('toggle_weather')) or (nd.get_switch('toggle_display_mode') == "MAP" and !nd.get_switch('toggle_centered'))),
|
||||
is_true: func(nd) nd.symbols.rangeArcs.show(),
|
||||
is_false: func(nd) nd.symbols.rangeArcs.hide(),
|
||||
}, # of rangeArcs.impl
|
||||
|
@ -256,10 +262,13 @@ var NDSourceDriver = {};
|
|||
NDSourceDriver.new = func {
|
||||
var m = {parents:[NDSourceDriver]};
|
||||
m.get_hdg_mag= func getprop("/orientation/heading-magnetic-deg");
|
||||
m.get_hdg_tru= func getprop("/orientation/heading-deg");
|
||||
m.get_trk_mag= func getprop("/orientation/track-magnetic-deg");
|
||||
m.get_trk_tru= func getprop("/orientation/track-deg");
|
||||
m.get_lat= func getprop("/position/latitude-deg");
|
||||
m.get_lon= func getprop("/position/longitude-deg");
|
||||
m.get_spd= func getprop("/velocities/groundspeed-kt");
|
||||
m.get_vspd= func getprop("/velocities/vertical-speed-fps");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
@ -275,7 +284,7 @@ return m;
|
|||
# TODO: switches are ND specific, so move to the NDStyle hash!
|
||||
|
||||
var default_switches = {
|
||||
'toggle_range': {path: '/inputs/range-nm', value:40, type:'INT'},
|
||||
'toggle_range': {path: '/inputs/range-nm', value:10, 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'},
|
||||
|
@ -283,8 +292,10 @@ var default_switches = {
|
|||
'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/tcas',value:0, type:'BOOL'},
|
||||
'toggle_traffic': {path: '/inputs/tfc',value:0, type:'BOOL'},
|
||||
'toggle_centered': {path: '/inputs/nd-centered',value:0, type:'BOOL'},
|
||||
'toggle_display_mode': {path: '/mfd/display-mode', value:'MAP', type:'STRING'},
|
||||
'toggle_true_north': {path: '/mfd/true-north', value:0, type:'BOOL'},
|
||||
};
|
||||
|
||||
# Hack to update weather radar once every 10 seconds
|
||||
|
@ -295,6 +306,14 @@ var update_weather = func {
|
|||
}
|
||||
update_weather();
|
||||
|
||||
# Hack to update airplane symbol location on PLAN mode every 5 seconds
|
||||
var update_apl_sym = func {
|
||||
if (getprop("/instrumentation/efis/mfd/display-mode") == "PLAN")
|
||||
setprop("/instrumentation/efis/mfd/display-mode","PLAN");
|
||||
settimer(update_apl_sym, 5);
|
||||
}
|
||||
update_apl_sym();
|
||||
|
||||
##
|
||||
# TODO:
|
||||
# - introduce a MFD class (use it also for PFD/EICAS)
|
||||
|
@ -342,13 +361,16 @@ var NavDisplay = {
|
|||
|
||||
# for creating NDs that are driven by AI traffic instead of the main aircraft (generalization rocks!)
|
||||
connectAI: func(source=nil) {
|
||||
me.aircraft_source = {
|
||||
get_hdg_mag: func source.getNode('orientation/heading-magnetic-deg').getValue(),
|
||||
get_trk_mag: func source.getNode('orientation/track-magnetic-deg').getValue(),
|
||||
get_lat: func source.getNode('position/latitude-deg').getValue(),
|
||||
get_lon: func source.getNode('position/longitude-deg').getValue(),
|
||||
get_spd: func source.getNode('velocities/true-airspeed-kt').getValue(),
|
||||
};
|
||||
me.aircraft_source = {
|
||||
get_hdg_mag: func source.getNode('orientation/heading-magnetic-deg').getValue(),
|
||||
get_hdg_tru: func source.getNode('orientation/heading-deg').getValue(),
|
||||
get_trk_mag: func source.getNode('orientation/track-magnetic-deg').getValue(),
|
||||
get_trk_tru: func source.getNode('orientation/track-deg').getValue(),
|
||||
get_lat: func source.getNode('position/latitude-deg').getValue(),
|
||||
get_lon: func source.getNode('position/longitude-deg').getValue(),
|
||||
get_spd: func source.getNode('velocities/true-airspeed-kt').getValue(),
|
||||
get_vspd: func source.getNode('velocities/vertical-speed-fps').getValue(),
|
||||
};
|
||||
}, # of connectAI
|
||||
|
||||
# TODO: the ctor should allow customization, for different aircraft
|
||||
|
@ -444,14 +466,14 @@ var NavDisplay = {
|
|||
# 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; ["rotateComp","windArrow","selHdg",
|
||||
"curHdgPtr","staFromL","staToL","trkInd",
|
||||
"staFromR","staToR","compass","hdgTrk","truMag","altArc"] )
|
||||
foreach(var element; ["rotateComp","rotateComp2","windArrow","selHdg","selHdg2","hdgGroup","northUp",
|
||||
"aplSymMap","aplSymMapCtr","aplSymVor","curHdgPtr","curHdgPtr2",
|
||||
"staFromL","staToL","staFromR","staToR","staFromL2","staToL2","staFromR2","staToR2",
|
||||
"trkInd","vorCrsPtr2","locPtr","compass","compassApp","hdgTrk","truMag","altArc","planArcs"] )
|
||||
me.symbols[element] = me.nd.getElementById(element).updateCenter();
|
||||
|
||||
# this should probably be using Philosopher's new SymbolLayer ?
|
||||
me.map = me.nd.createChild("map","map")
|
||||
.setTranslation(512,824)
|
||||
.set("clip", "rect(124, 1024, 1024, 0)");
|
||||
|
||||
# this callback will be passed onto the model via the controller hash, and used for the positioned queries, to specify max query range:
|
||||
|
@ -535,10 +557,10 @@ var NavDisplay = {
|
|||
me.drawdme();
|
||||
});
|
||||
# TODO: move this to the route.model
|
||||
# Hack to draw the route on rm activation
|
||||
me.listen("/autopilot/route-manager/active", func(active) {
|
||||
if(active.getValue()) {
|
||||
me.drawroute();
|
||||
me.drawrunways();
|
||||
setprop(me.get_full_switch_path('toggle_display_mode'),getprop(me.get_full_switch_path('toggle_display_mode')));
|
||||
} else {
|
||||
print("TODO: navdisplay.mfd: implement route-manager/layer clearing!");
|
||||
#me.route_group.removeAllChildren(); # HACK!
|
||||
|
@ -552,10 +574,9 @@ var NavDisplay = {
|
|||
drawroute: func print("drawroute no longer used!"),
|
||||
drawrunways: func print("drawrunways no longer used!"),
|
||||
|
||||
in_mode:func(switch, modes) foreach(var m; modes) {
|
||||
if (me.get_switch(switch)==m) return 1;
|
||||
else continue;
|
||||
print("not in checked mode");
|
||||
in_mode:func(switch, modes) {
|
||||
foreach(var m; modes)
|
||||
if (me.get_switch(switch)==m) return 1;
|
||||
return 0;
|
||||
},
|
||||
|
||||
|
@ -579,17 +600,39 @@ var NavDisplay = {
|
|||
|
||||
# fgcommand('profiler-start');
|
||||
|
||||
# Heading update
|
||||
var userHdgMag = me.aircraft_source.get_hdg_mag();
|
||||
var userTrkMag = me.aircraft_source.get_trk_mag(); # getprop("orientation/heading-deg"); # orientation/track-magnetic-deg is noisy
|
||||
var userLat = me.aircraft_source.get_lat();
|
||||
var userLon = me.aircraft_source.get_lon();
|
||||
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')) {
|
||||
me.symbols.truMag.setText("TRU");
|
||||
var userHdg=userHdgTru;
|
||||
var userTrk=userTrkTru;
|
||||
} else {
|
||||
me.symbols.truMag.setText("MAG");
|
||||
var userHdg=userHdgMag;
|
||||
var userTrk=userTrkMag;
|
||||
}
|
||||
if (me.aircraft_source.get_spd() < 80)
|
||||
userTrk = userHdg;
|
||||
|
||||
var userLat = me.aircraft_source.get_lat();
|
||||
var userLon = me.aircraft_source.get_lon();
|
||||
var userSpd = me.aircraft_source.get_spd();
|
||||
var userVSpd = me.aircraft_source.get_vspd();
|
||||
|
||||
# this should only ever happen when testing the experimental AI/MP ND driver hash (not critical)
|
||||
if (!userHdgMag or !userTrkMag or !userLat or !userLon) {
|
||||
print("aircraft source invalid, returning !");
|
||||
return;
|
||||
if (!userHdg or !userTrk or !userLat or !userLon) {
|
||||
print("aircraft source invalid, returning !");
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.get_switch('toggle_centered') or me.in_mode('toggle_display_mode', ['PLAN']))
|
||||
me.map.setTranslation(512,512);
|
||||
else
|
||||
me.map.setTranslation(512,824);
|
||||
|
||||
# Calculate length in NM of one degree at current location TODO: expose as methods, for external callbacks
|
||||
var userLatR = userLat*D2R;
|
||||
var userLonR = userLon*D2R;
|
||||
|
@ -611,61 +654,149 @@ var NavDisplay = {
|
|||
me.symbols.dmeRDist.setText(sprintf("%3.1f",nav1dist*0.000539));
|
||||
|
||||
me.symbols.range.setText(sprintf("%3.0f",me.rangeNm() ));
|
||||
#rangeNm=rangeNm*2;
|
||||
|
||||
# reposition the map, change heading & range:
|
||||
me.map._node.getNode("ref-lat",1).setDoubleValue(userLat);
|
||||
me.map._node.getNode("ref-lon",1).setDoubleValue(userLon);
|
||||
if(me.in_mode('toggle_display_mode', ['PLAN'])) {
|
||||
me.symbols.windArrow.hide();
|
||||
me.map._node.getNode("hdg",1).setDoubleValue(0);
|
||||
if (getprop(me.efis_path ~ "/inputs/plan-wpt-index") >= 0) {
|
||||
me.map._node.getNode("ref-lat",1).setDoubleValue(getprop("/autopilot/route-manager/route/wp["~getprop(me.efis_path ~ "/inputs/plan-wpt-index")~"]/latitude-deg"));
|
||||
me.map._node.getNode("ref-lon",1).setDoubleValue(getprop("/autopilot/route-manager/route/wp["~getprop(me.efis_path ~ "/inputs/plan-wpt-index")~"]/longitude-deg"));
|
||||
}
|
||||
} else {
|
||||
me.symbols.windArrow.show();
|
||||
me.map._node.getNode("ref-lat",1).setDoubleValue(userLat);
|
||||
me.map._node.getNode("ref-lon",1).setDoubleValue(userLon);
|
||||
}
|
||||
me.map._node.getNode("range",1).setDoubleValue(me.rangeNm()/2); # avoid this here, use a listener instead
|
||||
|
||||
if(me.get_switch('toggle_display_mode') == 'MAP' or me.get_switch('toggle_display_mode') == 'PLAN' ) {
|
||||
me.symbols.rotateComp.setRotation(-userTrkMag*D2R);
|
||||
if(me.in_mode('toggle_display_mode', ['MAP'])) {
|
||||
me.symbols.rotateComp.setRotation(-userTrk*D2R);
|
||||
me.symbols.rotateComp2.setRotation(-userTrk*D2R);
|
||||
me.symbols.trkInd.setRotation(0);
|
||||
me.symbols.curHdgPtr.setRotation(userHdgMag*D2R);
|
||||
me.map._node.getNode("hdg",1).setDoubleValue(userTrkMag);
|
||||
me.symbols.compass.setRotation(-userTrkMag*D2R);
|
||||
me.symbols.curHdgPtr.setRotation(userHdg*D2R);
|
||||
me.symbols.curHdgPtr2.setRotation(userHdg*D2R);
|
||||
me.map._node.getNode("hdg",1).setDoubleValue(userTrk);
|
||||
me.symbols.compass.setRotation(-userTrk*D2R);
|
||||
me.symbols.compassApp.setRotation(-userTrk*D2R);
|
||||
me.symbols.hdgTrk.setText("TRK");
|
||||
me.symbols.truMag.setText("MAG");
|
||||
}
|
||||
if(me.get_switch('toggle_display_mode') == 'APP' or me.get_switch('toggle_display_mode') == 'VOR' ) {
|
||||
me.symbols.rotateComp.setRotation(-userHdgMag*D2R);
|
||||
me.symbols.trkInd.setRotation((userTrkMag-userHdgMag)*D2R);
|
||||
me.symbols.curHdgPtr.setRotation(userHdgMag*D2R);
|
||||
me.map._node.getNode("hdg",1).setDoubleValue(userHdgMag);
|
||||
me.symbols.compass.setRotation(-userHdgMag*D2R);
|
||||
if(me.in_mode('toggle_display_mode', ['APP','VOR'])) {
|
||||
me.symbols.rotateComp.setRotation(-userHdg*D2R);
|
||||
me.symbols.rotateComp2.setRotation(-userHdg*D2R);
|
||||
me.symbols.trkInd.setRotation((userTrk-userHdg)*D2R);
|
||||
me.symbols.curHdgPtr.setRotation(userHdg*D2R);
|
||||
me.symbols.curHdgPtr2.setRotation(userHdg*D2R);
|
||||
me.map._node.getNode("hdg",1).setDoubleValue(userHdg);
|
||||
me.symbols.compass.setRotation(-userHdg*D2R);
|
||||
me.symbols.compassApp.setRotation(-userHdg*D2R);
|
||||
me.symbols.hdgTrk.setText("HDG");
|
||||
me.symbols.truMag.setText("MAG");
|
||||
}
|
||||
if(me.get_switch('toggle_centered')) {
|
||||
if (me.in_mode('toggle_display_mode', ['APP','VOR'])) {
|
||||
me.symbols.vorCrsPtr2.show();
|
||||
me.symbols.compassApp.show();
|
||||
if(getprop("instrumentation/nav/in-range")) {
|
||||
var deflection = getprop("instrumentation/nav/heading-needle-deflection-norm");
|
||||
me.symbols.locPtr.show();
|
||||
me.symbols.locPtr.setTranslation(deflection*150,0);
|
||||
if(abs(deflection < 0.99))
|
||||
me.symbols.locPtr.setColorFill(1,0,1,1);
|
||||
else
|
||||
me.symbols.locPtr.setColorFill(1,0,1,0);
|
||||
} else {
|
||||
me.symbols.locPtr.hide();
|
||||
}
|
||||
me.symbols.vorCrsPtr2.setRotation((getprop("instrumentation/nav/radials/selected-deg")-userHdg)*D2R);
|
||||
me.symbols.hdgGroup.setTranslation(0,100);
|
||||
} else {
|
||||
me.symbols.vorCrsPtr2.hide();
|
||||
me.symbols.hdgGroup.setTranslation(0,100*me.in_mode('toggle_display_mode', ['MAP']));
|
||||
me.symbols.compassApp.setVisible(me.in_mode('toggle_display_mode', ['MAP']));
|
||||
}
|
||||
} else {
|
||||
me.symbols.vorCrsPtr2.hide();
|
||||
me.symbols.hdgGroup.setTranslation(0,0);
|
||||
me.symbols.compassApp.hide();
|
||||
}
|
||||
|
||||
if (abs(getprop("velocities/vertical-speed-fps")) > 10) {
|
||||
var altRangeNm = (getprop("autopilot/settings/target-altitude-ft")-
|
||||
getprop("instrumentation/altimeter/indicated-altitude-ft"))/getprop("velocities/vertical-speed-fps")*
|
||||
getprop("/velocities/groundspeed-kt")*KT2MPS*M2NM;
|
||||
|
||||
if(altRangeNm > 1) {
|
||||
var altRangePx = (350/me.rangeNm())*altRangeNm;
|
||||
if (altRangePx > 700)
|
||||
altRangePx = 700;
|
||||
me.symbols.altArc.setTranslation(0,-altRangePx);
|
||||
} # altRangeNm > 1
|
||||
me.symbols.altArc.show();
|
||||
if ((me.get_switch('toggle_centered') and !me.in_mode('toggle_display_mode', ['PLAN'])) or me.in_mode('toggle_display_mode', ['PLAN'])) {
|
||||
me.symbols.compass.hide();
|
||||
} else {
|
||||
me.symbols.compass.show();
|
||||
}
|
||||
|
||||
var staPtrVis = !me.in_mode('toggle_display_mode', ['APP','PLAN']);
|
||||
if (!me.get_switch('toggle_centered') and me.in_mode('toggle_display_mode', ['APP','MAP','VOR'])) {
|
||||
me.symbols.trkInd.show();
|
||||
me.symbols.staFromL.setVisible(staPtrVis);
|
||||
me.symbols.staFromL2.hide();
|
||||
me.symbols.staFromR.setVisible(staPtrVis);
|
||||
me.symbols.staFromR2.hide();
|
||||
me.symbols.staToL.setVisible(staPtrVis);
|
||||
me.symbols.staToL2.hide();
|
||||
me.symbols.staToR.setVisible(staPtrVis);
|
||||
me.symbols.staToR2.hide();
|
||||
me.symbols.rotateComp.setVisible(staPtrVis);
|
||||
me.symbols.rotateComp2.hide();
|
||||
} else {
|
||||
me.symbols.trkInd.hide();
|
||||
me.symbols.staFromL.hide();
|
||||
me.symbols.staFromL2.setVisible(staPtrVis);
|
||||
me.symbols.staFromR.hide();
|
||||
me.symbols.staFromR2.setVisible(staPtrVis);
|
||||
me.symbols.staToL.hide();
|
||||
me.symbols.staToL2.setVisible(staPtrVis);
|
||||
me.symbols.staToR.hide();
|
||||
me.symbols.staToR2.setVisible(staPtrVis);
|
||||
me.symbols.rotateComp.hide();
|
||||
me.symbols.rotateComp2.setVisible(staPtrVis);
|
||||
}
|
||||
me.symbols.hdgGroup.setVisible(!me.in_mode('toggle_display_mode', ['PLAN']));
|
||||
me.symbols.northUp.setVisible(me.in_mode('toggle_display_mode', ['PLAN']));
|
||||
me.symbols.aplSymMap.setVisible(me.in_mode('toggle_display_mode', ['APP','MAP','VOR']) and !me.get_switch('toggle_centered'));
|
||||
me.symbols.aplSymMapCtr.setVisible(me.in_mode('toggle_display_mode', ['MAP']) and me.get_switch('toggle_centered'));
|
||||
me.symbols.aplSymVor.setVisible(me.in_mode('toggle_display_mode', ['APP','VOR']) and me.get_switch('toggle_centered'));
|
||||
me.symbols.planArcs.setVisible(me.in_mode('toggle_display_mode', ['PLAN']));
|
||||
|
||||
if (abs(userVSpd) > 5) {
|
||||
var altDiff = getprop("autopilot/settings/target-altitude-ft")-getprop("instrumentation/altimeter/indicated-altitude-ft");
|
||||
if (abs(altDiff) > 50 and altDiff/userVSpd > 0) {
|
||||
var altRangeNm = altDiff/userVSpd*userSpd*KT2MPS*M2NM;
|
||||
if(altRangeNm > 1) {
|
||||
var altRangePx = (350/me.rangeNm())*altRangeNm;
|
||||
if (altRangePx > 700)
|
||||
altRangePx = 700;
|
||||
me.symbols.altArc.setTranslation(0,-altRangePx);
|
||||
}
|
||||
me.symbols.altArc.show();
|
||||
} else
|
||||
me.symbols.altArc.hide();
|
||||
} else {
|
||||
me.symbols.altArc.hide();
|
||||
}# fps > 10
|
||||
}
|
||||
|
||||
## these would require additional arguments to be moved to an external config hash currently
|
||||
|
||||
me.symbols.selHdg.setRotation(getprop("autopilot/settings/true-heading-deg")*D2R);
|
||||
if (var nav0hdg=getprop("instrumentation/nav/heading-deg") != nil)
|
||||
me.symbols.selHdg2.setRotation(getprop("autopilot/settings/true-heading-deg")*D2R);
|
||||
if (var nav0hdg=getprop("instrumentation/nav/heading-deg") != nil) {
|
||||
me.symbols.staFromL.setRotation((nav0hdg-userHdgMag+180)*D2R);
|
||||
if (var nav0hdg=getprop("instrumentation/nav/heading-deg") != nil)
|
||||
me.symbols.staFromL2.setRotation((nav0hdg-userHdgMag+180)*D2R);
|
||||
}
|
||||
if (var nav0hdg=getprop("instrumentation/nav/heading-deg") != nil) {
|
||||
me.symbols.staToL.setRotation((nav0hdg-userHdgMag)*D2R);
|
||||
if (var nav1hdg=getprop("instrumentation/nav[1]/heading-deg") != nil)
|
||||
me.symbols.staToL2.setRotation((nav0hdg-userHdgMag)*D2R);
|
||||
}
|
||||
if (var nav1hdg=getprop("instrumentation/nav[1]/heading-deg") != nil) {
|
||||
me.symbols.staFromR.setRotation((nav1hdg-userHdgMag+180)*D2R);
|
||||
if (var nav1hdg=getprop("instrumentation/nav[1]/heading-deg") != nil)
|
||||
me.symbols.staFromR2.setRotation((nav1hdg-userHdgMag+180)*D2R);
|
||||
}
|
||||
if (var nav1hdg=getprop("instrumentation/nav[1]/heading-deg") != nil) {
|
||||
me.symbols.staToR.setRotation((nav1hdg-userHdgMag)*D2R);
|
||||
|
||||
|
||||
me.symbols.staToR2.setRotation((nav1hdg-userHdgMag)*D2R);
|
||||
}
|
||||
|
||||
## 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
|
||||
|
@ -690,13 +821,11 @@ var NavDisplay = {
|
|||
|
||||
## 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') );
|
||||
me.symbols['status.wpt'].setVisible( me.get_switch('toggle_waypoints'));
|
||||
me.symbols['status.arpt'].setVisible( me.get_switch('toggle_airports'));
|
||||
me.symbols['status.sta'].setVisible( me.get_switch('toggle_stations') );
|
||||
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']));
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -50,14 +50,14 @@ var draw_route = func (group, theroute, controller=nil, lod=0)
|
|||
append(coords,"N"~leg.path()[0].lat);
|
||||
append(coords,"E"~leg.path()[0].lon);
|
||||
append(cmds,2);
|
||||
canvas.drawwp(group, leg.path()[0].lat,leg.path()[0].lon,fp.getWP(0).wp_name,i, wp);
|
||||
canvas.drawwp(group, leg.path()[0].lat, leg.path()[0].lon, fp.getWP(0).alt_cstr, fp.getWP(0).wp_name, i, wp);
|
||||
i+=1;
|
||||
}
|
||||
var leg = fp.getWP(i);
|
||||
append(coords,"N"~leg.path()[1].lat);
|
||||
append(coords,"E"~leg.path()[1].lon);
|
||||
append(cmds,4);
|
||||
canvas.drawwp(group, leg.path()[1].lat,leg.path()[1].lon,leg.wp_name,i, wp);
|
||||
canvas.drawwp(group, leg.path()[1].lat, leg.path()[1].lon, leg.alt_cstr, leg.wp_name, i, wp);
|
||||
}
|
||||
|
||||
# Update route coordinates
|
||||
|
|
|
@ -8,31 +8,28 @@ MPTrafficModel.init = func {
|
|||
myPosition.set_latlon( myPositionVec[0], myPositionVec[1]);
|
||||
var max_dist_nm = me._controller['query_range']();
|
||||
|
||||
##
|
||||
# uncomment this for showing MP traffic
|
||||
# var traffic_type = "multiplayer";
|
||||
# and use this for development purposes:
|
||||
var traffic_type = "aircraft";
|
||||
|
||||
#if (traffic_type == "aircraft")
|
||||
# print("INFO: traffic.model is still showing AI traffic instead of MP traffic!");
|
||||
|
||||
me._view.reset(); # hides: removeAllChildren()
|
||||
var traffic = props.globals.initNode("/ai/models/").getChildren( traffic_type );
|
||||
#print("Total traffic:", size(traffic));
|
||||
|
||||
# AI traffic
|
||||
var traffic = props.globals.initNode("/ai/models/").getChildren( "aircraft" );
|
||||
foreach(var t; traffic) {
|
||||
pos.set_latlon( t.getNode("position/latitude-deg").getValue(),
|
||||
t.getNode("position/longitude-deg").getValue()
|
||||
);
|
||||
|
||||
if (pos.distance_to( myPosition ) <= max_dist_nm*NM2M ) {
|
||||
#print("Pushing: ", t.getNode("callsign").getValue() );
|
||||
if (pos.distance_to( myPosition ) <= max_dist_nm*NM2M )
|
||||
me.push(t);
|
||||
}
|
||||
# Multiplayer traffic
|
||||
var traffic = props.globals.initNode("/ai/models/").getChildren( "multiplayer" );
|
||||
foreach(var t; traffic) {
|
||||
pos.set_latlon( t.getNode("position/latitude-deg").getValue(),
|
||||
t.getNode("position/longitude-deg").getValue()
|
||||
);
|
||||
|
||||
if (pos.distance_to( myPosition ) <= max_dist_nm*NM2M )
|
||||
me.push(t);
|
||||
}
|
||||
}
|
||||
#print("traffic.model: Query range:", max_dist_nm, " Items:", me.hasData() );
|
||||
|
||||
|
||||
|
||||
me.notifyView();
|
||||
|
||||
|
@ -40,5 +37,4 @@ MPTrafficModel.init = func {
|
|||
# and the interval needs to be configurable via the controller
|
||||
# so better use maketimer() here
|
||||
settimer(func me.init(), 2);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
# Draw a waypoint symbol and waypoint name (Gijs' 744 ND.nas code)
|
||||
|
||||
#
|
||||
var drawwp = func (group, lat, lon, name, i, wp) {
|
||||
var drawwp = func (group, lat, lon, alt, name, i, wp) {
|
||||
var wp_group = group.createChild("group","wp");
|
||||
wp[i] = wp_group.createChild("path", "wp-" ~ i)
|
||||
.setStrokeLineWidth(3)
|
||||
|
@ -22,13 +22,17 @@ var drawwp = func (group, lat, lon, name, i, wp) {
|
|||
#
|
||||
# text_wp[i] = wp_group.createChild("text", "wp-text-" ~ i)
|
||||
#
|
||||
if (alt == 0)
|
||||
alt = "";
|
||||
else
|
||||
alt = "\n"~alt;
|
||||
var text_wps = wp_group.createChild("text", "wp-text-" ~ i)
|
||||
.setDrawMode( canvas.Text.TEXT )
|
||||
.setText(name)
|
||||
.setText(name~alt)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.setFontSize(28)
|
||||
.setTranslation(25,35)
|
||||
.setColor(1,0,1);
|
||||
.setColor(1,1,1);
|
||||
wp_group.setGeoPosition(lat, lon)
|
||||
.set("z-index",4);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue