1
0
Fork 0

Direct To (DTO) function for both MFD and PFD.

This commit is contained in:
Stuart Buchanan 2018-03-20 20:24:44 +00:00
parent 054da4e691
commit 779ffe8d78
10 changed files with 261 additions and 69 deletions

View file

@ -68,6 +68,14 @@
<g
id="DirectToGroup"
inkscape:label="#g9755">
<rect
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4252"
width="315"
height="325"
x="705"
y="278"
inkscape:label="#rect59059" />
<g
id="DirectToMap"
inkscape:label="#g60873">

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -0,0 +1,146 @@
# Copyright 2018 Stuart Buchanan
# This file is part of FlightGear.
#
# Foobar is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# FlightGear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FlightGear. If not, see <http://www.gnu.org/licenses/>.
#
# DirectTo page
#
# Technically this is supposed to be an overlay page, sitting on top of
# whatever page the user was on already. However, to simplify implementation,
# we will assume that the user was on the Map page, and simply display the
# NavigationMap page underneath.
var DirectTo =
{
SHORTCUTS : [ "FPL", "NRST", "RECENT", "USER", "AIRWAY" ],
new : func (mfd, myCanvas, device, svg)
{
var obj = {
parents : [
DirectTo,
MFDPage.new(mfd, myCanvas, device, svg, "DirectTo", "DIRECT TO")
],
symbols : {},
};
obj.crsrIdx = 0;
# Dynamic text elements in the SVG file. In the SVG these have an "DirectTo" prefix.
textelements = [
"Name",
"City",
"Region",
"LocationBRG",
"LocationDIS",
];
obj.addTextElements(textelements);
obj._SVGGroup.setInt("z-index", 9);
# Data Entry information. Keyed from the name of the element, which must
# be one of the textelements above. Each data element maps to a set of
# text elements in the SVG of the form [PageName][TextElement]{0...n}, each
# representing a single character for data entry.
#
# .size is the number of characters of data entry
# .chars is the set of characters, used to scroll through using the small
# FMS knob.
obj.IDEntry = PFD.DataEntryElement.new(obj.pageName, svg, "ID", "", 4, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
obj.VNVAltEntry = PFD.DataEntryElement.new(obj.pageName, svg, "VNVAlt", "", 5, "0123456789");
obj.VNVOffsetEntry = PFD.DataEntryElement.new(obj.pageName, svg, "VNVOffset", "", 2, "0123456789");
obj.CourseEntry = PFD.DataEntryElement.new(obj.pageName, svg, "Course", "", 3, "0123456789");
obj.Activate = PFD.TextElement.new(obj.pageName, svg, "Activate", "ACTIVATE?");
# The Shortcut window. This allows the user to scroll through a set of lists
# of waypoints.
obj.WaypointSubmenuGroup = obj._SVGGroup.getElementById("DirectToWaypointSubmenuGroup");
assert(obj.WaypointSubmenuGroup != nil, "Unable to find DirectToWaypointSubmenuGroup");
obj.WaypointSubmenuGroup.setVisible(0);
obj.WaypointSubmenuSelect = PFD.ScrollElement.new(obj.pageName, svg, "WaypointSubmenuSelect", DirectTo.SHORTCUTS);
obj.WaypointSubmenuScroll = PFD.GroupElement.new(obj.pageName, svg, [ "WaypointSubmenuScroll" ] , 4, "WaypointSubmenuScroll", 0, "WaypointSubmenuScrollTrough" , "WaypointSubmenuScrollThumb", 60);
# The Airport Chart
if (obj.elementExists("Map")) {
obj.DirectToChart = fg1000.NavMap.new(obj, obj.getElement("Map"), [860,440], "rect(-160px, 160px, 160px, -160px)", 0, 2, 1);
}
obj.setController(fg1000.DirectToController.new(obj, svg));
return obj;
},
displayDestination : func(destination) {
#me.IDEntry.clearElement();
if (destination != nil) {
# Display a given location
if (me.DirectToChart) {
me.DirectToChart.setVisible(1);
me.DirectToChart.getController().setPosition(destination.lat,destination.lon);
}
me.setTextElement("Name", string.uc(destination.name));
me.setTextElement("City", "CITY");
me.setTextElement("Region", "REGION");
me.setTextElement("LocationBRG", "" ~ sprintf("%03d°", destination.course));
me.setTextElement("LocationDIS", sprintf("%d", destination.range_nm) ~ "nm");
me.IDEntry.setValue(destination.id);
me.VNVAltEntry.setValue("00000");
me.VNVOffsetEntry.setValue("00");
me.CourseEntry.setValue("" ~ sprintf("%03d°", destination.course));
} else {
if (me.DirectToChart) me.DirectToChart.setVisible(0);
me.setTextElement("Name", "");
me.setTextElement("City", "");
me.setTextElement("Region", "");
me.setTextElement("LocationBRG", "_");
me.setTextElement("LocationDIS", "_");
me.IDEntry.setValue("____");
me.VNVAltEntry.setValue("00000");
me.VNVOffsetEntry.setValue("00");
me.CourseEntry.setValue(0);
}
},
offdisplay : func() {
me._group.setVisible(0);
me.getController().offdisplay();
me.mfd.NavigationMap.offdisplay(0);
},
ondisplay : func() {
me._group.setVisible(1);
# Display a false title, as underneath we're showing the navigation map.
me.mfd.setPageTitle("MAP - NAVIGATION MAP");
me.getElement("Map").setVisible(1);
me.getElement("Map-bg").setVisible(1);
if (me.DirectToChart) me.DirectToChart.setVisible(1);
me.getController().ondisplay();
# The DirectTo pages displays over the NavigationMap. This is a hack
# as the page should just magically sit ontop of whatever page the user was
# on. However, we also need to disable the NavMap's own controller so there's
# no confusion.
me.mfd.NavigationMap.ondisplay(0);
},
# When the Direct To display is enabled, nothing is displayed on the softkeys.
topMenu : func(device, pg, menuitem) {
pg.clearMenu();
pg.resetMenuColors();
device.updateMenus();
},
};

View file

@ -54,7 +54,7 @@ var MFDPages = [
"NearestUserWPT",
"NearestFrequencies",
"NearestAirspaces",
"DirectTo", # display at the top of the stack
"DirectTo",
"Surround",
];
@ -111,6 +111,12 @@ var MFDDisplay =
obj._MFDDevice = canvas.PFD_Device.new(obj._svg, 12, "SoftKey", myCanvas, "MFD");
obj._MFDDevice.device_id = device_id;
# DirectTo "Page" loaded first so that it receives any Emesary notifications
# _before_ the actual page.
obj._DTO = fg1000.DirectTo.new(obj, myCanvas, obj._MFDDevice, obj._svg);
obj._DTO.getController().RegisterWithEmesary();
obj._MFDDevice.RegisterWithEmesary();
# Surround dynamic elements
@ -133,7 +139,7 @@ var MFDDisplay =
# Now load the other pages normally;
foreach (var page; MFDPages) {
if ((page != "NavigationMap") and (page != "EIS")) {
if ((page != "NavigationMap") and (page != "EIS") and (page != "DirectTo")) {
#var code = "obj.Surround.addPage(\"" ~ page ~ "\", fg1000." ~ page ~ ".new(obj, myCanvas, obj._MFDDevice, obj._svg));";
var code = "obj.addPage(\"" ~ page ~ "\", fg1000." ~ page ~ ".new(obj, myCanvas, obj._MFDDevice, obj._svg));";
var addPageFn = compile(code);

View file

@ -74,6 +74,11 @@ addElement : func(e) {
}
},
elementExists : func(e) {
var element = me._SVGGroup.getElementById(me.pageName ~ e);
return (element != nil);
},
addElements : func(elements) {
foreach (var e; elements) {
me.addElement(e);

View file

@ -31,6 +31,9 @@ new : func (page)
obj._transmitter = emesary.GlobalTransmitter;
obj._registered = 0;
# DirectTo controls
obj._directTo = 0;
return obj;
},
@ -68,12 +71,7 @@ handleComVol : func (value) { return me.page.mfd.SurroundController.handle
handleComVolToggle : func (value) { return me.page.mfd.SurroundController.handleComVolToggle(value); },
# DTO button brings up the DirectTo Page.
handleDTO : func (value) {
var dtopage = me._page.getMFD().getPage("DirectTo");
assert(dtopage != nil, "Unable to find the DirectTo page.");
me._page.getDevice().selectPage(dtopage);
return emesary.Transmitter.ReceiptStatus_Finished;
},
handleDTO : func (value) { return emesary.Transmitter.ReceiptStatus_NotProcessed; },
handleFPL : func (value) { return emesary.Transmitter.ReceiptStatus_NotProcessed; },
handleClear : func (value) { return emesary.Transmitter.ReceiptStatus_NotProcessed; },

View file

@ -14,12 +14,9 @@
# You should have received a copy of the GNU General Public License
# along with FlightGear. If not, see <http://www.gnu.org/licenses/>.
#
# DirectTo page
#
# Technically this is supposed to be an overlay page, sitting on top of
# whatever page the user was on already. However, to simplify implementation,
# we will assume that the user was on the Map page, and simply display the
# NavigationMap page underneath.
# DirectTo page. This is an overlay, sitting on whatever page the user
# is on already. Hence it is not called in the normal way, but instead
# explicitly displays/hides itself when the DTO button is pressed.
var DirectTo =
{
@ -73,22 +70,27 @@ var DirectTo =
obj.WaypointSubmenuScroll = PFD.GroupElement.new(obj.pageName, svg, [ "WaypointSubmenuScroll" ] , 4, "WaypointSubmenuScroll", 0, "WaypointSubmenuScrollTrough" , "WaypointSubmenuScrollThumb", 60);
# The Airport Chart
obj.DirectToChart = fg1000.NavMap.new(obj, obj.getElement("Map"), [860,440], "rect(-160px, 160px, 160px, -160px)", 0, 2, 1);
if (obj.elementExists("Map")) {
print("DirectoTo Map exists");
obj.DirectToChart = fg1000.NavMap.new(obj, obj.getElement("Map"), [860,440], "rect(-160px, 160px, 160px, -160px)", 0, 2, 1);
} else {
obj.DirectToChart = nil;
}
obj.setController(fg1000.DirectToController.new(obj, svg));
return obj;
},
displayDestination : func(destination) {
#me.IDEntry.clearElement();
if (destination != nil) {
# Display a given location
me.DirectToChart.setVisible(1);
me.DirectToChart.getController().setPosition(destination.lat,destination.lon);
if (me.DirectToChart != nil) {
me.DirectToChart.setVisible(1);
me.DirectToChart.getController().setPosition(destination.lat,destination.lon);
}
me.setTextElement("Name", string.uc(destination.name));
me.setTextElement("City", "CITY");
me.setTextElement("Region", "REGION");
me.setTextElement("City", "");
me.setTextElement("Region", "");
me.setTextElement("LocationBRG", "" ~ sprintf("%03d°", destination.course));
me.setTextElement("LocationDIS", sprintf("%d", destination.range_nm) ~ "nm");
@ -97,14 +99,14 @@ var DirectTo =
me.VNVOffsetEntry.setValue("00");
me.CourseEntry.setValue("" ~ sprintf("%03d°", destination.course));
} else {
me.DirectToChart.setVisible(1);
if (me.DirectToChart != nil) me.DirectToChart.setVisible(0);
me.setTextElement("Name", "");
me.setTextElement("City", "");
me.setTextElement("Region", "");
me.setTextElement("LocationBRG", "_");
me.setTextElement("LocationDIS", "_");
me.IDEntry.setValue("____");
me.IDEntry.setValue("####");
me.VNVAltEntry.setValue("00000");
me.VNVOffsetEntry.setValue("00");
me.CourseEntry.setValue(0);
@ -113,30 +115,12 @@ var DirectTo =
offdisplay : func() {
me._group.setVisible(0);
me.getElement("Group").setVisible(0);
me.getController().offdisplay();
me.mfd.NavigationMap.offdisplay(0);
},
ondisplay : func() {
me._group.setVisible(1);
# Display a false title, as underneath we're showing the navigation map.
me.mfd.setPageTitle("MAP - NAVIGATION MAP");
me.getElement("Map").setVisible(1);
me.getElement("Map-bg").setVisible(1);
me.DirectToChart.setVisible(1);
me.getElement("Group").setVisible(1);
me.getController().ondisplay();
# The DirectTo pages displays over the NavigationMap. This is a hack
# as the page should just magically sit ontop of whatever page the user was
# on. However, we also need to disable the NavMap's own controller so there's
# no confusion.
me.mfd.NavigationMap.ondisplay(0);
},
# When the Direct To display is enabled, nothing is displayed on the softkeys.
topMenu : func(device, pg, menuitem) {
pg.clearMenu();
pg.resetMenuColors();
device.updateMenus();
},
};

View file

@ -22,6 +22,7 @@ var DirectToController =
var obj = { parents : [ DirectToController, MFDPageController.new(page)] };
obj.id = "";
obj.page = page;
obj.dto_displayed = 0;
obj._cursorElements = [
obj.page.IDEntry,
@ -59,6 +60,8 @@ var DirectToController =
},
handleCRSR : func() {
if (! me.dto_displayed) return emesary.Transmitter.ReceiptStatus_NotProcessed;
# No effect, but shouldn't be passed to underlying page?
return emesary.Transmitter.ReceiptStatus_Finished;
},
@ -158,7 +161,31 @@ var DirectToController =
}
},
handleDTO : func(value) {
if (me.dto_displayed == 0) {
# Display the DTO page.
me.page.ondisplay();
me.dto_displayed = 1;
} else {
# Hide the DTO page.
me.page.offdisplay();
me.dto_displayed = 0;
}
return emesary.Transmitter.ReceiptStatus_Finished;
},
handleRange : func(val)
{
if (me.page.DirectToChart != nil) {
return me.page.DirectToChart.handleRange(val);
} else {
return emesary.Transmitter.ReceiptStatus_NotProcessed;
}
},
handleFMSInner : func(value) {
if (! me.dto_displayed) return emesary.Transmitter.ReceiptStatus_NotProcessed;
if (me._waypointSubmenuVisible) {
# We're in the Waypoint Submenu, in which case the inner FMS knob
@ -184,7 +211,10 @@ var DirectToController =
return emesary.Transmitter.ReceiptStatus_Finished;
},
handleFMSOuter : func(value) {
if (! me.dto_displayed) return emesary.Transmitter.ReceiptStatus_NotProcessed;
if (me._waypointSubmenuVisible) {
# We're in the Waypoint Submenu, in which case the outer FMS knob
# selects between the different waypoints in the Waypoint Submenu.
@ -200,7 +230,10 @@ var DirectToController =
return emesary.Transmitter.ReceiptStatus_Finished;
},
handleEnter : func(value) {
if (! me.dto_displayed) return emesary.Transmitter.ReceiptStatus_NotProcessed;
if (me._waypointSubmenuVisible) {
# If we're in the Waypoint Submenu, then take whatever is highlighted
# in the scroll list, load it and hide the Waypoint submenu
@ -221,9 +254,9 @@ var DirectToController =
params.offset_nm = me.page.VNVOffsetEntry.getValue();
me.setNavData("SetDirectTo", params);
var mappage = me._page.getMFD().getPage("NavigationMap");
assert(mappage != nil, "Unable to find NavigationMap page");
me._page.getDevice().selectPage(mappage);
me.page.offdisplay();
me.dto_displayed = 0;
return emesary.Transmitter.ReceiptStatus_Finished;
}
@ -250,7 +283,10 @@ var DirectToController =
return emesary.Transmitter.ReceiptStatus_Finished;
},
handleClear : func(value) {
if (! me.dto_displayed) return emesary.Transmitter.ReceiptStatus_NotProcessed;
if (me._waypointSubmenuVisible) {
# If we're in the Waypoint Submenu, then this clears it.
me.page.WaypointSubmenuGroup.setVisible(0);
@ -258,18 +294,17 @@ var DirectToController =
} else if (me._cursorElements[me._selectedElement].isInEdit()) {
me._cursorElements[me._selectedElement].clearElement();
} else {
# Cancel the entire Direct To page, and go back to the Navigation Map.
var mappage = me._page.getMFD().getPage("NavigationMap");
assert(mappage != nil, "Unable to find NavigationMap page");
me._page.getDevice().selectPage(mappage);
# Cancel the entire Direct To page.
me.page.offdisplay();
me.dto_displayed = 0;
}
return emesary.Transmitter.ReceiptStatus_Finished;
},
# Reset controller if required when the page is displayed or hidden
# Note that we explicitly do NOT RegisterWithEmesary/DeRegisterWithEmesary!
# This page should RegisterWithEmesary at start of day instead.
ondisplay : func() {
me.RegisterWithEmesary();
# Find the current DTO target, which may have been set by the page the
# use was on.
var id = me.getNavData("CurrentDTO");
@ -277,21 +312,14 @@ var DirectToController =
me.loadDestination(id);
me.setCursorElement(0);
},
offdisplay : func() {
me.DeRegisterWithEmesary();
},
loadDestination : func(id) {
var d = {
id: id,
name: "",
lat: 0,
lon: 0,
course : 0,
range_nm : 0,
};
if ((id != nil) and size(id) > 1) {
if ((id == nil) or (id == "")) {
me.page.displayDestination(nil);
} else {
# Use Emesary to get the destination
var notification = notifications.PFDEventNotification.new(
"MFD",
@ -308,11 +336,11 @@ var DirectToController =
# Some elements don't have names
var name = destination.id;
if (defined("destination.name")) name = destination.name;
if (!defined("destination.name")) name = destination.name;
var point = { lat: destination.lat, lon: destination.lon };
var (course, dist) = courseAndDistance(point);
var d = {
id: destination.id,
name: name,
@ -321,9 +349,9 @@ var DirectToController =
course : course,
range_nm : dist,
};
me.page.displayDestination(d);
}
}
me.page.displayDestination(d);
},
};

View file

@ -86,7 +86,7 @@ var PFDInstrumentsController =
me._crsrToggle = (! me._crsrToggle);
if (me._crsrToggle) {
} else {
me.page.hideCRSR();
#me.page.hideCRSR();
}
return emesary.Transmitter.ReceiptStatus_Finished;
},

View file

@ -231,6 +231,7 @@ var NavMap = {
{
var incr_or_decr = (val > 0) ? 1 : -1;
me.setZoom(me.current_zoom + incr_or_decr);
return emesary.Transmitter.ReceiptStatus_Finished;
},
getMap : func() {

View file

@ -36,6 +36,9 @@ var PFDDisplay =
io.load_nasal(nasal_dir ~ "MFDPages/PFDInstruments/PFDInstrumentsOptions.nas", "fg1000");
io.load_nasal(nasal_dir ~ "MFDPages/PFDInstruments/PFDInstrumentsController.nas", "fg1000");
io.load_nasal(nasal_dir ~ "MFDPages/DirectTo/DirectTo.nas", "fg1000");
io.load_nasal(nasal_dir ~ "MFDPages/DirectTo/DirectToController.nas", "fg1000");
obj.ConfigStore = obj._fg1000.getConfigStore();
obj._svg = myCanvas.createGroup("softkeys");
@ -53,16 +56,29 @@ var PFDDisplay =
EIS_SVG,
{'font-mapper': fontmapper});
canvas.parsesvg(obj._svg,
'/Aircraft/Instruments-3d/FG1000/MFDPages/PFDInstruments.svg',
{'font-mapper': fontmapper});
canvas.parsesvg(obj._svg,
'/Aircraft/Instruments-3d/FG1000/MFDPages/DirectToPFD.svg',
{'font-mapper': fontmapper});
canvas.parsesvg(obj._svg,
'/Aircraft/Instruments-3d/FG1000/MFDPages/SurroundPFD.svg',
{'font-mapper': fontmapper});
obj._MFDDevice = canvas.PFD_Device.new(obj._svg, 12, "SoftKey", myCanvas, "PFD");
obj._MFDDevice.device_id = device_id;
# DirectTo "Page" loaded first so that it receives any Emesary notifications
# _before_ the actual page.
obj._DTO = fg1000.DirectTo.new(obj, myCanvas, obj._MFDDevice, obj._svg);
obj._DTO.getController().RegisterWithEmesary();
obj._MFDDevice.RegisterWithEmesary();
# Surround dynamic elements