1
0
Fork 0

Support for Runway numbers on RWY MapStructure layer

- Change getInstance to getOrCreateInstance for FG1000.
- Implement runway numbering on AirportInformation page.
This commit is contained in:
Stuart Buchanan 2018-02-18 21:41:17 +00:00
parent b6df0ded76
commit 91dd762736
16 changed files with 383 additions and 61 deletions

View file

@ -36,7 +36,7 @@ var FG1000 = {
_instance : nil,
# Factory method
getInstance : func(EIS_Class = nil, EIS_SVG = nil) {
getOrCreateInstance : func(EIS_Class = nil, EIS_SVG = nil) {
if (FG1000._instance == nil) {
FG1000._instance = FG1000.new(EIS_Class, EIS_SVG);
}
@ -87,8 +87,6 @@ addMFD : func(index=nil, targetcanvas=nil, screenObject=nil) {
if (index == nil) {
index = size(keys(me.displays));
debug.dump(keys(me.displays));
print("No index passed. Defaulting to " ~ index);
} else if (me.displays[index] != nil) {
print("FG1000 Index " ~ index ~ " already exists!");
return

View file

@ -32,7 +32,7 @@ var GenericInterfaceController = {
_instance : nil,
# Factory method
getInstance : func() {
getOrCreateInstance : func() {
if (GenericInterfaceController._instance == nil) {
GenericInterfaceController._instance = GenericInterfaceController.new();
}

View file

@ -92,7 +92,7 @@ var AirportInfo =
);
var r = func(name,vis=1,zindex=nil) return caller(0)[0];
foreach(var type; [r('TAXI'),r('RWY')] ) {
foreach(var type; [r('TAXI'),r('RWY'),r('APT')] ) {
obj.AirportChart.addLayer(canvas.SymbolLayer,
type.name,
4,

View file

@ -34,7 +34,7 @@ var AirportInfoOptions =
loadOptions : func() {
me.clearOptions();
me.Options.APS = {};
me.Options.RWY = {};
},
clearOptions : func() {

View file

@ -33,8 +33,23 @@ var AirportInfoStyles =
},
loadStyles : func() {
me. clearStyles();
me.Styles.XXX = {};
me.clearStyles();
me.Styles.RWY = {};
me.Styles.RWY.text_color = [0,0,0,1]; # Black text ...
me.Styles.RWY.text_bgcolor = [1,1,1,1]; # ... on a white background
me.Styles.RWY.text_mode = canvas.Text.TEXT + canvas.Text.FILLEDBOUNDINGBOX;
me.Styles.RWY.text_padding = 1;
me.Styles.RWY.text_alignment = 'center-center';
me.Styles.RWY.text_size = 14;
me.Styles.RWY.show_labels= 1;
me.Styles.APT = {};
me.Styles.APT.scale_factor = 0.4; # 40% (applied to whole group)
me.Styles.APT.line_width = 3.0;
me.Styles.APT.color_default = [0,0.6,0.85]; #rgb
me.Styles.APT.label_font_color = me.Styles.APT.color_default;
me.Styles.APT.label_font_size=28;
},
clearStyles : func() {

View file

@ -23,7 +23,8 @@ piston engine.
You need to load it as follows:
var nasal_dir = getprop("/sim/fg-root") ~ "/Aircraft/Instruments-3d/FG1000/Nasal/";
var interfaceController = fg1000.GenericInterfaceController.getInstance();
io.load_nasal(nasal_dir ~ 'Interfaces/GenericInterfaceController.nas', "fg1000");
var interfaceController = fg1000.GenericInterfaceController.getOrCreateInstance();
interfaceController.start();
You may want to create your own version depending on what properties you are
@ -59,4 +60,4 @@ fg1000system.display(1);
fg1000system.display(2);
# Display a GUI version of device 1 at 50% scale.
#fg1000system.displayGUI(1, 0.5);
#fg1000system.displayGUI(1, 0.5)

View file

@ -0,0 +1,25 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'APS_FG1000';
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;

View file

@ -0,0 +1,18 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name = 'APS_FG1000';
var parents = [SVGSymbol];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
var svg_path = "Nasal/canvas/map/Images/genericAirplane.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);
};

View file

@ -0,0 +1,80 @@
<?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.91 r13725"
sodipodi:docname="genericAirplane.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="-4.1832711"
inkscape:cy="113.61967"
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="2495"
inkscape:window-height="1416"
inkscape:window-x="65"
inkscape:window-y="24"
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(320.73272,270.26689)"
inkscape:label="#g3781">
<g
id="g4609">
<path
id="path4607"
d="m 49.91928,116.3638 9.13879,0 -0.27758,10.02755 -14.86121,0 -15.05315,0 0.1063,-10.02755 8.94685,0 0,-61.61222 6,0 6,0 z m -12,-47.864661 12,0 m 0,15 -12,0"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.9684999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccc" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.9684999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 1.990145,83.499139 -0.14173,-15 c 27.960049,0 59.018293,0 84.124015,0 l -0.1063,15 c -27.878168,0 -58.844686,0 -83.875985,0 z"
id="path3783" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -8,12 +8,8 @@ SymbolLayer.add(name, {
parents: [MultiSymbolLayer],
type: name, # Symbol type
df_controller: __self__, # controller to use by default -- this one
df_style: {
surface_color: canvas.SURFACECOLORS
},
df_options: { # default configuration options
disable_position: 1,
},
df_options: {},
df_style: {},
});
var a_instance = nil;
var new = func(layer) {
@ -28,13 +24,11 @@ var new = func(layer) {
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);

View file

@ -5,6 +5,18 @@ var parents = [DotSym];
var __self__ = caller(0)[0];
DotSym.makeinstance( name, __self__ );
SymbolLayer.get(name).df_style = {
surface_color: canvas.SURFACECOLORS,
text_alignment: "center-center",
text_bgcolor: [0,0,0,0],
text_color: [0,0.6,0.85],
text_mode: canvas.Text.TEXT,
text_padding: 0,
text_size: 14,
text_font: "LiberationFonts/LiberationSans-Regular.ttf",
show_labels: 0,
};
var element_type = "group"; # we want a group, becomes "me.element"
var rwys = nil;
@ -98,40 +110,88 @@ var init = func {
end_thr2[0], end_thr2[1] ]
);
#draw helipads
foreach(var hp; keys(apt.helipads))
{
var hp = apt.runway(hp);
var clr = me.style.surface_color[hp.surface];
if (clr == nil) { clr = SURFACECOLORS[hp.surface]};
if (clr == nil) { clr = SURFACECOLORS[0]};
if (me.style.show_labels == 1) {
var coord1 = geo.Coord.new();
coord1.set_latlon(rw1.lat, rw1.lon);
coord1.apply_course_distance(rw1.heading, - 50.0);
var icon_hp =
me.element.createChild("path", "helipad-" ~ hp.id)
.setStrokeLineWidth(0.5)
.setColor(1.0,1.0,1.0)
.setColorFill(clr.r, clr.g, clr.b);
var coord2 = geo.Coord.new();
coord2.set_latlon(rw2.lat, rw2.lon);
coord2.apply_course_distance(rw2.heading, - 50.0);
var heli = Runway.new(hp);
var p1 = heli.pointOffCenterline(0.5 * hp.length, 0.5 * hp.width);
var p2 = heli.pointOffCenterline(0.5 * hp.length, -0.5 * hp.width);
var p3 = heli.pointOffCenterline(-0.5 * hp.length, -0.5 * hp.width);
var p4 = heli.pointOffCenterline(-0.5 * hp.length, 0.5 * hp.width);
icon_hp.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ p1[0], p1[1],
p2[0], p2[1],
p3[0], p3[1],
p4[0], p4[1] ]
);
}
var txt1 = me.element.createChild("text", "rwy1label")
.setText(rw1.id)
.setGeoPosition(coord1.lat(), coord1.lon())
.setFont(me.style.text_font)
.setFontSize(me.style.text_size)
.setAlignment(me.style.text_alignment)
.setPadding(me.style.text_padding)
.setDrawMode(me.style.text_mode)
.setColor(me.style.text_color)
.setColorFill(me.style.text_bgcolor);
var txt1 = me.element.createChild("text", "rwy2label")
.setText(rw2.id)
.setGeoPosition(coord2.lat(), coord2.lon())
.setFont(me.style.text_font)
.setFontSize(me.style.text_size)
.setAlignment(me.style.text_alignment)
.setPadding(me.style.text_padding)
.setDrawMode(me.style.text_mode)
.setColor(me.style.text_color)
.setColorFill(me.style.text_bgcolor);
}
}
#draw helipads
foreach(var hp; keys(apt.helipads))
{
var hp = apt.runway(hp);
var clr = me.style.surface_color[hp.surface];
if (clr == nil) { clr = SURFACECOLORS[hp.surface]};
if (clr == nil) { clr = SURFACECOLORS[0]};
var icon_hp =
me.element.createChild("path", "helipad-" ~ hp.id)
.setStrokeLineWidth(0.5)
.setColor(1.0,1.0,1.0)
.setColorFill(clr.r, clr.g, clr.b);
var heli = Runway.new(hp);
var p1 = heli.pointOffCenterline(0.5 * hp.length, 0.5 * hp.width);
var p2 = heli.pointOffCenterline(0.5 * hp.length, -0.5 * hp.width);
var p3 = heli.pointOffCenterline(-0.5 * hp.length, -0.5 * hp.width);
var p4 = heli.pointOffCenterline(-0.5 * hp.length, 0.5 * hp.width);
icon_hp.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ p1[0], p1[1],
p2[0], p2[1],
p3[0], p3[1],
p4[0], p4[1] ]
);
if (me.style.show_labels == 1) {
var coord1 = geo.Coord.new();
coord1.set_latlon(rw1.lat, rw1.lon);
coord1.apply_course_distance(rw1.heading, - 50.0);
var txt1 = me.element.createChild("text", "hplabel")
.setText(hp.id)
.setGeoPosition(coord1.lat(), coord1.lon())
.setFont(me.style.text_font)
.setFontSize(me.style.text_size)
.setAlignment(me.style.text_alignment)
.setPadding(me.style.text_padding)
.setDrawMode(me.style.text_mode)
.setColor(me.style.text_color)
.setColorFill(me.style.text_bgcolor);
}
}
};
var draw = func;

View file

@ -16,7 +16,7 @@ var new = func(layer) {
layer: layer,
map: layer.map,
listeners: [],
query_type:'ndb',
query_type:'vor',
};
m.addVisibilityListener();

View file

@ -104,15 +104,16 @@ var init = func {
);
cache.render(me.element, me.style).setScale(me.style.scale_factor);
var txt_offset = me.getStyle('text_offset', [3, 0]);
var txt_alignment = me.getStyle('text_alignment', 'left-bottom');
var txt_color = me.getStyle('text_color', [0,0.6,0.85]);
var txt_bgcolor = me.getStyle('text_bgcolor', [0,0,0,0]);
var txt_mode = me.getStyle('text_mode', canvas.Text.TEXT);
var txt_padding = me.getStyle('text_padding', 0);
var txt_size = me.getStyle('font_size', 14);
# non-cached stuff:
if (me.style.show_labels){
var txt_offset = me.getStyle('text_offset', [3, 0]);
var txt_alignment = me.getStyle('text_alignment', 'center-bottom');
var txt_color = me.getStyle('text_color', [0,0.6,0.85]);
var txt_bgcolor = me.getStyle('text_bgcolor', [0,0,0,0]);
var txt_mode = me.getStyle('text_mode', canvas.Text.TEXT);
var txt_padding = me.getStyle('text_padding', 0);
var txt_size = me.getStyle('font_size', 14);
me.text_fix = me.newText(me.model.id).
setScale(me.style.scale_factor).
setTranslation(txt_offset).

View file

@ -0,0 +1,62 @@
# See: http://wiki.flightgear.org/MapStructure
# Class things:
var name ='VOR-g1000';
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: {
nav1_frq: 'instrumentation/nav/frequencies/selected-mhz',
nav2_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');

View file

@ -0,0 +1,70 @@
# Class things:
var name = 'VOR-g1000';
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 = 'Nasal/canvas/map/Garmin/Images/g1000_vor2.svg';
#var svg_path = 'Nasal/canvas/map/Airbus/Images/airbus_vor.svg';
var vor_sym = nil;
var vor_center = nil;
var draw = func{
if(me.vor_sym == nil) {
me.vor_sym = me.element.getElementById("vor");
#me.vor_sym = me.element.getElementById("airbus-vor-sym");
}
me.vor_sym.setTranslation(-100,-100);
var heading = me.map.getHdg();
me.vor_sym.setRotation(heading);
#me.vor_sym.setScale(0.5);
if(me.text_vor == nil){
var transl = me.getStyle('translation', [-10,20]);
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(12)
.setColor(text_color)
.setTranslation(transl);
}
if(me.vor_center == nil) {
var line_width = me.getStyle('line_width', 3);
var color = me.getStyle('color', [0.2,0.2,0.6]);
me.vor_center = me.element.createChild("path")
.moveTo(-15,0)
.lineTo(-7.5,12.5)
.lineTo(7.5,12.5)
.lineTo(15,0)
.lineTo(7.5,-12.5)
.lineTo(-7.5,-12.5)
.close()
.setStrokeLineWidth(line_width)
.setColor(color)
.set("z-index",-2);
}
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 nav1_frq = getprop(me.options.nav1_frq);
var nav2_frq = getprop(me.options.nav2_frq);
if(nav1_frq == frq or nav2_frq == frq){
me.text_vor.setColor(me.getStyle('text_color', [1,1,1]));
} else {
me.text_vor.setColor(me.getStyle('text_color', [0.7,0.7,0.7]));
}
}
}

View file

@ -828,19 +828,17 @@
<script>
var nasal_dir = getprop("/sim/fg-root") ~ "/Aircraft/Instruments-3d/FG1000/Nasal/";
if (! defined("fg1000")) {
print("Loading FG1000 libraries");
io.load_nasal(nasal_dir ~ 'FG1000.nas', "fg1000");
io.load_nasal(nasal_dir ~ 'Interfaces/GenericInterfaceController.nas', "fg1000");
}
var fg1000system = fg1000.FG1000.getInstance();
var fg1000system = fg1000.FG1000.getOrCreateInstance();
var index = fg1000system.addMFD();
print("Index " ~ index);
fg1000system.displayGUI(index);
# Start the interface controller after the FG1000, as it will publish
# immediately and update the NAV/COM data.
var interfaceController = fg1000.GenericInterfaceController.getInstance();
var interfaceController = fg1000.GenericInterfaceController.getOrCreateInstance();
interfaceController.stop();
interfaceController.start();