# The following is largely inspired from the Extra500 Avidyne Entegra 9 # https://gitlab.com/extra500/extra500.git # Many thanks to authors: Dirk Dittmann and Eric van den Berg var RouteItemClass = { new : func (canvasGroup, index) { var m = {parents:[RouteItemClass]}; m.index = index; m.group = canvasGroup.createChild('group', 'Waypoint-' ~ index).setVisible(0); m.can = { Waypoint : m.group.createChild('path','icon-' ~ index) .setStrokeLineWidth(3) .setScale(1) .setColor(1,1,1) .setColorFill(1,1,1) .moveTo(-20, 0) .lineTo(-5, 5) .lineTo(0, 20) .lineTo(5, 5) .lineTo(20, 0) .lineTo(5, -5) .lineTo(0, -20) .lineTo(-5, -5) .close(), Label : m.group.createChild('text', 'wptLabel-' ~ index) .setFont('LiberationFonts/LiberationMono-Bold.ttf') .setTranslation(25,-25) .setFontSize(20, 1) .setColor(1,1,1) .setColorFill(1,1,1), track : canvasGroup.createChild('path','track-' ~ index) .setStrokeLineWidth(3) .setScale(1) .setColor(1,1,1) .setVisible(1), }; return m; }, setVisible : func (v) { me.group.setVisible(v); me.can.track.setVisible(v); }, draw : func (wpt) { me.can.Label.setText(wpt[0].name); me.setColor(1,1,1); me.group.setGeoPosition(wpt[0].lat, wpt[0].lon); me.group.setVisible(1); }, drawTrack : func (wpt) { var cmds = []; var coords = []; var cmd = canvas.Path.VG_MOVE_TO; me.can.track.setVisible(1); foreach (var pt; wpt) { append(coords, 'N' ~ pt.lat); append(coords, 'E' ~ pt.lon); append(cmds, cmd); cmd = canvas.Path.VG_LINE_TO; } me.can.track.setDataGeo(cmds, coords); }, setColor : func (color) { me.can.Label.setColor(color).setColorFill(color); me.can.Waypoint.setColor(color).setColorFill(color); }, del : func { me.can.track.del(); me.group.del(); me = nil; }, }; var FMSIcon = { new : func (canvasGroup, text) { var m = {parents:[ FMSIcon ]}; m.group = canvasGroup.createChild('group', 'FMS-' ~ text).setVisible(0); m.can = { icon : m.group.createChild('path','FMS-icon' ~ text) .setStrokeLineWidth(3) .setScale(1) .setColor(0,1,0) .setColorFill(0,1,0) .moveTo(-15, 0) .lineTo(0, 15) .lineTo(15, 0) .lineTo(0, -15) .close(), label : m.group.createChild('text', 'FMS-label-' ~ text) .setFont('LiberationFonts/LiberationMono-Bold.ttf') .setTranslation(20,12) .setFontSize(32, 1) .setColor(0,1,0) .setColorFill(0,1,0) .setText(text), }; return m; }, setVisible : func (v) me.group.setVisible(v), setGeoPosition : func (lat, lon) me.group.setGeoPosition(lat, lon), }; var FMSIconRTA = { new : func (canvasGroup, text) { var m = {parents:[FMSIconRTA]}; m.group = canvasGroup.createChild('group', 'FMS-' ~ text).setVisible(0); m.can = { icon : m.group.createChild('path','FMS-icon' ~ text) .setStrokeLineWidth(3) .setScale(1) .setColor(0,1,0) .setColorFill(0,1,0) .moveTo(-15, 0) .lineTo(0, 15) .lineTo(15, 0) .lineTo(0, -15) .close(), label : m.group.createChild('text', 'FMS-label-' ~ text) .setFont('LiberationFonts/LiberationMono-Bold.ttf') .setTranslation(-80,12) .setFontSize(32, 1) .setColor(0,1,0) .setColorFill(0,1,0) .setText(text), }; return m; }, setVisible : func (v) me.group.setVisible(v), setGeoPosition : func (lat, lon) me.group.setGeoPosition(lat, lon), }; var MapRoute = { new : func (device, group) { var m = {parents:[ MapRoute ]}; m.item = []; m.itemIndex = 0; m.visibility = 0; m.device = device; m.group = group.createChild('map', 'route map') .setTranslation( m.device.role == 'MFD' ? (m.device.data.mapview[0] + m.device.data.mapclip.left)/2 : 120, m.device.role == 'MFD' ? 400 : 600) .setVisible(m.visibility); m.group.setRange(m.device.data['range-nm']/2); m.group._node .getNode('ref-lat', 1).setDoubleValue(data.lat); m.group._node .getNode('ref-lon', 1).setDoubleValue(data.lon); m.groupTrack = m.group.createChild('group', 'Track') .setVisible(1); m.groupOBS = m.group.createChild('group', 'OBS') .setVisible(0); m.groupFMS = m.group.createChild('group', 'FMS') .setVisible(1); m.can = { track : m.group.createChild('path', 'track') .setStrokeLineWidth(3) .setScale(1) .setColor(1,1,1), currentLeg : m.groupFMS.createChild('path', 'currentLeg') .setStrokeLineWidth(5) .setScale(1) .setColor(1,0,1), nextLeg : m.groupFMS.createChild('path', 'nextLeg') .setStrokeLineWidth(5) .setScale(1) .setStrokeDashArray([25,25]) .setColor(1,0,1), obsCourse : m.groupOBS.createChild('path', 'obsCourse') .setStrokeLineWidth(5) .setScale(1) .setColor(1,0,1), }; m.TOD = FMSIcon.new(m.groupFMS, 'TOD'); m.TOC = FMSIcon.new(m.groupFMS, 'TOC'); m.RTA = FMSIconRTA.new(m.groupFMS, 'RTA'); m.track = { cmds : [], coords: [], }; m.currentLeg = { cmds: [ canvas.Path.VG_MOVE_TO, canvas.Path.VG_LINE_TO ], coords: [0, 0, 0, 0], index : -1, }; m.nextLeg = { cmds: [ canvas.Path.VG_MOVE_TO, canvas.Path.VG_LINE_TO ], coords: [0, 0, 0, 0], index : -1, }; m.mapOptions = { orientation : 0, }; m.obsMode = 0; m.obsCourse = 0; m.obsWaypoint = RouteItemClass.new(m.groupOBS, 'obs_wp'); m.obsCourseData = { cmds: [ canvas.Path.VG_MOVE_TO, canvas.Path.VG_LINE_TO ], coords: [0, 0, 0, 0]}; m.flightPlan = []; m.currentWpIndex = getprop('/autopilot/route-manager/current-wp'); if (m.device.role == 'PFD') m.device.softkeys.colored.INSETROUTE = 1; if (m.device.role == 'MFD') m.device.softkeys.colored.MAPROUTE = 1; return m; }, off: func { me.setVisible(0); me.group.setVisible(0); me.group.removeAllChildren(); }, update: func { me.visibility != 0 or return; me.group.setRange(me.device.data['range-nm']/2); me.group._node.getNode('ref-lat', 1).setDoubleValue(data.lat); me.group._node.getNode('ref-lon', 1).setDoubleValue(data.lon); }, setVisible : func (v) { if (me.visibility != v) { me.visibility = v; me.group.setVisible(v); } }, updateOrientation : func (value) { me.mapOptions.orientation = value; me.can.obsCourse.setRotation((me.obsCourse - me.mapOptions.orientation) * D2R); }, onFlightPlanChange : func { for (var i = size(me.item) - 1; i >= 0; i -= 1) { me.item[i].del(); pop(me.item); } me.itemIndex = 0; me.flightPlan = []; var route = props.globals.getNode('/autopilot/route-manager/route'); var planSize = getprop('/autopilot/route-manager/route/num'); for (var i=0; i < planSize - 1; i+=1) { var wp0 = route.getNode('wp[' ~ i ~ ']'); var wp1 = route.getNode('wp[' ~ (i+1) ~ ']'); append(me.flightPlan, [ { lat : wp0.getNode('latitude-deg').getValue(), lon : wp0.getNode('longitude-deg').getValue(), name: wp0.getNode('id').getValue(), }, { lat : wp1.getNode('latitude-deg').getValue(), lon : wp1.getNode('longitude-deg').getValue(), name: wp1.getNode('id').getValue(), } ]); append(me.item, RouteItemClass.new(me.groupTrack, i)); } me.setVisible(me.device.map.visibility); me.drawWaypoints(); }, onCurrentWaypointChange : func (n) { me.currentWpIndex = n.getValue(); me.currentLeg.index = me.currentWpIndex - 1; me.nextLeg.index = me.currentWpIndex; if (me.currentWpIndex == 0) { n.setIntValue(1); me.currentWpIndex = 1; } me.drawLegs(); }, drawWaypoints : func { me.visibility != 0 or return; var cmd = canvas.Path.VG_MOVE_TO; for (var i=0; i < size(me.flightPlan); i+=1) { # me.item[me.itemIndex].draw(me.flightPlan[i]); me.item[me.itemIndex].drawTrack(me.flightPlan[i]); me.itemIndex +=1; } me.groupTrack.setVisible(me.visibility and (me.obsMode == 0)); }, drawLegs : func { me.visibility != 0 or return; if (me.currentLeg.index >= 0 and me.currentLeg.index < size(me.flightPlan)) { var cmd = canvas.Path.VG_MOVE_TO; me.currentLeg.coords = []; me.currentLeg.cmds = []; foreach (var pt; me.flightPlan[me.currentLeg.index]) { append(me.currentLeg.coords, 'N' ~ pt.lat); append(me.currentLeg.coords, 'E' ~ pt.lon); append(me.currentLeg.cmds, cmd); cmd = canvas.Path.VG_LINE_TO; } me.can.currentLeg.setDataGeo(me.currentLeg.cmds, me.currentLeg.coords); me.can.currentLeg.setVisible(1); } else me.can.currentLeg.setVisible(0); if (me.nextLeg.index >= 1 and me.nextLeg.index < size(me.flightPlan)) { var cmd = canvas.Path.VG_MOVE_TO; me.nextLeg.coords = []; me.nextLeg.cmds = []; foreach (var pt; me.flightPlan[me.nextLeg.index]) { append(me.nextLeg.coords,'N' ~ pt.lat); append(me.nextLeg.coords,'E' ~ pt.lon); append(me.nextLeg.cmds,cmd); cmd = canvas.Path.VG_LINE_TO; } me.can.nextLeg.setDataGeo(me.nextLeg.cmds, me.nextLeg.coords); me.can.nextLeg.setVisible(1); } else me.can.nextLeg.setVisible(0); }, # _onVisibilityChange : func { # me.group.setVisible(me.visibility and (me.obsMode == 0)); # me.groupTrack.setVisible(me.visibility and (me.obsMode == 0)); # me.groupFMS.setVisible(me.visibility and (me.obsMode == 0)); # me.groupOBS.setVisible(me.visibility and (me.obsMode == 1)); # me.TOD.setVisible(fms._dynamicPoint.TOD.visible and me.visibility); # me.TOC.setVisible(fms._dynamicPoint.TOC.visible and me.visibility); # me.RTA.setVisible(fms._dynamicPoint.RTA.visible and me.visibility); # }, # _onFplReadyChange : func (n) { # me.TOD.setVisible(fms._dynamicPoint.TOD.visible and me.visibility); # me.TOC.setVisible(fms._dynamicPoint.TOC.visible and me.visibility); # me.RTA.setVisible(fms._dynamicPoint.RTA.visible and me.visibility); # }, # _onFplUpdatedChange : func (n) { # if (fms._dynamicPoint.TOD.visible) # me.TOD.setGeoPosition(fms._dynamicPoint.TOD.position.lat, fms._dynamicPoint.TOD.position.lon); # if (fms._dynamicPoint.TOC.visible) # me.TOC.setGeoPosition(fms._dynamicPoint.TOC.position.lat, fms._dynamicPoint.TOC.position.lon); # if (fms._dynamicPoint.RTA.visible) # me.RTA.setGeoPosition(fms._dynamicPoint.RTA.position.lat, fms._dynamicPoint.RTA.position.lon); # # me.TOD.setVisible(fms._dynamicPoint.TOD.visible and me.visibility); # me.TOC.setVisible(fms._dynamicPoint.TOC.visible and me.visibility); # me.RTA.setVisible(fms._dynamicPoint.RTA.visible and me.visibility); # }, # _onObsModeChange : func (n) { # me.obsMode = n.getValue(); # # if (me.obsMode==1) { # var wp = { # wp_lat : getprop('/instrumentation/gps[0]/scratch/latitude-deg'), # wp_lon : getprop('/instrumentation/gps[0]/scratch/longitude-deg'), # wp_name : getprop('/instrumentation/gps[0]/scratch/ident'), # }; # var acLat = getprop('/position/latitude-deg'); # var acLon = getprop('/position/longitude-deg'); # # me.groupOBS.setGeoPosition(wp.wp_lat, wp.wp_lon); # # me.obsCourseData.coords = [ # 0, # 0, # 0, # 5000, # ]; # # me.obsWaypoint._can.Label.setText(wp.wp_name); # me.obsWaypoint.setColor(1,0,1); # me.obsWaypoint._group.setVisible(1); # # me.can.obsCourse.setData(me.obsCourseData.cmds,me.obsCourseData.coords); # } # # me.groupTrack.setVisible(me.visibility and (me.obsMode == 0)); # me.groupFMS.setVisible(me.visibility and (me.obsMode == 0)); # me.groupOBS.setVisible(me.visibility and (me.obsMode == 1)); # }, # _onObsCourseChange : func (n) { # me.obsCourse = n.getValue(); # me.can.obsCourse.setRotation((me.obsCourse - me.mapOptions.orientation) * global.CONST.DEG2RAD); # }, };