cbendele wrote in Sun Jul 27, 2014 11:00 pm:They have nice looking Airspace displays. Do we have some kind of airspace api in flightgear that will provide the information needed for "nearest airspace" pages and "close to airspace" popup warnings? Also, is there an airspace layer to the MapStructure?
not yet, but we're planning to add one sooner or later, some of the data we have already, it's just not exposed to Nasal yet - see:
viewtopic.php?f=6&t=21762&p=199446&hilit=#p199446viewtopic.php?f=75&t=23041 That will involve using cppbind to expose some existing data structures to Nasal:
http://wiki.flightgear.org/Nasal/CppBindhttp://wiki.flightgear.org/Canvas_MapStructure_Layers(loosely related) question: Are the fixes in the nav database classified in some way? Like, high altitude enroute, low altitude enroute and procedures (star and sid related)? The nearest intersections list is really cluttered with the approach/departure waypoints, and I don't think I should usually display them there. In the map, also, it would be nice to only display procedure related fixes during actual procedures (approachs or departures), and otherwise only display enroute fixes. I don't care about the high-altitude jet routes versus low altitude airways that much, but filtering out the procedure fixes would definitely be nice.
I think Gijs raised the same question a while, at least his ND code has some comments along those lines - so I don't think there's any classification in place currently, keep in mind that the navdb is not very recent at all. But we can also use NaviGraph data - so it should be possible to enrich the data accordingly and update the SQL db. It mainly depends how responsive core developers are - the navdb is being maintained by one of the most active core devs (Zakalawe).
But even absent any support there, the MapStructure/ND side of things could even be purely driven by an alternate data source without too much work:
Subject: 777 EFB: initial feedbackHooray wrote:Well, we've been talking about the lack of current navdata in FG recently. On the MapStructure side of things we really only need to encapsulate any NasalPositioned calls, to support arbitrary data - including even fetched (XML), or manually entered navaids/fixes. Such data could then be centrally served or based on NaviGraph. So we wouldn't have to touch any of the existing NavDB stuff to work around its limitations.
So I am thinking about moving all NasalPositioned queries in MapStructure into a "driver" hash, but maybe more in line with the aircraftpos.controller stuff that Philosopher developed, just specific to some kind of "NavaidSource".
That would allow us to easily work around such limitations, so that I-NEMO, Hyde, Gijs etc can easily use the latest data on their EFB/ND. The other motivation here is that I experimented with interactive layers, i.e. where objects could be visually placed on a map-these could be scenery objects, but also navaids. And once we move such assumptions out of the lcontroller files, we can trivially support other cool use-cases.
So depending on future progress, we could easily support other sources and ignore the oudated FG NavDB - if necessary.
Regarding your recent commits:
For the sake of intuitivity, I'd consider moving the included base class to the top of the file, and individual page groups next ?
And right, we can easily extend NavDisplay.new() to support a props.Node() too - feel free to make that change, see $FG_ROOT/Nasal/canvas/map/navdisplay.mfd - it's kinda messy actually, the whole new() vs. newMFD() separation, but it's getting increasingly cleaned up - and having different aircraft/use-cases is helping make it more generic
This is one of those things where working directly with a fgdata clone (e.g. via canvas-hackers) is probably a good idea to help clean up things across related efforts, such as the ND and MapStructure.
Besides, we should probably also change the MapStructure/ND code such that it can directly use an existing canvas, so that you don't have to use a separate canvas here.
We were exploring supporting that for the GPSMap196 anyway - it makes sense to directly deal with a group and apply clipping etc there - instead of having the hard-coded assumption that there'll always be a fixed-size canvas available. For the 196 that would be nice, because it supports multiple "map" views on a single screen.
Regarding the whole PageGroup structure, I think that's looking pretty good already - good job !
And even if you never consider to support the GNS430, I'd still suggest to keep the design sufficiently generic, so that others can have a go at it - even if that may not happen anytime soon, it will help modularize your code even more.
In the GPSMap196 we went a bit further and actually extracted device-agnostic APIs, so that other MFD-style instruments could be modeled on top of those APIs.
Currently, your code looks close enough actually - and once your mode/page handling is generalized some more, I'd kill off the old code and use your's
But as you can see in the GPSMap196 code, I'd consider adding a dedicated "Page Manager" class where all pages are registered, and where all event handling is taking place, and propagated to the active page via "mode" helpers.
To see for yourself, see:
https://gitorious.org/fg/canvas-hackers ... /GPSmap196However, that code uses a pretty weird approach in terms of button-handling via listeners - since then, Tom has updated Canvas to also support custom events, but that's not yet been integrated yet (F-JJTH is currently n/a). But the underlying idea -of having a dedicated PageManager- should scale better than most existing code:
https://gitorious.org/fg/canvas-hackers ... 96.nas#L62It's a fairly simple helper class actually, but helps encapsulate mode-handling:
https://gitorious.org/fg/canvas-hackers ... fd.nas#L47Given your own work, you could probably borrow some ideas/concepts and easily make the old code obsolete, while allowing us to reuse your work in the GPSMap196 code.
EDIT:
http://wiki.flightgear.org/Nasal_Variables- Code: Select all
diff --git a/GNS530.nas b/GNS530.nas
index 392908d..44883a6 100644
--- a/GNS530.nas
+++ b/GNS530.nas
@@ -156,7 +156,7 @@ var GNS530 = {
buttons = ["Swap_C", "Swap_V", "CDI", "Range", "Enter",
"Radio_kHz", "Radio_kHz_rot", "Radio_MHz_rot",
"Cursor", "Cursor_rot", "Field_rot"];
- foreach(p; buttons) {
+ foreach(var p; buttons) {
gns.mynode.initNode("buttons/"~p, 0.0, "DOUBLE");
};
@@ -177,7 +177,7 @@ var GNS530 = {
## general Annunciators
## ANNUNC window
- screen = gns.mycanvas.createGroup();
+ var screen = gns.mycanvas.createGroup();
screen.createChild("path")
.moveTo(5,350).lineTo(160,350).lineTo(160,443).lineTo(5,443).close()
.setColor(0.2,1,1).setColorFill(0, 0, 0).setStrokeLineWidth("2")
@@ -240,12 +240,12 @@ var GNS530 = {
setup_comm_vloc : func(comm_num, nav_num) {
var cv = {};
- screen = me.mycanvas.createGroup();
+ var screen = me.mycanvas.createGroup();
## COMM and VLOC frequency windows
conf = [ {label: "comm", text : "COM1", pos : 5},
{label: "vloc", text : "VLOC1", pos : 120}];
- foreach(p; conf) {
+ foreach(var p; conf) {
screen.createChild("path")
.moveTo(5, p.pos).lineTo(160, p.pos)
.lineTo(160, p.pos+110).lineTo(5, p.pos+110).close()
@@ -276,7 +276,7 @@ var GNS530 = {
conf = [ { label : "vor_ident", text: "VOR", pos : 268 },
{ label : "vor_radial", text: "RAD", pos : 300 },
{ label : "vor_distance", text: "DIS", pos : 335 } ];
- foreach(p; conf) {
+ foreach(var p; conf) {
screen.createChild("text")
.setTranslation(15, p.pos-4).setAlignment("left-baseline")
.setFontSize(20).setColor(0.2,1,1).set("z-index", 1)
@@ -293,7 +293,7 @@ var GNS530 = {
com_stby : props.globals.initNode("instrumentation/comm["~comm_num~"]/frequencies/standby-mhz", 120.350, "DOUBLE"),
nav_freq : props.globals.initNode("instrumentation/nav["~nav_num~"]/frequencies/selected-mhz", 110.00, "DOUBLE"),
nav_stby : props.globals.initNode("instrumentation/nav["~nav_num~"]/frequencies/standby-mhz", 112.50, "DOUBLE"), };
- foreach(k; keys(cv.nodes)) {
+ foreach(var k; keys(cv.nodes)) {
setlistener(cv.nodes[k], func() { me.update_freq(); }, 0, 0);
};
@@ -398,7 +398,7 @@ var create_nearest_list = func(type, maxentries) {
if(type == "airport") {
var info = airportinfo(entry.ident);
entry.length = 0;
- foreach(k; keys(info.runways)) {
+ foreach(var k; keys(info.runways)) {
if(info.runways[k].length > entry.length or
(info.runways[k].length == entry.length and info.runways[k].ils != nil)) {
entry.length = info.runways[k].length;
@@ -415,7 +415,7 @@ var create_nearest_list = func(type, maxentries) {
entry.comm_id = "";
entry.frequency = " . ";
var comms = info.comms();
- foreach(p; comms) {
+ foreach(var p; comms) {
if(substr(p.ident, 0, size(entry.name)) == entry.name)
p.ident = substr(p.ident, size(entry.name)+1);
append(entry.radio, {station : p.ident, frequency: sprintf("%3.2f", p.frequency)});
diff --git a/NAV.pagegroup.nas b/NAV.pagegroup.nas
index aa8012f..a199e9e 100644
--- a/NAV.pagegroup.nas
+++ b/NAV.pagegroup.nas
@@ -100,7 +100,7 @@ var NAV = {
## dep, dest, alt and enroute airfields, sorted by distance
## from current position
stations = {"departure" : "Departure", "destination" : "Arrival", "alternate" : "Alternate"};
- foreach(p; keys(stations)) {
+ foreach(var p; keys(stations)) {
var s = {ident : routemgr.getNode(p ~ "/airport", 1).getValue()};
if(s.ident != "" and s.ident != nil){
s.name = routemgr.getNode(p ~ "/name", 1).getValue();
@@ -109,7 +109,7 @@ var NAV = {
append(me.airports, s);
}
}
- foreach(p; me.airports) {
+ foreach(var p; me.airports) {
var info = airportinfo(p.ident);
if(size(info.comms()) > 0) {
var comms = info.comms();
diff --git a/PageGroup.nas b/PageGroup.nas
index a1e191f..297af4a 100644
--- a/PageGroup.nas
+++ b/PageGroup.nas
@@ -69,14 +69,14 @@ var PageGroup = {
{label: "right2", head_pos: 445, pos: 445, align: "center-baseline"},
{label: "right", head_pos: 615, pos: 620, align: "right-baseline"}];
pg.header={};
- foreach(p; pg.columns_conf) {
+ foreach(var p; pg.columns_conf) {
pg.header[p.label] = pg.list.createChild("text")
.setTranslation(p.head_pos, 65).setAlignment(p.align)
.setFontSize(20).setColor(0.2,1,1).set("z-index", 1);
};
pg.entry=[{},{},{},{},{},{},{},{}];
- forindex(i; pg.entry) {
- foreach(p; pg.columns_conf) {
+ forindex(var i; pg.entry) {
+ foreach(var p; pg.columns_conf) {
pg.entry[i][p.label] = pg.list.createChild("text")
.setTranslation(p.pos, 103+(42*i)).setAlignment(p.align)
.setFontSize(28).setColor(0.2,1,0.2).setColorFill(0.2, 1, 0.2)
@@ -97,7 +97,7 @@ var PageGroup = {
.setTranslation(420, 475).setAlignment("right-baseline")
.setFontSize(30).setColor(1,1,1).set("z-index", 1);
PageGroup.pnl.pageno_pictorial=[nil, nil, nil, nil, nil, nil, nil, nil];
- forindex(i; PageGroup.pnl.pageno_pictorial) {
+ forindex(var i; PageGroup.pnl.pageno_pictorial) {
PageGroup.pnl.pageno_pictorial[i] = pageno_bar.createChild("path")
.moveTo(440+(20*i), 453).lineTo(450+(20*i), 453).lineTo(450+(20*i), 473).lineTo(440+(20*i), 473).close()
.setColor(0.2,1,1).setColorFill(0.2,0.2,1).setStrokeLineWidth(2).set("z-index", 1);
@@ -114,12 +114,12 @@ var PageGroup = {
if(me.index > me.wintop + (viz - 1)) me.wintop = me.index - (viz - 1);
if(me.wintop < 0) me.wintop = 0;
var i = me.wintop;
- foreach(p; me.columns_conf) {
+ foreach(var p; me.columns_conf) {
me.header[p.label].setText(me.my_conf.header[p.label]);
}
while(i <= (me.wintop + (viz - 1))) {
- forindex(l; me.my_conf.line) {
- foreach(p; me.columns_conf) {
+ forindex(var l; me.my_conf.line) {
+ foreach(var p; me.columns_conf) {
var col = me.my_conf.line[l][p.label];
if(col == nil or col == "" or i >= size(me.my_list))
me.entry[i*me.my_conf.lines + l - (me.wintop * me.my_conf.lines)][p.label].hide();
@@ -166,7 +166,7 @@ var PageGroup = {
update_pageno : func() {
PageGroup.pnl.pageno_label.setText(me.group_name);
- forindex(i; PageGroup.pnl.pageno_pictorial) {
+ forindex(var i; PageGroup.pnl.pageno_pictorial) {
if (i < me.num_pages)
PageGroup.pnl.pageno_pictorial[i].setColor(0.2,1,1).setColorFill(0.2,0.2,1);
else