Airbus style for MapStructure/navdisplay
105
Nasal/canvas/MapDrivers.nas
Normal file
|
@ -0,0 +1,105 @@
|
|||
var RouteDriver = {
|
||||
new: func(){
|
||||
var m = {
|
||||
parents: [RouteDriver],
|
||||
};
|
||||
m.init();
|
||||
return m;
|
||||
},
|
||||
init: func(){
|
||||
me.update();
|
||||
},
|
||||
update: func(){
|
||||
me.flightplan = flightplan();
|
||||
},
|
||||
getNumberOfFlightPlans: func(){1},
|
||||
getFlightPlanType: func(fpNum){'current'},
|
||||
getFlightPlan: func(fpNum){me.flightplan},
|
||||
getPlanSize: func(fpNum){me.flightplan.getPlanSize()},
|
||||
getWP: func(fpNum, idx){me.flightplan.getWP(idx)},
|
||||
getPlanModeWP: func(plan_wp_idx){me.flightplan.getWP(plan_wp_idx)},
|
||||
hasDiscontinuity: func(fpNum, wptID){0},
|
||||
getListeners: func(){[]},
|
||||
shouldUpdate: func 1
|
||||
};
|
||||
|
||||
var MultiRouteDriver = {
|
||||
parents: [RouteDriver],
|
||||
new: func(){
|
||||
var m = {
|
||||
parents: [MultiRouteDriver],
|
||||
_flightplans: [],
|
||||
currentFlightPlan: 0
|
||||
};
|
||||
m.init();
|
||||
return m;
|
||||
},
|
||||
addFlightPlan: func(type, plan){
|
||||
append(me._flightplans, {
|
||||
type: type,
|
||||
flightplan: plan
|
||||
});
|
||||
},
|
||||
removeFlightPlanAtIndex: func(idx){
|
||||
var sz = size(me._flightplans);
|
||||
if(idx < sz){
|
||||
if(sz == 1)
|
||||
me._flightplans = [];
|
||||
elsif(sz == 2 and idx == 0)
|
||||
me._flightplans = [me._flightplans[1]];
|
||||
elsif(sz == 2 and idx == 1)
|
||||
pop(me._flightplans);
|
||||
else {
|
||||
var subv_l = subvec(me._flightplans, 0, idx);
|
||||
var subv_r = subvec(me._flightplans, idx + 1);
|
||||
me._flightplans = subv_l ~ subv_r;
|
||||
}
|
||||
}
|
||||
me.triggerSignal('fp-added');
|
||||
},
|
||||
removeFlightPlanOfType: func(type){
|
||||
var new_vec = [];
|
||||
foreach(var fp; me._flightplans){
|
||||
if(fp['type'] != type)
|
||||
append(new_vec, fp);
|
||||
}
|
||||
me._flightplans = new_vec;
|
||||
me.triggerSignal('fp-removed');
|
||||
},
|
||||
getNumberOfFlightPlans: func(){
|
||||
size(me._flightplans);
|
||||
},
|
||||
getFlightPlanType: func(fpNum){
|
||||
if(fpNum >= size(me._flightplans)) return nil;
|
||||
var fp = me._flightplans[fpNum];
|
||||
return fp.type;
|
||||
},
|
||||
getFlightPlan: func(fpNum){
|
||||
if(fpNum >= size(me._flightplans)) return nil;
|
||||
return me._flightplans[fpNum];
|
||||
},
|
||||
getPlanSize: func(fpNum){
|
||||
if(fpNum >= size(me._flightplans)) return 0;
|
||||
return me._flightplans[fpNum].getPlanSize();
|
||||
},
|
||||
getWP: func(fpNum, idx){
|
||||
if(fpNum >= size(me._flightplans)) return nil;
|
||||
var fp = me._flightplans[fpNum].getPlanSize();
|
||||
return fp.getWP(idx);
|
||||
},
|
||||
getPlanModeWP: func(idx){
|
||||
if(me.currentFlightPlan >= size(me._flightplans)) return nil;
|
||||
var fp = me._flightplans[me.currentFlightPlan];
|
||||
return fp.getWP(idx);
|
||||
},
|
||||
triggerSignal: func(signal){
|
||||
setprop(me.signalPath(signal));
|
||||
},
|
||||
signalPath: func(signal){
|
||||
'autopilot/route-manager/signals/rd-'~ signal;
|
||||
},
|
||||
getListeners: func(){[
|
||||
me.getSignal('fp-added'),
|
||||
me.getSignal('fp-removed')
|
||||
]}
|
||||
};
|
|
@ -261,6 +261,17 @@ var hashdup = func(_,rkeys=nil) {
|
|||
var h={}; var k=rkeys!=nil?rkeys:members(_);
|
||||
foreach (var k;k) h[tryintern(k)]=member(_,k); h
|
||||
}
|
||||
var opt_member = func(h,k) {
|
||||
if (contains(h, k)) return h[k];
|
||||
if (contains(h, "parents")) {
|
||||
var _=h.parents;
|
||||
for (var i=0;i<size(_);i+=1){
|
||||
var v = opt_member(_[i], k);
|
||||
if (v != nil) return v;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
var member = func(h,k) {
|
||||
if (contains(h, k)) return h[k];
|
||||
if (contains(h, "parents")) {
|
||||
|
@ -434,6 +445,118 @@ var Symbol = {
|
|||
t.setColor(color);
|
||||
return t;
|
||||
},
|
||||
# Helper method that can be used to create a formatted String using
|
||||
# values extracted from the current model.
|
||||
#
|
||||
# SYNOPSIS:
|
||||
#
|
||||
# symbol.formattedString(format, model_property_names)
|
||||
#
|
||||
# Arguments:
|
||||
# - format: string
|
||||
# - model_property_names: a vector of strings representing the model
|
||||
# property names to be used as arguments
|
||||
#
|
||||
# EXAMPLE:
|
||||
#
|
||||
# var label = waypoint.formattedString('Waypoint %s: lat %.4f, lng %.4f', [model.id, model.lat, model.lon]);
|
||||
formattedString: func(frmt, model_props){
|
||||
if(me.model == nil) return frmt;
|
||||
var args = [];
|
||||
foreach(var prop; model_props){
|
||||
if(contains(me.model, prop)){
|
||||
var val = me.model[prop];
|
||||
var tp = typeof(val);
|
||||
if(tp != 'scalar'){
|
||||
val = '';
|
||||
#printlog("warn", "formattedString: invalid type for "~prop~" (" ~ tp ~ ")");
|
||||
} else {
|
||||
append(args, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return call(sprintf, [frmt] ~ args);
|
||||
},
|
||||
|
||||
# Wrapper method for accessing options. It allows to pass a default value
|
||||
# if the requested option is not defined.
|
||||
#
|
||||
# EXAMPLE:
|
||||
# var ok = (contains(me.options, 'enabled') ? me.options.enabled : 0);
|
||||
# var ok = me.getOption('enabled', 0);
|
||||
getOption: func(name, default = nil){
|
||||
var opt = me.options;
|
||||
if(opt == nil)
|
||||
opt = me.layer.options;
|
||||
if(opt == nil) return default;
|
||||
var val = opt_member(opt, name);
|
||||
if(val == nil) return default;
|
||||
return val;
|
||||
},
|
||||
|
||||
# Wrapper method for accessing style. It allows to pass a default value
|
||||
# if the requested style is not defined.
|
||||
# It also automatically resolves style properties when they're defined as
|
||||
# functions, by calling the corresponding function using the 'me' context
|
||||
#
|
||||
# EXAMPLE:
|
||||
#
|
||||
# me.style = {
|
||||
# color: [1,1,1],
|
||||
# line_color: func(){
|
||||
# me.model.tuned ? [0,0,1] : [1,1,1]
|
||||
# }
|
||||
# }
|
||||
# var color = me.getStyle('color'); # --> [1,1,1]
|
||||
# me.model.tuned = 1;
|
||||
# var line_color = me.getStyle('line_color'); # --> [0,0,1]
|
||||
# var txt_color = me.getStyle('text_color', [1,1,1]); # --> [1,1,1]
|
||||
getStyle: func(name, default = nil){
|
||||
var st = me.style;
|
||||
if(st == nil)
|
||||
st = me.layer.style;
|
||||
if(st == nil) return default;
|
||||
var val = opt_member(st, name);
|
||||
if(typeof(val) == 'func'){
|
||||
val = (call(val,[],me));
|
||||
}
|
||||
if(val == nil) return default;
|
||||
return val;
|
||||
},
|
||||
getLabelFromModel: func(default_val = nil){
|
||||
if(me.model == nil) return default_val;
|
||||
if(default_val == nil and contains(me.model, 'id'))
|
||||
default_val = me.model.id;
|
||||
var label_content = me.getOption('label_content');
|
||||
if(label_content == nil) return default_val;
|
||||
if(typeof(label_content) == 'scalar')
|
||||
label_content = [label_content];
|
||||
var format_s = me.getOption('label_format');
|
||||
var label = '';
|
||||
if(format_s == nil){
|
||||
format_s = "%s";
|
||||
}
|
||||
return me.formattedString(format_s, label_content);
|
||||
},
|
||||
# Executes callback function specified by the first argument with
|
||||
# variable arguments. The callback is executed within the 'me' context.
|
||||
# Callbacks must be defined inside the options hash.
|
||||
#
|
||||
# EXAMPLE:
|
||||
#
|
||||
# me.options = {
|
||||
# dump_callback: func(){
|
||||
# print('Waypoint '~ me.model.id);
|
||||
# }
|
||||
# }
|
||||
# me.callback('dump');
|
||||
callback: func(name, args...){
|
||||
name = name ~'_callback';
|
||||
var f = me.getOption(name);
|
||||
if(typeof(f) == 'func'){
|
||||
return call(f, args, me);
|
||||
}
|
||||
}
|
||||
}; # of Symbol
|
||||
|
||||
|
||||
|
@ -611,6 +734,7 @@ var DotSym = {
|
|||
} else
|
||||
me.element.show();
|
||||
me.draw();
|
||||
if(me.getOption('disable_position', 0)) return;
|
||||
var pos = me.controller.getpos(me.model);
|
||||
if (size(pos) == 2)
|
||||
pos~=[nil]; # fall through
|
||||
|
@ -632,17 +756,27 @@ var SVGSymbol = {
|
|||
element_type: "group",
|
||||
cacheable: 0,
|
||||
init: func() {
|
||||
me.callback('init_before');
|
||||
var opt_path = me.getStyle('svg_path');
|
||||
if(opt_path != nil)
|
||||
me.svg_path = opt_path;
|
||||
if (!me.cacheable) {
|
||||
canvas.parsesvg(me.element, me.svg_path);
|
||||
if(me.svg_path != nil and me.svg_path != '')
|
||||
canvas.parsesvg(me.element, me.svg_path);
|
||||
# hack:
|
||||
if (var scale = me.layer.style['scale_factor'])
|
||||
me.element.setScale(scale);
|
||||
if ((var transl = me.layer.style['translate']) != nil)
|
||||
me.element.setTranslation(transl);
|
||||
} else {
|
||||
__die("cacheable not implemented yet!");
|
||||
}
|
||||
me.callback('init_after');
|
||||
me.draw();
|
||||
},
|
||||
draw: func,
|
||||
draw: func{
|
||||
me.callback('draw');
|
||||
},
|
||||
}; # of SVGSymbol
|
||||
|
||||
|
||||
|
@ -685,7 +819,13 @@ var LineSymbol = {
|
|||
# For the instances returned from makeinstance:
|
||||
new: func(group, layer, model, controller=nil) {
|
||||
if (me == nil) __die("Need me reference for LineSymbol.new()");
|
||||
if (typeof(model) != 'vector') __die("LineSymbol.new(): need a vector of points");
|
||||
if (typeof(model) != 'vector') {
|
||||
if(typeof(model) == 'hash'){
|
||||
if(!contains(model, 'path'))
|
||||
__die("LineSymbol.new(): model hash requires path");
|
||||
}
|
||||
else __die("LineSymbol.new(): need a vector of points or a hash");
|
||||
}
|
||||
var m = {
|
||||
parents: [me],
|
||||
group: group,
|
||||
|
@ -705,19 +845,32 @@ var LineSymbol = {
|
|||
# Non-static:
|
||||
draw: func() {
|
||||
if (!me.needs_update) return;
|
||||
me.callback('draw_before');
|
||||
printlog(_MP_dbg_lvl, "redrawing a LineSymbol "~me.layer.type);
|
||||
me.element.reset();
|
||||
var cmds = [];
|
||||
var coords = [];
|
||||
var cmd = canvas.Path.VG_MOVE_TO;
|
||||
foreach (var m; me.model) {
|
||||
var (lat,lon) = me.controller.getpos(m);
|
||||
append(coords,"N"~lat);
|
||||
append(coords,"E"~lon);
|
||||
append(cmds,cmd); cmd = canvas.Path.VG_LINE_TO;
|
||||
var path = me.model;
|
||||
if(typeof(path) == 'hash'){
|
||||
path = me.model.path;
|
||||
if(path == nil)
|
||||
__die("LineSymbol model requires a 'path' member (vector)");
|
||||
}
|
||||
foreach (var m; path) {
|
||||
if(size(keys(m)) >= 2){
|
||||
var (lat,lon) = me.controller.getpos(m);
|
||||
append(coords,"N"~lat);
|
||||
append(coords,"E"~lon);
|
||||
append(cmds,cmd);
|
||||
cmd = canvas.Path.VG_LINE_TO;
|
||||
} else {
|
||||
cmd = canvas.Path.VG_MOVE_TO;
|
||||
}
|
||||
}
|
||||
me.element.setDataGeo(cmds, coords);
|
||||
me.element.update(); # this doesn't help with flickering, it seems
|
||||
me.callback('draw_after');
|
||||
},
|
||||
del: func() {
|
||||
printlog(_MP_dbg_lvl, "LineSymbol.del()");
|
||||
|
@ -791,6 +944,24 @@ var SymbolLayer = {
|
|||
assert_m(controller.parents[0], "parents");
|
||||
if (controller.parents[0].parents[0] != SymbolLayer.Controller)
|
||||
__die("MultiSymbolLayer: OOP error");
|
||||
if(options != nil){
|
||||
var listeners = opt_member(controller, 'listeners');
|
||||
var listen = opt_member(options, 'listen');
|
||||
if (listen != nil and listeners != nil){
|
||||
var listen_tp = typeof(listen);
|
||||
if(listen_tp != 'vector' and listen_tp != 'scalar')
|
||||
__die("Options 'listen' cannot be a "~ listen_tp);
|
||||
if(typeof(listen) == 'scalar')
|
||||
listen = [listen];
|
||||
foreach(var node_name; listen){
|
||||
var node = opt_member(options, node_name);
|
||||
if(node == nil)
|
||||
node = node_name;
|
||||
append(controller.listeners,
|
||||
setlistener(node, func call(m.update,[],m),0,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
m.controller = controller;
|
||||
},
|
||||
# For instances:
|
||||
|
@ -1010,6 +1181,67 @@ var SingleSymbolLayer = {
|
|||
# set up a cache for 32x32 symbols (initialized below in load_MapStructure)
|
||||
var SymbolCache32x32 = nil;
|
||||
|
||||
var MapStructure = {
|
||||
# Generalized load methods used to load various symbols, layer controllers,...
|
||||
loadFile : func(file, name) {
|
||||
if (name == nil)
|
||||
var name = split("/", file)[-1];
|
||||
var code = io.readfile(file);
|
||||
var code = call(func compile(code, file), [code], var err=[]);
|
||||
if (size(err)) {
|
||||
if (substr(err[0], 0, 12) == "Parse error:") { # hack around Nasal feature
|
||||
var e = split(" at line ", err[0]);
|
||||
if (size(e) == 2)
|
||||
err[0] = string.join("", [e[0], "\n at ", file, ", line ", e[1], "\n "]);
|
||||
}
|
||||
for (var i = 1; (var c = caller(i)) != nil; i += 1)
|
||||
err ~= subvec(c, 2, 2);
|
||||
debug.printerror(err);
|
||||
return;
|
||||
}
|
||||
#code=bind(
|
||||
call(code, nil, nil, var hash = {});
|
||||
|
||||
# validate
|
||||
var url = ' http://wiki.flightgear.org/MapStructure#';
|
||||
# TODO: these rules should be extended for all main files lcontroller/scontroller and symbol
|
||||
var checks = [
|
||||
{ extension:'symbol', symbol:'update', type:'func', error:' update() must not be overridden:', id:300},
|
||||
# Sorry, this one doesn't work with the new LineSymbol
|
||||
# { extension:'symbol', symbol:'draw', type:'func', required:1, error:' symbol files need to export a draw() routine:', id:301},
|
||||
# Sorry, this one doesn't work with the new SingleSymbolLayer
|
||||
# { extension:'lcontroller', symbol:'searchCmd', type:'func', required:1, error:' lcontroller without searchCmd method:', id:100},
|
||||
];
|
||||
|
||||
|
||||
var makeurl = func(scope, id) url ~ scope ~ ':' ~ id;
|
||||
var bailout = func(file, message, scope, id) __die(file~message~"\n"~makeurl(scope,id) );
|
||||
|
||||
var current_ext = split('.', file)[-1];
|
||||
foreach(var check; checks) {
|
||||
# check if we have any rules matching the current file extension
|
||||
if (current_ext == check.extension) {
|
||||
# check for fields that must not be overridden
|
||||
if (check['error'] != nil and
|
||||
hash[check.symbol]!=nil and !check['required'] and
|
||||
typeof(hash[check.symbol])==check.type ) {
|
||||
bailout(file,check.error,check.extension,check.id);
|
||||
}
|
||||
|
||||
# check for required fields
|
||||
if (check['required'] != nil and
|
||||
hash[check.symbol]==nil and
|
||||
typeof( hash[check.symbol]) != check.type) {
|
||||
bailout(file,check.error,check.extension,check.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var load_MapStructure = func {
|
||||
canvas.load_MapStructure = func; # disable any subsequent attempt to load
|
||||
|
||||
|
@ -1063,62 +1295,6 @@ var load_MapStructure = func {
|
|||
####### LOAD FILES #######
|
||||
(func {
|
||||
var FG_ROOT = getprop("/sim/fg-root");
|
||||
var load = func(file, name) {
|
||||
if (name == nil)
|
||||
var name = split("/", file)[-1];
|
||||
var code = io.readfile(file);
|
||||
var code = call(func compile(code, file), [code], var err=[]);
|
||||
if (size(err)) {
|
||||
if (substr(err[0], 0, 12) == "Parse error:") { # hack around Nasal feature
|
||||
var e = split(" at line ", err[0]);
|
||||
if (size(e) == 2)
|
||||
err[0] = string.join("", [e[0], "\n at ", file, ", line ", e[1], "\n "]);
|
||||
}
|
||||
for (var i = 1; (var c = caller(i)) != nil; i += 1)
|
||||
err ~= subvec(c, 2, 2);
|
||||
debug.printerror(err);
|
||||
return;
|
||||
}
|
||||
#code=bind(
|
||||
call(code, nil, nil, var hash = {});
|
||||
|
||||
# validate
|
||||
var url = ' http://wiki.flightgear.org/MapStructure#';
|
||||
# TODO: these rules should be extended for all main files lcontroller/scontroller and symbol
|
||||
var checks = [
|
||||
{ extension:'symbol', symbol:'update', type:'func', error:' update() must not be overridden:', id:300},
|
||||
# Sorry, this one doesn't work with the new LineSymbol
|
||||
# { extension:'symbol', symbol:'draw', type:'func', required:1, error:' symbol files need to export a draw() routine:', id:301},
|
||||
# Sorry, this one doesn't work with the new SingleSymbolLayer
|
||||
# { extension:'lcontroller', symbol:'searchCmd', type:'func', required:1, error:' lcontroller without searchCmd method:', id:100},
|
||||
];
|
||||
|
||||
|
||||
var makeurl = func(scope, id) url ~ scope ~ ':' ~ id;
|
||||
var bailout = func(file, message, scope, id) __die(file~message~"\n"~makeurl(scope,id) );
|
||||
|
||||
var current_ext = split('.', file)[-1];
|
||||
foreach(var check; checks) {
|
||||
# check if we have any rules matching the current file extension
|
||||
if (current_ext == check.extension) {
|
||||
# check for fields that must not be overridden
|
||||
if (check['error'] != nil and
|
||||
hash[check.symbol]!=nil and !check['required'] and
|
||||
typeof(hash[check.symbol])==check.type ) {
|
||||
bailout(file,check.error,check.extension,check.id);
|
||||
}
|
||||
|
||||
# check for required fields
|
||||
if (check['required'] != nil and
|
||||
hash[check.symbol]==nil and
|
||||
typeof( hash[check.symbol]) != check.type) {
|
||||
bailout(file,check.error,check.extension,check.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
};
|
||||
|
||||
# sets up a shared symbol cache, which will be used by all MapStructure maps and layers
|
||||
canvas.SymbolCache32x32 = SymbolCache.new(1024,32);
|
||||
|
@ -1146,7 +1322,7 @@ var load_MapStructure = func {
|
|||
foreach (var d; dep_names) {
|
||||
foreach (var f; deps[d]) {
|
||||
var name = split(".", f)[0];
|
||||
load(contents_dir~f, name);
|
||||
MapStructure.loadFile(contents_dir~f, name);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -360,6 +360,46 @@ var Group = {
|
|||
|
||||
return children;
|
||||
},
|
||||
# Recursively get all children of class specified by first param
|
||||
getChildrenOfType: func(type, array = nil){
|
||||
var children = array;
|
||||
if(children == nil)
|
||||
children = [];
|
||||
var my_children = me.getChildren();
|
||||
if(typeof(type) != 'vector')
|
||||
type = [type];
|
||||
foreach(var c; my_children){
|
||||
foreach(var t; type){
|
||||
if(isa(c, t)){
|
||||
append(children, c);
|
||||
}
|
||||
}
|
||||
if(isa(c, canvas.Group)){
|
||||
c.getChildrenOfType(type, children);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
},
|
||||
# Set color to children of type Path and Text. It is possible to optionally
|
||||
# specify which types of children should be affected by passing a vector as
|
||||
# the last agrument, ie. my_group.setColor(1,1,1,[Path]);
|
||||
setColor: func(){
|
||||
var color = arg;
|
||||
var types = [Path, Text];
|
||||
var arg_c = size(color);
|
||||
if(arg_c > 1 and typeof(color[-1]) == 'vector'){
|
||||
types = color[-1];
|
||||
color = subvec(color, 0, arg_c - 1);
|
||||
}
|
||||
var children = me.getChildrenOfType(types);
|
||||
if(typeof(color) == 'vector'){
|
||||
var first = color[0];
|
||||
if(typeof(first) == 'vector')
|
||||
color = first;
|
||||
}
|
||||
foreach(var c; children)
|
||||
c.setColor(color);
|
||||
},
|
||||
# Get first child with given id (breadth-first search)
|
||||
#
|
||||
# @note Use with care as it can take several miliseconds (for me eg. ~2ms).
|
||||
|
@ -460,11 +500,12 @@ var Map = {
|
|||
|
||||
return me;
|
||||
},
|
||||
addLayer: func(factory, type_arg=nil, priority=nil, style=nil, options=nil, visible=1)
|
||||
addLayer: func(factory, type_arg=nil, priority=nil, style=nil, opts=nil, visible=1)
|
||||
{
|
||||
if(contains(me.layers, type_arg))
|
||||
printlog("warn", "addLayer() warning: overwriting existing layer:", type_arg);
|
||||
|
||||
var options = opts;
|
||||
# Argument handling
|
||||
if (type_arg != nil) {
|
||||
var layer = factory.new(type:type_arg, group:me, map:me, style:style, options:options, visible:visible);
|
||||
|
|
|
@ -9,9 +9,9 @@ SymbolLayer.add(name, {
|
|||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
df_options: { # default configuration options
|
||||
active_node: "/autopilot/route-manager/active",
|
||||
fplan_active: "/autopilot/route-manager/active",
|
||||
vnav_node: "/autopilot/route-manager/vnav/",
|
||||
types: ["tc", "td", "sc", "ed"],
|
||||
types: ["tc", "td", "ec", "ed","sc", "sd"],
|
||||
}
|
||||
});
|
||||
var new = func(layer) {
|
||||
|
@ -22,7 +22,8 @@ var new = func(layer) {
|
|||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(a,b) a.getName() == b.getName();
|
||||
append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ));
|
||||
append(m.listeners, setlistener(layer.options.fplan_active,
|
||||
func m.layer.update() ));
|
||||
m.addVisibilityListener();
|
||||
|
||||
return m;
|
||||
|
|
|
@ -13,20 +13,39 @@ var element_type = "group";
|
|||
|
||||
var init = func {
|
||||
var name = me.model.getName();
|
||||
var disptext = chr(string.toupper(name[0]))~"/"~chr(string.toupper(name[1]));
|
||||
var radius = me.style.radius;
|
||||
me.element.createChild("path")
|
||||
var svg_path = me.getOption('svg_path');
|
||||
if (svg_path != nil) {
|
||||
var grp = me.element.createChild("group", name);
|
||||
if(typeof(svg_path) == 'scalar'){
|
||||
canvas.parsesvg(me.element, svg_path);
|
||||
}
|
||||
else{ #need hash
|
||||
if(!contains(svg_path, name))
|
||||
die('ALT-Profile: no SVG Path for '~ name);
|
||||
var path = svg_path[name];
|
||||
canvas.parsesvg(me.element, path);
|
||||
}
|
||||
} else {
|
||||
var disptext = chr(string.toupper(name[0]))~"/"~chr(string.toupper(name[1]));
|
||||
var radius = me.style.radius;
|
||||
me.element.createChild("path")
|
||||
.setStrokeLineWidth(5)
|
||||
.moveTo(-radius, 0)
|
||||
.arcLargeCW(radius, radius, 0, 2 * radius, 0)
|
||||
.arcLargeCW(radius, radius, 0, -2 * radius, 0)
|
||||
.arcLargeCW(radius, radius, 0, 2 * radius, 0)
|
||||
.arcLargeCW(radius, radius, 0, -2 * radius, 0)
|
||||
.setColor(0.195,0.96,0.097);
|
||||
me.element.createChild("text")
|
||||
me.element.createChild("text")
|
||||
.setDrawMode( canvas.Text.TEXT )
|
||||
.setText(disptext)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.setFontSize(28)
|
||||
.setTranslation(25,35)
|
||||
.setColor(0.195,0.96,0.097);
|
||||
}
|
||||
me.callback('init_after');
|
||||
}
|
||||
|
||||
var draw = func{
|
||||
me.callback('draw');
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,13 @@ SymbolLayer.add(name, {
|
|||
# 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: layer.map.getPosCoord(),
|
||||
_model: __model,
|
||||
};
|
||||
};
|
||||
var del = func;
|
||||
|
|
|
@ -15,6 +15,8 @@ SymbolLayer.add(name, {
|
|||
color_default: [0,0.6,0.85],
|
||||
label_font_color:[0,0.6,0.85],
|
||||
label_font_size: 28,
|
||||
text_offset: [17,35],
|
||||
svg_path: nil
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
@ -11,23 +11,34 @@ var text_apt = nil;
|
|||
|
||||
# add the draw routine from airports-nd.draw here
|
||||
var init = func {
|
||||
var icon_apt = me.element.createChild("path", name ~ " icon" )
|
||||
var icon_apt = nil;
|
||||
var style = me.layer.style;
|
||||
var svg_path = style.svg_path;
|
||||
if (svg_path != nil) {
|
||||
canvas.parsesvg(me.element, svg_path);
|
||||
} else {
|
||||
icon_apt = me.element.createChild("path", name ~ " icon" )
|
||||
.moveTo(-17,0)
|
||||
.arcSmallCW(17,17,0,34,0)
|
||||
.arcSmallCW(17,17,0,-34,0)
|
||||
.close()
|
||||
.setColor(me.layer.style.color_default)
|
||||
.setStrokeLineWidth(me.layer.style.line_width);
|
||||
.setColor(style.color_default)
|
||||
.setStrokeLineWidth(style.line_width);
|
||||
}
|
||||
var text = me.getLabelFromModel();
|
||||
if(text == nil){
|
||||
text = me.model.id;
|
||||
}
|
||||
var text_apt = me.element.createChild("text", name ~ " label")
|
||||
.setDrawMode( canvas.Text.TEXT )
|
||||
.setTranslation(17,35)
|
||||
.setText(me.model.id)
|
||||
.setTranslation(style.text_offset)
|
||||
.setText(text)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.setColor(me.layer.style.label_font_color)
|
||||
.setFontSize(me.layer.style.label_font_size);
|
||||
.setColor(style.label_font_color)
|
||||
.setFontSize(style.label_font_size);
|
||||
|
||||
# FIXME: this applies scale to the whole group, better do this separately for each element?
|
||||
me.element.setScale(me.layer.style.scale_factor);
|
||||
me.element.setScale(style.scale_factor);
|
||||
};
|
||||
var draw = func;
|
||||
|
||||
|
|
70
Nasal/canvas/map/Airbus/Images/airbusAirplane.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="apl_path"
|
||||
d="m 44.0787,102 0,-90 M 84,38 l -78,0 M 63,90 l -38,0"
|
||||
style="fill:none;stroke:#f2f235;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.1 KiB |
2084
Nasal/canvas/map/Airbus/Images/airbusND.svg
Normal file
After Width: | Height: | Size: 142 KiB |
99
Nasal/canvas/map/Airbus/Images/airbus_airport.svg
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg3090"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="Nuovo documento 10">
|
||||
<defs
|
||||
id="defs3092" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="8.6118945"
|
||||
inkscape:cx="24.13482"
|
||||
inkscape:cy="21.929539"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1256"
|
||||
inkscape:window-height="677"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata3095">
|
||||
<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
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="g3120"
|
||||
transform="translate(0.81282928,-0.3483554)">
|
||||
<g
|
||||
id="g3110">
|
||||
<rect
|
||||
style="fill:#af0063;stroke:#af0063"
|
||||
id="rect3106"
|
||||
width="31.128778"
|
||||
height="1.1431472"
|
||||
x="7.7382278"
|
||||
y="-24.606066"
|
||||
transform="scale(1,-1)" />
|
||||
<rect
|
||||
transform="matrix(0,-1,-1,0,0,0)"
|
||||
y="-23.874191"
|
||||
x="-39.598881"
|
||||
height="1.1431472"
|
||||
width="31.128778"
|
||||
id="rect3108"
|
||||
style="fill:#af0063;stroke:#af0063" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-10.169774,23.516978)"
|
||||
id="g3114">
|
||||
<rect
|
||||
transform="scale(1,-1)"
|
||||
y="-24.606066"
|
||||
x="7.7382278"
|
||||
height="1.1431472"
|
||||
width="31.128778"
|
||||
id="rect3116"
|
||||
style="fill:#af0063;stroke:#af0063" />
|
||||
<rect
|
||||
style="fill:#af0063;stroke:#af0063"
|
||||
id="rect3118"
|
||||
width="31.128778"
|
||||
height="1.1431472"
|
||||
x="-39.598881"
|
||||
y="-23.874191"
|
||||
transform="matrix(0,-1,-1,0,0,0)" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
77
Nasal/canvas/map/Airbus/Images/airbus_decel.svg
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_decel.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.3"
|
||||
inkscape:cx="-12.902798"
|
||||
inkscape:cy="24.002241"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="665"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#af0063;stroke-width:1.47335875;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path5312"
|
||||
sodipodi:cx="24.069767"
|
||||
sodipodi:cy="23.581396"
|
||||
sodipodi:rx="17.55814"
|
||||
sodipodi:ry="16.976744"
|
||||
d="m 41.627907,23.581396 a 17.55814,16.976744 0 1 1 -35.1162798,0 17.55814,16.976744 0 1 1 35.1162798,0 z"
|
||||
transform="matrix(1.3347658,0,0,1.3804934,-7.6915012,-8.9902419)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#af0063;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
|
||||
x="24.799843"
|
||||
y="38.763"
|
||||
id="text6082"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6084"
|
||||
x="24.799843"
|
||||
y="38.763">D</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
72
Nasal/canvas/map/Airbus/Images/airbus_ec.svg
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_ec.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.27"
|
||||
inkscape:cx="11.14417"
|
||||
inkscape:cy="15.800695"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="665"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="ec_symbol"
|
||||
style="stroke:#af0063;stroke-opacity:1">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2993"
|
||||
d="m 2.9285709,34.185715 12.3428571,-12.685716 30.514286,0 -4.8,-7.542856"
|
||||
style="fill:none;stroke:#af0063;stroke-width:2.39999999999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#af0063;stroke-width:2.40000010000000019px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 45.785714,21.561266 -4.8,7.542856"
|
||||
id="path3094"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
73
Nasal/canvas/map/Airbus/Images/airbus_ed.svg
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_ed.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.27"
|
||||
inkscape:cx="-22.252415"
|
||||
inkscape:cy="15.800695"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="706"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="ed_symbol"
|
||||
transform="matrix(1,0,0,-1,0,48.142858)"
|
||||
style="stroke:#118eff;stroke-opacity:1">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2993"
|
||||
d="m 2.9285709,34.185715 12.3428571,-12.685716 30.514286,0 -4.8,-7.542856"
|
||||
style="fill:none;stroke:#118eff;stroke-width:2.40000010000000019;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#118eff;stroke-width:2.40000010000000019px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 45.785714,21.561266 -4.8,7.542856"
|
||||
id="path3094"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
60
Nasal/canvas/map/Airbus/Images/airbus_holdL.svg
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?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="64px"
|
||||
height="64px"
|
||||
id="svg6263"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_hold_r.svg">
|
||||
<defs
|
||||
id="defs6265" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="11.363636"
|
||||
inkscape:cy="39.272727"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="64"
|
||||
inkscape:window-height="64"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6268">
|
||||
<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
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
d="m 38,58 l 0,-38 a 10,10 0 1 1 -20,0 l -5,-7 m5,7 l 8,-2"
|
||||
id="path7043"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:55.40000153;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
62
Nasal/canvas/map/Airbus/Images/airbus_holdR.svg
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?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="64px"
|
||||
height="64px"
|
||||
id="svg6263"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_holdL.svg">
|
||||
<defs
|
||||
id="defs6265" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="11.363636"
|
||||
inkscape:cy="36.978476"
|
||||
inkscape:current-layer="svg6263"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="703"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6268">
|
||||
<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
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="matrix(-1,0,0,1,59,0)">
|
||||
<path
|
||||
d="m 38,58 0,-38 a 10,10 0 1 1 -20,0 l -5,-7 m 5,7 8,-2"
|
||||
id="path7043"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:55.40000153;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
62
Nasal/canvas/map/Airbus/Images/airbus_sc.svg
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_sc.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.3"
|
||||
inkscape:cx="-39.763263"
|
||||
inkscape:cy="24.002241"
|
||||
inkscape:current-layer="Layer 1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="665"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="Layer 1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="stroke:#ffffff;stroke-width:2.07588959px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0.30339278,31.209046 c 44.00763722,0 34.21827422,0 34.21827422,0 l 9.840217,-13.513241 2.733394,9.652315 M 34.291189,18.20861 44.865702,16.790953"
|
||||
id="sc_symbol"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
62
Nasal/canvas/map/Airbus/Images/airbus_sd.svg
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_td.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.3"
|
||||
inkscape:cx="-8.8330301"
|
||||
inkscape:cy="24.002241"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="665"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="Layer 1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#none;stroke:#ffffff;stroke-width:2.07588959000000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0.30339278,21.60313 c 44.00763722,0 34.21827422,0 34.21827422,0 l 9.840217,13.513241 2.733394,-9.652314 m -12.804089,9.139509 10.574513,1.417657"
|
||||
id="sd_symbol"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
140
Nasal/canvas/map/Airbus/Images/airbus_spd_limit.svg
Normal file
|
@ -0,0 +1,140 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="airbus_spd_limit.svg">
|
||||
<defs
|
||||
id="defs2987">
|
||||
<linearGradient
|
||||
id="linearGradient5782"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#323232;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5784" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5412"
|
||||
osb:paint="solid">
|
||||
<stop
|
||||
style="stop-color:#af0063;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5414" />
|
||||
</linearGradient>
|
||||
<pattern
|
||||
patternUnits="userSpaceOnUse"
|
||||
width="34.9375"
|
||||
height="5.375"
|
||||
patternTransform="translate(7.71875,41.3125)"
|
||||
id="pattern5851">
|
||||
<g
|
||||
id="g5847"
|
||||
transform="translate(-7.71875,-41.3125)">
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0;fill-rule:nonzero;stroke:#323232;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
|
||||
id="rect5800"
|
||||
width="34.813999"
|
||||
height="2.6294737"
|
||||
x="7.7832417"
|
||||
y="43.999527" />
|
||||
<rect
|
||||
y="41.370525"
|
||||
x="7.7832417"
|
||||
height="2.6294737"
|
||||
width="34.814232"
|
||||
id="rect5845"
|
||||
style="fill:#323232;fill-opacity:1;fill-rule:nonzero;stroke:#323232;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
</g>
|
||||
</pattern>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.73"
|
||||
inkscape:cx="25.807853"
|
||||
inkscape:cy="26.171035"
|
||||
inkscape:current-layer="airbus-vor-sym"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1197"
|
||||
inkscape:window-height="667"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="airbus-spd-sym"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#323232;fill-opacity:1;stroke:none"
|
||||
d="M 12.5 11.5 C 11.276818 12.626179 10.226321 13.93529 9.375 15.375 L 38.625 15.375 C 37.773679 13.93529 36.723182 12.626179 35.5 11.5 L 12.5 11.5 z "
|
||||
id="rect3058" />
|
||||
<path
|
||||
style="fill:#af0063;fill-opacity:1;stroke:none"
|
||||
d="M 9.4375 15.28125 C 8.706022 16.49978 8.0972549 17.795497 7.6875 19.1875 L 40.3125 19.1875 C 39.902745 17.795497 39.293978 16.49978 38.5625 15.28125 L 9.4375 15.28125 z "
|
||||
id="rect4544" />
|
||||
<path
|
||||
style="fill:#323232;fill-opacity:1;stroke:none"
|
||||
d="M 7.71875 19.09375 C 7.3437512 20.340744 7.1407327 21.650439 7.0625 23 L 40.9375 23 C 40.859267 21.650439 40.656249 20.340744 40.28125 19.09375 L 7.71875 19.09375 z "
|
||||
id="rect4556" />
|
||||
<path
|
||||
style="fill:#af0063;fill-opacity:1;stroke:none"
|
||||
d="M 7.0625 22.90625 C 7.0396116 23.267297 7 23.633178 7 24 C 7 24.945579 7.1015573 25.877693 7.25 26.78125 L 40.75 26.78125 C 40.898443 25.877693 41 24.945579 41 24 C 41 23.633178 40.960388 23.267297 40.9375 22.90625 L 7.0625 22.90625 z "
|
||||
id="rect4558" />
|
||||
<path
|
||||
style="fill:#323232;fill-opacity:1;stroke:none"
|
||||
d="M 7.21875 26.6875 C 7.4348196 28.051579 7.8235864 29.358048 8.34375 30.59375 L 39.65625 30.59375 C 40.176414 29.358048 40.56518 28.051579 40.78125 26.6875 L 7.21875 26.6875 z "
|
||||
id="rect4572" />
|
||||
<path
|
||||
style="fill:#af0063;fill-opacity:1;stroke:none"
|
||||
d="M 8.28125 30.5 C 8.8624157 31.905891 9.6447903 33.188749 10.5625 34.375 L 37.4375 34.375 C 38.35521 33.188749 39.137584 31.905891 39.71875 30.5 L 8.28125 30.5 z "
|
||||
id="rect4574" />
|
||||
<path
|
||||
style="fill:#323232;fill-opacity:1;stroke:none"
|
||||
d="M 10.46875 34.28125 C 11.63072 35.807354 13.051977 37.12846 14.65625 38.1875 L 33.34375 38.1875 C 34.948023 37.12846 36.36928 35.807354 37.53125 34.28125 L 10.46875 34.28125 z "
|
||||
id="rect4578" />
|
||||
<path
|
||||
style="fill:#af0063;fill-opacity:1;stroke:none"
|
||||
d="M 14.5 38.09375 C 17.213218 39.926763 20.479185 41 24 41 C 27.520815 41 30.786782 39.926763 33.5 38.09375 L 14.5 38.09375 z "
|
||||
id="rect4580" />
|
||||
<path
|
||||
style="fill:#323232;fill-opacity:1;stroke:none"
|
||||
d="M 24 7 C 22.20493 7 20.468087 7.2655778 18.84375 7.78125 L 29.15625 7.78125 C 27.531913 7.2655778 25.79507 7 24 7 z "
|
||||
id="rect4592" />
|
||||
<path
|
||||
style="fill:#af0063;fill-opacity:1;stroke:none"
|
||||
d="M 19.1875 7.6875 C 16.607244 8.4470332 14.285939 9.80207 12.375 11.59375 L 35.625 11.59375 C 33.714061 9.80207 31.392756 8.4470332 28.8125 7.6875 L 19.1875 7.6875 z "
|
||||
id="rect4594" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.6 KiB |
71
Nasal/canvas/map/Airbus/Images/airbus_tc.svg
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_tc.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.27"
|
||||
inkscape:cx="14.464853"
|
||||
inkscape:cy="15.800695"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="665"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<g
|
||||
id="tc_symbol">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2993"
|
||||
d="m 2.9285709,34.185715 12.3428571,-12.685716 30.514286,0 -4.8,-7.542856"
|
||||
style="fill:none;stroke:#118eff;stroke-width:2.39999999999999991;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<path
|
||||
style="fill:none;stroke:#118eff;stroke-width:2.4000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 45.785714,21.561266 -4.8,7.542856"
|
||||
id="path3094"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
62
Nasal/canvas/map/Airbus/Images/airbus_td.svg
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_td.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.3"
|
||||
inkscape:cx="-8.8330301"
|
||||
inkscape:cy="24.002241"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1075"
|
||||
inkscape:window-height="665"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="Layer 1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#none;stroke:#ffffff;stroke-width:2.07588959000000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 0.30339278,21.60313 c 44.00763722,0 34.21827422,0 34.21827422,0 l 9.840217,13.513241 2.733394,-9.652314 m -12.804089,9.139509 10.574513,1.417657"
|
||||
id="td_symbol"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
101
Nasal/canvas/map/Airbus/Images/airbus_vor.old.svg
Normal file
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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="50"
|
||||
height="50"
|
||||
id="svg3076"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus-vor.svg">
|
||||
<metadata
|
||||
id="metadata3092">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs3090" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1248"
|
||||
inkscape:window-height="703"
|
||||
id="namedview3088"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.6619718"
|
||||
inkscape:cx="-33.09322"
|
||||
inkscape:cy="71"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg3076" />
|
||||
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
|
||||
<g
|
||||
id="g3078"
|
||||
inkscape:groupmode="layer"
|
||||
transform="matrix(0.34013605,0,0,0.33783784,0.84746249,0.78240397)">
|
||||
<title
|
||||
id="title3080">Layer 1</title>
|
||||
<g
|
||||
id="svg_7">
|
||||
<line
|
||||
id="svg_3"
|
||||
y2="71"
|
||||
x2="142"
|
||||
y1="71"
|
||||
x1="112"
|
||||
style="fill:none;stroke:#b00064;stroke-width:5" />
|
||||
<circle
|
||||
id="svg_2"
|
||||
r="39.115215"
|
||||
cy="71.5"
|
||||
cx="71"
|
||||
sodipodi:cx="71"
|
||||
sodipodi:cy="71.5"
|
||||
sodipodi:rx="39.115215"
|
||||
sodipodi:ry="39.115215"
|
||||
style="fill:none;stroke:#b00064;stroke-width:5"
|
||||
d="m 110.11522,71.5 c 0,21.602737 -17.512483,39.11522 -39.11522,39.11522 -21.602737,0 -39.115215,-17.512483 -39.115215,-39.11522 0,-21.602737 17.512478,-39.115215 39.115215,-39.115215 21.602737,0 39.11522,17.512478 39.11522,39.115215 z" />
|
||||
<line
|
||||
id="svg_4"
|
||||
y2="71"
|
||||
x2="30"
|
||||
y1="71"
|
||||
x1="0"
|
||||
style="fill:none;stroke:#b00064;stroke-width:5" />
|
||||
<line
|
||||
transform="matrix(0,1,-1,0,198,58)"
|
||||
id="svg_5"
|
||||
y2="128"
|
||||
x2="85"
|
||||
y1="128"
|
||||
x1="55"
|
||||
style="fill:none;stroke:#b00064;stroke-width:5" />
|
||||
<line
|
||||
id="svg_6"
|
||||
transform="matrix(0,1,-1,0,85,-55)"
|
||||
y2="15"
|
||||
x2="85"
|
||||
y1="15"
|
||||
x1="55"
|
||||
style="fill:none;stroke:#b00064;stroke-width:5" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
90
Nasal/canvas/map/Airbus/Images/airbus_vor.svg
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?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="48px"
|
||||
height="48px"
|
||||
id="svg2985"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="airbus_vor.svg">
|
||||
<defs
|
||||
id="defs2987" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.7255132"
|
||||
inkscape:cx="41.056088"
|
||||
inkscape:cy="29.220813"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1197"
|
||||
inkscape:window-height="667"
|
||||
inkscape:window-x="20"
|
||||
inkscape:window-y="20"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata2990">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="airbus-vor-sym"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#af0063;stroke-width:1.57920909;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path3014"
|
||||
sodipodi:cx="28.214285"
|
||||
sodipodi:cy="22.642857"
|
||||
sodipodi:rx="10.5"
|
||||
sodipodi:ry="10.214286"
|
||||
d="m 38.714285,22.642857 a 10.5,10.214286 0 1 1 -21,0 10.5,10.214286 0 1 1 21,0 z"
|
||||
transform="matrix(1.1857807,0,0,1.2189494,-9.1389546,-3.9914967)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3084"
|
||||
d="m 36.915889,23.738251 c 7.210196,0 9.210196,0 9.210196,0 l 0,0"
|
||||
style="fill:none;stroke:#af0063;stroke-width:2.23682857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#af0063;stroke-width:2.22900009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 24.316735,1.1057656 c 0,7.8137242 0,7.8137242 0,7.8137242 l 0,2.0000002"
|
||||
id="path3086"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3088"
|
||||
d="m 24.316735,35.872915 c 0,7.462294 0,9.462294 0,9.462294 l 0,0"
|
||||
style="fill:none;stroke:#af0063;stroke-width:2.22900009;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#af0063;stroke-width:2.23682857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 3.3195483,23.738251 c 7.2101957,0 7.2101957,0 7.2101957,0 l 2,0"
|
||||
id="path4589"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
37
Nasal/canvas/map/DECEL.lcontroller
Normal file
|
@ -0,0 +1,37 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'DECEL';
|
||||
var parents = [canvas.SymbolLayer.Controller];
|
||||
var __self__ = caller(0)[0];
|
||||
|
||||
canvas.SymbolLayer.Controller.add(name, __self__);
|
||||
canvas.SymbolLayer.add(name, {
|
||||
parents: [MultiSymbolLayer],
|
||||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
df_options : { # default configuration options
|
||||
decel_node: "/instrumentation/nd/symbols/decel/"
|
||||
}
|
||||
});
|
||||
var new = func(layer) {
|
||||
var m = {
|
||||
parents: [__self__],
|
||||
layer: layer,
|
||||
map: layer.map,
|
||||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(a,b) a.getName() == b.getName();
|
||||
return m;
|
||||
};
|
||||
var del = func() {
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
};
|
||||
|
||||
var searchCmd = func {
|
||||
var results = [];
|
||||
var symNode = props.globals.getNode(me.layer.options.decel_node);
|
||||
if (symNode != nil and symNode.getValue('longitude-deg') != nil)
|
||||
append(results, symNode);
|
||||
return results;
|
||||
}
|
32
Nasal/canvas/map/DECEL.symbol
Normal file
|
@ -0,0 +1,32 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'DECEL';
|
||||
var parents = [canvas.DotSym];
|
||||
var __self__ = caller(0)[0];
|
||||
canvas.DotSym.makeinstance( name, __self__ );
|
||||
|
||||
#canvas.SymbolLayer.get(name).df_style = {
|
||||
# radius: 13,
|
||||
#};
|
||||
|
||||
var element_type = "group";
|
||||
|
||||
var init = func {
|
||||
var svg_path = me.getStyle('svg_path');
|
||||
if(svg_path == nil)
|
||||
svg_path = 'Nasal/canvas/map/Airbus/Images/airbus_decel.svg';
|
||||
me.decel_grp = me.element.createChild("group","decel");
|
||||
canvas.parsesvg(me.decel_grp, svg_path);
|
||||
me.decel_grp.set('z-index', 5);
|
||||
}
|
||||
|
||||
var draw = func{
|
||||
if(me.decel_grp != nil){
|
||||
var spd_ctrl = getprop(me.options.spd_ctrl);
|
||||
var spd_managed = (spd_ctrl == me.options.managed_val);
|
||||
if(spd_managed)
|
||||
me.decel_grp.setColor(me.style.managed_color);
|
||||
else
|
||||
me.decel_grp.setColor(me.style.selected_color);
|
||||
}
|
||||
}
|
|
@ -103,22 +103,27 @@ var init_cache = func {
|
|||
#
|
||||
var init = func {
|
||||
# debug.dump(me.layer.style);
|
||||
me.icon_dme = me.element.createChild("path")
|
||||
.moveTo(-15,0)
|
||||
.line(-12.5,-7.5)
|
||||
.line(7.5,-12.5)
|
||||
.line(12.5,7.5)
|
||||
.lineTo(7.5,-12.5)
|
||||
.line(12.5,-7.5)
|
||||
.line(7.5,12.5)
|
||||
.line(-12.5,7.5)
|
||||
.lineTo(15,0)
|
||||
.lineTo(7.5,12.5)
|
||||
.vert(14.5)
|
||||
.horiz(-14.5)
|
||||
.vert(-14.5)
|
||||
.close()
|
||||
.setStrokeLineWidth( me.layer.style.line_width );
|
||||
var draw_func = me.getOption('draw_dme');
|
||||
if(typeof(draw_func) == 'func'){
|
||||
me.icon_dme = draw_func(me);
|
||||
} else {
|
||||
me.icon_dme = me.element.createChild("path")
|
||||
.moveTo(-15,0)
|
||||
.line(-12.5,-7.5)
|
||||
.line(7.5,-12.5)
|
||||
.line(12.5,7.5)
|
||||
.lineTo(7.5,-12.5)
|
||||
.line(12.5,-7.5)
|
||||
.line(7.5,12.5)
|
||||
.line(-12.5,7.5)
|
||||
.lineTo(15,0)
|
||||
.lineTo(7.5,12.5)
|
||||
.vert(14.5)
|
||||
.horiz(-14.5)
|
||||
.vert(-14.5)
|
||||
.close()
|
||||
.setStrokeLineWidth( me.layer.style.line_width );
|
||||
}
|
||||
|
||||
# finally scale the symbol as requested, this is done last so that people can override this when creating the layer
|
||||
me.apply_scale();
|
||||
|
@ -126,6 +131,15 @@ var init = func {
|
|||
me.timer = maketimer(0.33, func me.animate() );
|
||||
me.timer.start();
|
||||
}
|
||||
if(me.getOption('draw_text', 0)){
|
||||
me.dme_text = me.element.createChild("text")
|
||||
.setDrawMode( canvas.Text.TEXT )
|
||||
.setText(me.model.id)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.setFontSize(28)
|
||||
.setColor(me.getStyle('text_color', [1,1,1]))
|
||||
.setTranslation(me.getStyle('translation', [45,25]));
|
||||
}
|
||||
me.draw();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,20 +30,31 @@ var drawFIX = func(group) {
|
|||
.setStrokeLineWidth(line_width)
|
||||
.setColor(color);
|
||||
}
|
||||
|
||||
var cache = StyleableCacheable.new(
|
||||
name:name, draw_func: drawFIX,
|
||||
cache: SymbolCache32x32,
|
||||
draw_mode: SymbolCache.DRAW_CENTERED,
|
||||
relevant_keys: ["line_width", "color"],
|
||||
);
|
||||
var _name = name;
|
||||
|
||||
var init = func {
|
||||
# initialize the cached fix symbol
|
||||
var draw_fn = me.getOption('draw_function');
|
||||
if(typeof(draw_fn) != 'func')
|
||||
draw_fn = drawFIX;
|
||||
|
||||
var cache = StyleableCacheable.new(
|
||||
name:_name,
|
||||
draw_func: draw_fn,
|
||||
cache: SymbolCache32x32,
|
||||
draw_mode: SymbolCache.DRAW_CENTERED,
|
||||
relevant_keys: ["line_width", "color"],
|
||||
);
|
||||
cache.render(me.element, me.style).setScale(me.style.scale_factor);
|
||||
|
||||
var txt_offset = me.getStyle('text_offset', [17, 35]);
|
||||
var txt_color = me.getStyle('text_color', [0,0.6,0.85]);
|
||||
# non-cached stuff:
|
||||
if (me.style.show_labels)
|
||||
me.text_fix = me.newText(me.model.id).setScale(me.style.scale_factor).setTranslation(17,35).setColor(0,0.6,0.85);
|
||||
if (me.style.show_labels){
|
||||
me.text_fix = me.newText(me.model.id).
|
||||
setScale(me.style.scale_factor).
|
||||
setTranslation(txt_offset).
|
||||
setColor(txt_color);
|
||||
}
|
||||
}
|
||||
var draw = func;
|
||||
var draw = func {me.callback('draw');};
|
||||
|
|
100
Nasal/canvas/map/HOLD.lcontroller
Normal file
|
@ -0,0 +1,100 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'HOLD';
|
||||
var parents = [canvas.SymbolLayer.Controller];
|
||||
var __self__ = caller(0)[0];
|
||||
|
||||
canvas.SymbolLayer.Controller.add(name, __self__);
|
||||
canvas.SymbolLayer.add(name, {
|
||||
parents: [MultiSymbolLayer],
|
||||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
});
|
||||
var new = func(layer) {
|
||||
var m = {
|
||||
parents: [__self__],
|
||||
layer: layer,
|
||||
#map: layer.map,
|
||||
listeners: [],
|
||||
};
|
||||
#debug.dump(layer.parents);
|
||||
layer.searcher._equals = func(a,b) a.id == b.id;
|
||||
#append(m.listeners, setlistener(layer.options.fplan_active, func m.layer.update() ));
|
||||
#m.addVisibilityListener();
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
var del = func() {
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
};
|
||||
|
||||
var searchCmd = func {
|
||||
var results = [];
|
||||
var node = props.globals.getNode(me.layer.options.hold_node);
|
||||
var wp_id = node.getValue('wp');
|
||||
if(wp_id == nil or wp_id == '' or wp_id == '---'){
|
||||
return [];
|
||||
}
|
||||
var pointsNode = node.getNode('points');
|
||||
var pointNode = nil;
|
||||
var lat = nil;
|
||||
var lon = nil;
|
||||
if(pointsNode != nil)
|
||||
pointNode = pointsNode.getNode('point', 0);
|
||||
if (pointNode != nil){
|
||||
lat = pointNode.getValue('lat');
|
||||
lon = pointNode.getValue('lon');
|
||||
}
|
||||
if (pointNode != nil and lat != nil and lon != nil){
|
||||
var r = node.getValue('crs');
|
||||
var d = node.getValue('dist');
|
||||
var t = node.getValue('turn');
|
||||
var model = {
|
||||
parents: [geo.Coord],
|
||||
id: wp_id~r~d~t,
|
||||
pos: pointNode,
|
||||
type: 'pattern',
|
||||
latlon: func(){
|
||||
return [
|
||||
lat,
|
||||
lon
|
||||
];
|
||||
},
|
||||
radial: r,
|
||||
dist: d,
|
||||
turn: t,
|
||||
equals: func(o){me.id == o.id and me.radial == o.radial}
|
||||
};
|
||||
append(results, model);
|
||||
} else {
|
||||
var wp_idx = node.getValue('wp_id');
|
||||
var fp = flightplan();
|
||||
var wp = fp.getWP(wp_idx);
|
||||
#print("HOLD AT "~wp.wp_lat~", "~wp.wp_lon);
|
||||
if(wp == nil or wp.id != wp_id)
|
||||
return [];
|
||||
var wp_lat = wp.wp_lat;
|
||||
var wp_lon = wp.wp_lon;
|
||||
var model = {
|
||||
parents: [geo.Coord],
|
||||
id: wp_id~'-'~wp_idx~'-inactive',
|
||||
pos: nil,
|
||||
type: 'hold_symbol',
|
||||
latlon: func(){
|
||||
return [
|
||||
wp_lat,
|
||||
wp_lon
|
||||
];
|
||||
},
|
||||
radial: node.getValue('crs'),
|
||||
dist: node.getValue('dist'),
|
||||
turn: node.getValue('turn'),
|
||||
equals: func(o){me.id == o.id}
|
||||
};
|
||||
append(results, model);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
106
Nasal/canvas/map/HOLD.symbol
Normal file
|
@ -0,0 +1,106 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'HOLD';
|
||||
var parents = [canvas.DotSym];
|
||||
var __self__ = caller(0)[0];
|
||||
canvas.DotSym.makeinstance( name, __self__ );
|
||||
|
||||
#canvas.SymbolLayer.get(name).df_style = {
|
||||
# radius: 13,
|
||||
#};
|
||||
|
||||
var element_type = "group";
|
||||
|
||||
var draw_pattern = func(dist, ){
|
||||
var pattern = me.element.createChild("path", 'hold-pattern');
|
||||
pattern.set("z-index",4);
|
||||
var w = (dist * 2) / math.pi;
|
||||
var h = dist * 70;
|
||||
var r = w / 2;
|
||||
pattern.arcSmallCW(r,r,0,70 * w,0).
|
||||
line(0,h).
|
||||
arcSmallCW(r,r,0,-70 * w,0).
|
||||
line(0,-h).
|
||||
setStrokeLineWidth(5).
|
||||
setColor(me.active_color);
|
||||
return pattern;
|
||||
};
|
||||
|
||||
var draw_hold_sym = func(turn){
|
||||
var hold_symbol = me.element.createChild("group", 'hold-symbol');
|
||||
var svg = "Nasal/canvas/map/Airbus/Images/airbus_hold"~turn~".svg";
|
||||
canvas.parsesvg(hold_symbol, svg);
|
||||
hold_symbol.setTranslation(-32,-64).set('z-index', 4);
|
||||
return hold_symbol;
|
||||
}
|
||||
|
||||
var init = func {
|
||||
var type = me.model.type;
|
||||
var dist = me.model.dist;
|
||||
var turn = me.model.turn;
|
||||
me.active_color = me.getStyle('active_color',
|
||||
me.getOption('active_route_color',
|
||||
[0.4,0.7,0.4]));
|
||||
me.inactive_color = me.getStyle('inactive_color',
|
||||
me.getOption('inactive_route_color',
|
||||
[0.95,0.95,0.21]));
|
||||
if(type == 'pattern'){
|
||||
me.hold_pattern = me.draw_pattern(dist);
|
||||
me.hold_symbol = nil;
|
||||
} else {
|
||||
#print('CREATING HOLD SYM');
|
||||
me.hold_pattern = nil;
|
||||
me.hold_symbol = me.draw_hold_sym(turn);
|
||||
}
|
||||
}
|
||||
|
||||
var draw = func{
|
||||
var type = me.model.type;
|
||||
var map = me.layer.map;
|
||||
var pos = map.getPos();
|
||||
if(type == 'pattern'){
|
||||
var dist = me.model.dist;
|
||||
if(me.hold_symbol != nil){
|
||||
me.hold_symbol.hide();
|
||||
}
|
||||
if(me.hold_pattern == nil)
|
||||
me.hold_pattern = me.draw_pattern(dist);
|
||||
if(me.hold_pattern == nil) return;
|
||||
var radial = me.model.radial;
|
||||
if(radial != nil){
|
||||
|
||||
var hdg = pos[2];
|
||||
if(hdg == nil) hdg = 0;
|
||||
radial -= hdg;
|
||||
if(radial < 0) radial = 360 + radial;
|
||||
me.element.setRotation(radial*D2R);
|
||||
}
|
||||
var rng = pos[3];
|
||||
if(rng == nil) rng = 10;
|
||||
rng = 10 / rng;
|
||||
me.element.setScale(rng,rng);
|
||||
var lat_ctrl = getprop(me.getOption('lat_ctrl'));
|
||||
var lnav = (lat_ctrl == me.getOption('lat_ctrl_managed','fmgc'));
|
||||
var actv = getprop(me.getOption('fplan_active'));
|
||||
#print('HOLD ' ~ lnav ~ ',' ~ actv);
|
||||
if(!lnav or !actv)
|
||||
me.hold_pattern.setStrokeDashArray([32, 16]);
|
||||
else
|
||||
me.hold_pattern.setStrokeDashArray([1,0]);
|
||||
if(!actv)
|
||||
me.hold_pattern.setColor(me.inactive_color);
|
||||
else
|
||||
me.hold_pattern.setColor(me.active_color);
|
||||
} else {
|
||||
var turn = me.model.turn;
|
||||
if(me.hold_pattern != nil){
|
||||
me.hold_pattern.hide();
|
||||
}
|
||||
if(me.hold_symbol == nil)
|
||||
me.hold_symbol = me.draw_hold_sym(turn);
|
||||
|
||||
me.hold_symbol.show();
|
||||
me.element.setScale(1,1);
|
||||
me.element.setRotation(0);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ SymbolLayer.add(name, {
|
|||
active_node: "/autopilot/route-manager/active",
|
||||
current_wp_node: "/autopilot/route-manager/current-wp",
|
||||
wp_num: "/autopilot/route-manager/route/num",
|
||||
display_inactive_rte: 0
|
||||
}
|
||||
});
|
||||
var new = func(layer) {
|
||||
|
@ -25,9 +26,19 @@ var new = func(layer) {
|
|||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(l,r) 0; # TODO: create model objects instead?
|
||||
append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ), setlistener(layer.options.wp_num, func m.layer.update() ));
|
||||
m.addVisibilityListener();
|
||||
append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ),
|
||||
setlistener(layer.options.wp_num, func m.layer.update() ));
|
||||
|
||||
m.addVisibilityListener();
|
||||
var driver = opt_member(m.layer.options, 'route_driver');
|
||||
if(driver == nil){
|
||||
driver = RouteDriver.new();
|
||||
}
|
||||
var driver_listeners = driver.getListeners();
|
||||
foreach(var listener; driver_listeners){
|
||||
append(m.listeners, setlistener(listener, func m.layer.update()));
|
||||
}
|
||||
m.route_driver = driver;
|
||||
return m;
|
||||
};
|
||||
var del = func() {
|
||||
|
@ -35,21 +46,49 @@ var del = func() {
|
|||
removelistener(l);
|
||||
};
|
||||
|
||||
var last_result = [];
|
||||
|
||||
var searchCmd = func {
|
||||
# FIXME: do we return the current route even if it isn't active?
|
||||
printlog(_MP_dbg_lvl, "Running query: ", name);
|
||||
var plans = []; # TODO: multiple flightplans?
|
||||
|
||||
var plans = [];
|
||||
var driver = me.route_driver;
|
||||
driver.update();
|
||||
if(!driver.shouldUpdate()) return me.last_result;
|
||||
# http://wiki.flightgear.org/Nasal_Flightplan
|
||||
var fp = flightplan();
|
||||
var fpSize = fp.getPlanSize();
|
||||
if (!getprop(me.layer.options.active_node)) fpSize = 0;
|
||||
var coords = [];
|
||||
for (var i=0; i<fpSize; i += 1) {
|
||||
var leg = fp.getWP(i);
|
||||
coords ~= leg.path();
|
||||
var planCount = driver.getNumberOfFlightPlans();
|
||||
for (var idx = 0; idx < planCount; idx += 1) {
|
||||
#var fp = driver.getFlightPlan(idx);
|
||||
var fpSize = driver.getPlanSize(idx);
|
||||
if(fpSize < 2) continue;
|
||||
var type = driver.getFlightPlanType(idx);
|
||||
if(type == nil) type = 'current';
|
||||
if (!getprop(me.layer.options.active_node) and
|
||||
type == 'current' and
|
||||
!me.layer.options.display_inactive_rte) fpSize = 0;
|
||||
var coords = [];
|
||||
var discontinuity = 0;
|
||||
for (var i=0; i<fpSize; i += 1) {
|
||||
var leg = driver.getWP(idx, i);
|
||||
if(discontinuity)
|
||||
coords ~= [{},{lon:leg.wp_lon, lat:leg.wp_lat}];
|
||||
else
|
||||
coords ~= leg.path();
|
||||
discontinuity = driver.hasDiscontinuity(idx, leg.id);
|
||||
}
|
||||
append(plans, {
|
||||
id: type,
|
||||
#name: type,
|
||||
type: type,
|
||||
path: coords,
|
||||
#size: fpSize,
|
||||
equals: func(o){
|
||||
me.id == o.id# and me.size == o.size
|
||||
}
|
||||
});
|
||||
}
|
||||
append(plans, coords);
|
||||
me.last_result = plans;
|
||||
return plans;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,8 +11,31 @@ SymbolLayer.get(name).df_style = { # style to use by default
|
|||
color: [1,0,1]
|
||||
};
|
||||
|
||||
var init = func {
|
||||
me.element.setColor(me.style.color)
|
||||
.setStrokeLineWidth(me.style.line_width);
|
||||
var getLineStyle = func(property, df_val){
|
||||
var type = nil;
|
||||
if(typeof(me.model) == 'hash'){
|
||||
type = me.model.type;
|
||||
}
|
||||
if(type != nil and type != 'current'){
|
||||
var base_prop = property;
|
||||
property = property~'_'~type;
|
||||
me.getStyle(property, me.getStyle(base_prop, df_val));
|
||||
} else {
|
||||
me.getStyle(property, df_val);
|
||||
}
|
||||
};
|
||||
|
||||
var setRouteStyle = func{
|
||||
var df_style = SymbolLayer.get(name).df_style;
|
||||
var dash = me.getLineStyle('line_dash', []);
|
||||
var color = me.getLineStyle('color', df_style.color);
|
||||
var line_width = me.getLineStyle('line_width', df_style.line_width);
|
||||
me.element.setColor(color).setStrokeLineWidth(line_width);
|
||||
if(typeof(dash) == 'vector')
|
||||
me.element.setStrokeDashArray(dash);
|
||||
};
|
||||
|
||||
var init = func {
|
||||
me.setRouteStyle();
|
||||
};
|
||||
|
||||
|
|
104
Nasal/canvas/map/RWY-profile.lcontroller
Normal file
|
@ -0,0 +1,104 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
|
||||
var name = 'RWY-profile';
|
||||
var parents = [SymbolLayer.Controller];
|
||||
var __self__ = caller(0)[0];
|
||||
SymbolLayer.Controller.add(name, __self__);
|
||||
SymbolLayer.add(name, {
|
||||
parents: [MultiSymbolLayer],
|
||||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
df_options: { # default configuration options
|
||||
disable_position: 1,
|
||||
dep_rwy: '/autopilot/route-manager/departure/runway',
|
||||
dest_rwy: '/autopilot/route-manager/destination/runway',
|
||||
dep_arpt: '/autopilot/route-manager/departure/airport',
|
||||
dest_arpt: '/autopilot/route-manager/destination/airport'
|
||||
}
|
||||
});
|
||||
|
||||
var new = func(layer) {
|
||||
var m = {
|
||||
parents: [__self__],
|
||||
layer: layer,
|
||||
map: layer.map,
|
||||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(l,r) {l.equals(r)}; # TODO: create model objects instead?
|
||||
#append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ));
|
||||
#m.addVisibilityListener();
|
||||
var driver = opt_member(m.layer.options, 'route_driver');
|
||||
if(driver == nil){
|
||||
driver = RouteDriver.new();
|
||||
}
|
||||
var driver_listeners = driver.getListeners();
|
||||
foreach(var listener; driver_listeners){
|
||||
append(m.listeners, setlistener(listener, func m.layer.update()));
|
||||
}
|
||||
m.route_driver = driver;
|
||||
return m;
|
||||
};
|
||||
|
||||
var del = func() {
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
};
|
||||
|
||||
var FPRunwayModel = {
|
||||
new: func(apt, rwy){
|
||||
var m = {
|
||||
parents: [FPRunwayModel],
|
||||
id: rwy.id,
|
||||
lat: rwy.lat,
|
||||
lon: rwy.lon,
|
||||
length: rwy.length,
|
||||
width: rwy.width,
|
||||
heading: rwy.heading,
|
||||
airport_id: apt.id
|
||||
};
|
||||
return m;
|
||||
},
|
||||
latlon: func(){
|
||||
return [
|
||||
me.lat,
|
||||
me.lon
|
||||
];
|
||||
},
|
||||
equals: func(o){me.id == o.id and me.airport_id == o.airport_id}
|
||||
};
|
||||
|
||||
var searchCmd = func {
|
||||
#var desApt = airportinfo(getprop(me.layer.options.dest_arpt));
|
||||
#var depApt = airportinfo(getprop(me.layer.options.dep_arpt));
|
||||
#if(desApt == nil and depApt == nil)
|
||||
# return [];
|
||||
var res = [];
|
||||
var desRwy = nil;
|
||||
var depRwy = nil;
|
||||
|
||||
var driver = me.route_driver;
|
||||
if(!driver.shouldUpdate()) return res;
|
||||
driver.update();
|
||||
var fpcount = driver.getNumberOfFlightPlans();
|
||||
for(var i = 0; i < fpcount; i += 1){
|
||||
if(!driver.shouldUpdate()) continue;
|
||||
var fp = driver.getFlightPlan(i);
|
||||
var depApt = fp.departure;
|
||||
if(depApt != nil){
|
||||
var depRwy = fp.departure_runway;
|
||||
if(depRwy != nil){
|
||||
var model = FPRunwayModel.new(depApt, depRwy);
|
||||
append(res, model);
|
||||
}
|
||||
}
|
||||
var desApt = fp.destination;
|
||||
if(desApt != nil){
|
||||
var desRwy = fp.destination_runway;
|
||||
if(desRwy != nil){
|
||||
var model = FPRunwayModel.new(desApt, desRwy);
|
||||
append(res, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
93
Nasal/canvas/map/RWY-profile.symbol
Normal file
|
@ -0,0 +1,93 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
|
||||
# Class things:
|
||||
var name = 'RWY-profile';
|
||||
var parents = [DotSym];
|
||||
var __self__ = caller(0)[0];
|
||||
DotSym.makeinstance( name, __self__ );
|
||||
|
||||
var element_type = "group";
|
||||
|
||||
var style = { # style to use by default
|
||||
zoom: 20,
|
||||
color: [1,1,1],
|
||||
center_line_len: 0.75,
|
||||
line_width: 3
|
||||
};
|
||||
|
||||
SymbolLayer.get(name).df_style = style;
|
||||
#var already_drawn = 0;
|
||||
|
||||
var init = func {
|
||||
#if(me.already_drawn) return;
|
||||
var lat = me.model.lat;
|
||||
var lon = me.model.lon;
|
||||
var rwyhdg = me.model.heading;
|
||||
var width = me.model.width;
|
||||
var length = me.model.length;
|
||||
var group = me.element;
|
||||
var ctr_len = length * me.getStyle('center_line_len', 0.75);
|
||||
var crds = [];
|
||||
var coord = geo.Coord.new();
|
||||
width = width * me.getStyle('zoom', 20); # Else rwy is too thin to be visible
|
||||
var line_w = me.getStyle('line_width', 3);
|
||||
var color = me.getStyle('color', [1,1,1]);
|
||||
coord.set_latlon(lat, lon);
|
||||
coord.apply_course_distance(rwyhdg, -(ctr_len / 2));
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
coord.apply_course_distance(rwyhdg, (ctr_len));
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
icon_rwy = group.createChild("path", "rwy-cl")
|
||||
.setStrokeLineWidth(line_w)
|
||||
.setDataGeo([2,4],crds)
|
||||
.setColor(color);
|
||||
#.setStrokeDashArray([10, 20, 10, 20, 10]);
|
||||
#icon_rwy.hide();
|
||||
var crds = [];
|
||||
coord.set_latlon(lat, lon);
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
coord.apply_course_distance(rwyhdg + 90, width/2);
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
coord.apply_course_distance(rwyhdg, length);
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
icon_rwy = group.createChild("path", "rwy")
|
||||
.setStrokeLineWidth(line_w)
|
||||
.setDataGeo([2,4,4],crds)
|
||||
.setColor(color);
|
||||
var crds = [];
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
coord.apply_course_distance(rwyhdg - 90, width);
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
coord.apply_course_distance(rwyhdg, -length);
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
coord.apply_course_distance(rwyhdg + 90, width / 2);
|
||||
append(crds,"N"~coord.lat());
|
||||
append(crds,"E"~coord.lon());
|
||||
icon_rwy = group.createChild("path", "rwy")
|
||||
.setStrokeLineWidth(line_w)
|
||||
.setDataGeo([2,4,4,4],crds)
|
||||
.setColor(color);
|
||||
};
|
||||
|
||||
var draw = func{}
|
||||
|
||||
|
||||
#var update = func() {
|
||||
# if (me.controller != nil) {
|
||||
# if (!me.controller.update(me, me.model)) return;
|
||||
# elsif (!me.controller.isVisible(me.model)) {
|
||||
# me.element.hide();
|
||||
# return;
|
||||
# }
|
||||
# } else
|
||||
# me.element.show();
|
||||
# me.draw();
|
||||
#}
|
49
Nasal/canvas/map/SPD-profile.lcontroller
Normal file
|
@ -0,0 +1,49 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'SPD-profile';
|
||||
var parents = [canvas.SymbolLayer.Controller];
|
||||
var __self__ = caller(0)[0];
|
||||
|
||||
var _options = { # default configuration options
|
||||
alts: [100,140,250,260,'wp']
|
||||
};
|
||||
canvas.SymbolLayer.Controller.add(name, __self__);
|
||||
canvas.SymbolLayer.add(name, {
|
||||
parents: [MultiSymbolLayer],
|
||||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
df_options: _options
|
||||
});
|
||||
var new = func(layer) {
|
||||
var m = {
|
||||
parents: [__self__],
|
||||
layer: layer,
|
||||
#map: layer.map,
|
||||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(a,b) a.getName() == b.getName();
|
||||
#append(m.listeners, setlistener(layer.options.fplan_active, func m.layer.update() ));
|
||||
#m.addVisibilityListener();
|
||||
|
||||
return m;
|
||||
};
|
||||
var del = func() {
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
};
|
||||
|
||||
var searchCmd = func {
|
||||
var results = [];
|
||||
var symNode = props.globals.getNode(me.layer.options.spd_node);
|
||||
if (symNode != nil)
|
||||
foreach (var alt; me.layer.options.alts) {
|
||||
t = 'spd-change-point' ~ '-' ~ alt;
|
||||
#print('SPD-Controller, search for '~t);
|
||||
var n = symNode.getNode(t);
|
||||
if (n != nil and n.getValue('longitude-deg') != nil){
|
||||
#print('SPD-Controller -> Append');
|
||||
append(results, n);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
40
Nasal/canvas/map/SPD-profile.symbol
Normal file
|
@ -0,0 +1,40 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'SPD-profile';
|
||||
var parents = [canvas.SVGSymbol];
|
||||
var __self__ = caller(0)[0];
|
||||
canvas.DotSym.makeinstance( name, __self__ );
|
||||
|
||||
#canvas.SymbolLayer.get(name).df_style = {
|
||||
# radius: 13,
|
||||
#};
|
||||
|
||||
var element_type = "group";
|
||||
var svg_path = 'Nasal/canvas/map/Airbus/Images/airbus_spd_limit.svg';
|
||||
var spd_sym = nil;
|
||||
|
||||
#var init = func {
|
||||
# var name = me.model.getName();
|
||||
# #var radius = me.style.radius;
|
||||
# var sym_group = me.element.createChild("group", name);
|
||||
# sym_group.set("z-index",5);
|
||||
# var color = me.getStyle('color');
|
||||
# var spd_path = sym_group.createChild("path").
|
||||
# setStrokeLineWidth(3).
|
||||
# moveTo(-17,0).
|
||||
# arcSmallCW(17,17,0,34,0).
|
||||
# arcSmallCW(17,17,0,-34,0).
|
||||
# setColor(color).
|
||||
# setColorFill(color).
|
||||
# set("z-index",5);
|
||||
#}
|
||||
|
||||
var draw = func{
|
||||
# var name = me.model.getName();
|
||||
# var sym_group = me.element.getElementById(name);
|
||||
# sym_group.set('z-index', 5);
|
||||
if(me.spd_sym == nil){
|
||||
me.spd_sym = me.getElementById("airbus-spd-sym");
|
||||
me.spd_sym.setTranslation(-24, -24).set('z-index', 5);
|
||||
}
|
||||
}
|
62
Nasal/canvas/map/VOR-airbus.lcontroller
Normal file
|
@ -0,0 +1,62 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name ='VOR-airbus';
|
||||
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');
|
44
Nasal/canvas/map/VOR-airbus.symbol
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Class things:
|
||||
var name = 'VOR-airbus';
|
||||
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/Airbus/Images/airbus_vor.svg';
|
||||
var vor_sym = nil;
|
||||
|
||||
var draw = func{
|
||||
if(me.vor_sym == nil)
|
||||
me.vor_sym = me.element.getElementById("airbus-vor-sym");
|
||||
me.vor_sym.setTranslation(-24,-24);
|
||||
if(me.text_vor == nil){
|
||||
var transl = me.getStyle('translation', [25,10]);
|
||||
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(28)
|
||||
.setColor(text_color)
|
||||
.setTranslation(transl);
|
||||
}
|
||||
|
||||
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.element.setColor(tuned_color);
|
||||
} else {
|
||||
me.element.setColor(dfcolor);
|
||||
}
|
||||
}
|
||||
|
||||
me.text_vor.setColor(me.getStyle('text_color', [1,1,1]));
|
||||
}
|
137
Nasal/canvas/map/WPT-airbus.lcontroller
Normal file
|
@ -0,0 +1,137 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'WPT-airbus';
|
||||
var parents = [canvas.SymbolLayer.Controller];
|
||||
var __self__ = caller(0)[0];
|
||||
|
||||
canvas.SymbolLayer.Controller.add(name, __self__);
|
||||
canvas.SymbolLayer.add(name, {
|
||||
parents: [canvas.MultiSymbolLayer],
|
||||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
df_options: { # default configuration options
|
||||
fix_symbol: func(group){
|
||||
group.createChild('path')
|
||||
.moveTo(-10,0)
|
||||
.lineTo(0,-17)
|
||||
.lineTo(10,0)
|
||||
.lineTo(0,17)
|
||||
.close()
|
||||
.setStrokeLineWidth(3)
|
||||
.setColor(1,1,1)
|
||||
.setScale(1);
|
||||
},
|
||||
vor_symbol: 'Nasal/canvas/map/Airbus/Images/airbus_vor.svg',
|
||||
airport_symbol: 'Nasal/canvas/map/Airbus/Images/airbus_airport.svg',
|
||||
ndb_symbol: func(group){
|
||||
group.createChild('path')
|
||||
.moveTo(-15,15)
|
||||
.lineTo(0,-15)
|
||||
.lineTo(15,15)
|
||||
.close()
|
||||
.setStrokeLineWidth(3)
|
||||
#.setColor(0.69,0,0.39)
|
||||
#.setTranslation(-24, -24),
|
||||
.setScale(1,1);
|
||||
}
|
||||
},
|
||||
df_style: {
|
||||
active_wp_color: [0.4,0.7,0.4],
|
||||
current_wp_color: [1,1,1],
|
||||
translation: {
|
||||
'airport': [-24,-24],
|
||||
'vor': [-24,-24]
|
||||
}
|
||||
},
|
||||
toggle_cstr: 0
|
||||
});
|
||||
|
||||
var new = func(layer) {
|
||||
var m = {
|
||||
parents: [__self__],
|
||||
layer: layer,
|
||||
map: layer.map,
|
||||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(a,b) a.equals(b);
|
||||
var driver = opt_member(m.layer.options, 'route_driver');
|
||||
if(driver == nil){
|
||||
driver = RouteDriver.new();
|
||||
}
|
||||
var driver_listeners = driver.getListeners();
|
||||
foreach(var listener; driver_listeners){
|
||||
append(m.listeners, setlistener(listener, func m.layer.update()));
|
||||
}
|
||||
m.route_driver = driver;
|
||||
return m;
|
||||
};
|
||||
|
||||
var del = func() {
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
};
|
||||
|
||||
var WPTModel = {
|
||||
new: func(fp, idx) {
|
||||
var m = { parents:[WPTModel] };
|
||||
var wp = fp.getWP(idx);
|
||||
|
||||
m.id = wp.id;
|
||||
m.name = wp.wp_name;
|
||||
m.alt = wp.alt_cstr;
|
||||
m.spd = wp.speed_cstr;
|
||||
m.type = wp.wp_type;
|
||||
|
||||
(m.lat,m.lon) = (wp.wp_lat,wp.wp_lon);
|
||||
var is_rwy = (m.type == 'runway');
|
||||
var id_len = size(m.id);
|
||||
if(!is_rwy and id_len < 5){
|
||||
if(id_len == 4 and airportinfo(m.id) != nil)
|
||||
m.navtype = 'airport';
|
||||
else {
|
||||
var navaid = nil;
|
||||
foreach(var t; ['vor', 'ndb']){
|
||||
navaid = navinfo(m.lat, m.lon, t, m.id);
|
||||
if(navaid != nil and size(navaid)){
|
||||
m.navtype = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(navaid == nil or !size(navaid)) m.navtype = 'fix';
|
||||
}
|
||||
} else {
|
||||
m.navtype = (is_rwy ? 'rwy' : 'fix');
|
||||
}
|
||||
|
||||
m.wp = wp;
|
||||
idx = wp.index;
|
||||
m.idx = idx;
|
||||
m.is_departure = (idx == 0 and is_rwy);
|
||||
m.is_destination = (idx > 0 and is_rwy);
|
||||
return m;
|
||||
},
|
||||
equals: func(other) {
|
||||
# this is set on symbol init, so use this for equality...
|
||||
me.name == other.name and me.alt == other.alt and
|
||||
me.type == other.type and me.idx == other.idx and
|
||||
me.navtype == other.navtype
|
||||
},
|
||||
};
|
||||
|
||||
var searchCmd = func {
|
||||
var driver = me.route_driver;
|
||||
if(!driver.shouldUpdate()) return [];
|
||||
driver.update();
|
||||
var result = [];
|
||||
var planCount = driver.getNumberOfFlightPlans();
|
||||
for(var idx = 0; idx < planCount; idx += 1){
|
||||
var fp = driver.getFlightPlan(idx);
|
||||
if(fp == nil) continue;
|
||||
var fpSize = fp.getPlanSize(idx);
|
||||
for (var i = 0; i < fpSize; i+=1){
|
||||
if(!driver.shouldUpdate()) return[];
|
||||
append(result, WPTModel.new(fp, i));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
137
Nasal/canvas/map/WPT-airbus.symbol
Normal file
|
@ -0,0 +1,137 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'WPT-airbus';
|
||||
var parents = [canvas.DotSym];
|
||||
var __self__ = caller(0)[0];
|
||||
canvas.DotSym.makeinstance( name, __self__ );
|
||||
|
||||
var element_type = "group";
|
||||
|
||||
var init = func {
|
||||
var name = me.model.name;
|
||||
var alt = me.model.alt;
|
||||
var spd = me.model.spd;
|
||||
var wp_group = me.element;
|
||||
me.alt_path = nil;
|
||||
|
||||
var colors = [
|
||||
'wp_color',
|
||||
'current_wp_color',
|
||||
'constraint_color',
|
||||
'active_constraint_color',
|
||||
'missed_constraint_color'
|
||||
];
|
||||
foreach(col; colors){
|
||||
me[col] = me.getStyle(col, me.getOption(col));
|
||||
}
|
||||
|
||||
var idLen = size(me.model.id);
|
||||
var draw_sym = nil;
|
||||
var navtype = me.model.navtype;
|
||||
if (navtype == nil) navtype = 'fix';
|
||||
if(navtype == 'airport')
|
||||
draw_sym = me.options.airport_symbol;
|
||||
elsif(navtype == 'vor')
|
||||
draw_sym = me.options.vor_symbol;
|
||||
elsif(navtype == 'ndb')
|
||||
draw_sym = me.options.ndb_symbol;
|
||||
else
|
||||
draw_sym = me.options.fix_symbol;
|
||||
me.wp_sym = me.element.createChild('group', 'wp-'~ me.model.idx);
|
||||
if(typeof(draw_sym) == 'func')
|
||||
draw_sym(me.wp_sym);
|
||||
elsif(typeof(draw_sym) == 'scalar')
|
||||
canvas.parsesvg(me.wp_sym, draw_sym);
|
||||
var translation = me.getStyle('translation', {});
|
||||
if(contains(translation, navtype)){
|
||||
me.wp_sym.setTranslation(translation[navtype]);
|
||||
}
|
||||
me.text_wps = wp_group.createChild("text", "wp-text-" ~ me.model.idx)
|
||||
.setDrawMode( canvas.Text.TEXT )
|
||||
.setText(me.model.name)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.setFontSize(28)
|
||||
.setTranslation(25,15)
|
||||
.setColor(1,1,1);
|
||||
me.text_alt = nil;
|
||||
if(alt > 0 or spd > 0){
|
||||
var cstr_txt = "\n";
|
||||
if(alt > 0){
|
||||
if(alt > 10000)
|
||||
cstr_txt ~= sprintf('FL%3.0f', int(alt / 100));
|
||||
else
|
||||
cstr_txt ~= sprintf('%4.0f', int(alt));
|
||||
}
|
||||
if(spd > 0){
|
||||
if(alt > 0) cstr_txt ~= "\n";
|
||||
if(spd <= 1)
|
||||
cstr_txt ~= sprintf('%1.2fM', spd);
|
||||
else
|
||||
cstr_txt ~= sprintf('%3.0fKT', int(spd));
|
||||
}
|
||||
me.text_alt = wp_group.createChild("text", "wp-alt-text-" ~ me.model.idx)
|
||||
.setDrawMode( canvas.Text.TEXT )
|
||||
.setText(cstr_txt)
|
||||
.setFont("LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.setFontSize(28)
|
||||
.setTranslation(25,15);
|
||||
}
|
||||
}
|
||||
|
||||
var draw = func{
|
||||
var wp_group = me.element;
|
||||
var alt = me.model.alt;
|
||||
var i = me.model.idx;
|
||||
var vnav_actv = getprop(me.options.ver_ctrl) == me.options.managed_val;
|
||||
var curwp = getprop(me.options.current_wp);
|
||||
if(alt > 0){
|
||||
var wp_d = me.model.wp.distance_along_route;
|
||||
var lvl_off_at = getprop(me.options.level_off_alt);
|
||||
if(lvl_off_at == nil) lvl_off_at = 0;
|
||||
if(me.alt_path == nil){
|
||||
me.alt_path = wp_group.createChild("path").
|
||||
setStrokeLineWidth(4).
|
||||
moveTo(-22,0).
|
||||
arcSmallCW(22,22,0,44,0).
|
||||
arcSmallCW(22,22,0,-44,0);
|
||||
}
|
||||
if(vnav_actv){
|
||||
if(lvl_off_at and (lvl_off_at - wp_d) > 0.5 and curwp == i)
|
||||
me.alt_path.setColor(me.missed_constraint_color);
|
||||
else
|
||||
me.alt_path.setColor(me.active_constraint_color);
|
||||
}
|
||||
else
|
||||
me.alt_path.setColor(me.constraint_color);
|
||||
if(me.layer.toggle_cstr)
|
||||
me.alt_path.show();
|
||||
else
|
||||
me.alt_path.hide();
|
||||
} else {
|
||||
if(me.alt_path != nil) me.alt_path.hide();
|
||||
}
|
||||
wp_group.set("z-index",4);
|
||||
#var sym = me.element.getElementById('wp-' ~ me.model.idx);
|
||||
if(alt > 0 and me.text_alt != nil){
|
||||
if(vnav_actv)
|
||||
me.text_alt.setColor(me.active_constraint_color);
|
||||
else
|
||||
me.text_alt.setColor(me.constraint_color);
|
||||
}
|
||||
if(i == curwp) {
|
||||
me.wp_sym.setColor(me.current_wp_color);
|
||||
me.text_wps.setColor(me.current_wp_color);
|
||||
} else {
|
||||
me.wp_sym.setColor(me.wp_color);
|
||||
me.text_wps.setColor(me.wp_color);
|
||||
}
|
||||
if(me.model.is_departure or me.model.is_destination){
|
||||
var prop = (me.model.is_departure ? 'departure' : 'destination');
|
||||
var rwy = getprop("/autopilot/route-manager/"~prop~"/runway");
|
||||
if(rwy != nil and size(rwy) > 0){
|
||||
me.wp_sym.hide();
|
||||
} else {
|
||||
me.wp_sym.show();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,6 +24,15 @@ var new = func(layer) {
|
|||
};
|
||||
layer.searcher._equals = func(l,r) l.equals(r);
|
||||
append(m.listeners, setlistener(layer.options.active_node, func m.layer.update() ), setlistener(layer.options.wp_num, func m.layer.update() ));
|
||||
var driver = opt_member(m.layer.options, 'route_driver');
|
||||
if(driver == nil){
|
||||
driver = RouteDriver.new();
|
||||
}
|
||||
var driver_listeners = driver.getListeners();
|
||||
foreach(var listener; driver_listeners){
|
||||
append(m.listeners, setlistener(listener, func m.layer.update()));
|
||||
}
|
||||
m.route_driver = driver;
|
||||
m.addVisibilityListener();
|
||||
|
||||
return m;
|
||||
|
@ -59,12 +68,16 @@ var searchCmd = func {
|
|||
printlog(_MP_dbg_lvl, "Running query: "~name);
|
||||
|
||||
if (!getprop(me.options.active_node)) return [];
|
||||
|
||||
var fp = flightplan();
|
||||
var fpSize = fp.getPlanSize();
|
||||
var driver = me.route_driver;
|
||||
driver.update();
|
||||
var result = [];
|
||||
for (var i = 0; i < fpSize; i+=1)
|
||||
append(result, WPT_model.new(fp, i));
|
||||
var planCount = driver.getNumberOfFlightPlans();
|
||||
for(var idx = 0; idx < planCount; idx += 1){
|
||||
var fp = driver.getFlightPlan(idx);
|
||||
var fpSize = fp.getPlanSize(idx);
|
||||
for (var i = 0; i < fpSize; i+=1)
|
||||
append(result, WPT_model.new(fp, i));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
|
69
Nasal/canvas/map/WXR_live.lcontroller
Normal file
|
@ -0,0 +1,69 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'WXR_live';
|
||||
var parents = [SymbolLayer.Controller];
|
||||
var __self__ = caller(0)[0];
|
||||
SymbolLayer.Controller.add(name, __self__);
|
||||
SymbolLayer.add(name, {
|
||||
parents: [MultiSymbolLayer],
|
||||
type: name, # Symbol type
|
||||
df_controller: __self__, # controller to use by default -- this one
|
||||
df_options: { # default configuration options
|
||||
viewport_radius: 670
|
||||
}
|
||||
});
|
||||
|
||||
var wxr_tree = "/instrumentation/wxr";
|
||||
|
||||
var new = func(layer) {
|
||||
var m = {
|
||||
parents: [__self__],
|
||||
layer: layer,
|
||||
map: layer.map,
|
||||
listeners: [],
|
||||
};
|
||||
layer.searcher._equals = func(l,r) l.equals(r);
|
||||
m.addVisibilityListener();
|
||||
#io.read_properties(getprop("/sim/fg-root") ~ "/Nasal/canvas/wxr_api.xml", wxr_tree);
|
||||
var saved_conf = getprop("/sim/fg-home") ~ "/Export/wxr_api.xml";
|
||||
if(io.stat(saved_conf) != nil)
|
||||
io.read_properties(saved_conf, wxr_tree);
|
||||
else
|
||||
io.read_properties(getprop("/sim/fg-root") ~ "/Nasal/canvas/wxr_api.xml", wxr_tree);
|
||||
return m;
|
||||
};
|
||||
var del = func() {
|
||||
#print(name~".lcontroller.del()");
|
||||
foreach (var l; me.listeners)
|
||||
removelistener(l);
|
||||
};
|
||||
|
||||
var searchCmd = func {
|
||||
if(me.map.getRange() == nil) return [];
|
||||
var api_key = getprop(wxr_tree~"/api-key");
|
||||
if(!api_key or api_key == '' or api_key == 'YOUR API KEY')
|
||||
return [];
|
||||
var lat = getprop(wxr_tree~"/center/latitude-deg");
|
||||
var lon = getprop(wxr_tree~"/center/longitude-deg");
|
||||
|
||||
if(lat == nil or lon == nil) {
|
||||
var pos = geo.aircraft_position();
|
||||
lat = pos.lat();
|
||||
lon = pos.lon();
|
||||
}
|
||||
|
||||
var result = geo.Coord.new();
|
||||
result.set_latlon(lat, lon);
|
||||
result.rangeNm = me.map.getRange();
|
||||
result.key = api_key;
|
||||
result.res = getprop(wxr_tree~"/resolution");
|
||||
result.ltype = getprop(wxr_tree~"/layer-type");
|
||||
result.smooth = getprop(wxr_tree~"/smooth");
|
||||
result.fetchRad = getprop(wxr_tree~"/fetch-radius");
|
||||
result.equals = func(r){
|
||||
me.ltype == r.ltype and me.fetchRad == r.fetchRad and
|
||||
me.lat == r.lat and me.lon == r.lon
|
||||
};
|
||||
|
||||
return [result];
|
||||
};
|
111
Nasal/canvas/map/WXR_live.symbol
Normal file
|
@ -0,0 +1,111 @@
|
|||
# See: http://wiki.flightgear.org/MapStructure
|
||||
# Class things:
|
||||
var name = 'WXR_live';
|
||||
var parents = [DotSym];
|
||||
var __self__ = caller(0)[0];
|
||||
DotSym.makeinstance( name, __self__ );
|
||||
|
||||
var element_type = "group";
|
||||
|
||||
var getWXRImageFilePath = func(){
|
||||
var home = getprop('sim/fg-home');
|
||||
var aircraft = getprop('sim/aircraft');
|
||||
var idx = me.layer.getCanvas()._node.getIndex();
|
||||
return home ~ '/Export/' ~ aircraft ~ '-wxr-'~me.ltype~'-'~idx~'.png';
|
||||
};
|
||||
|
||||
var getWXRAPIUrl = func(lat, lon){
|
||||
var res = me.res;
|
||||
if(me.ltype == "radar"){
|
||||
return "http://api.wunderground.com/api/"~me.key~
|
||||
"/radar/image.png?centerlat="~lat~"¢erlon="~lon~
|
||||
"&radius="~me.fetchRad~"&width="~res~"&height="~res~
|
||||
"&smooth="~me.smooth;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
};
|
||||
|
||||
var fetchWXRMap = func(size){
|
||||
if(me.fetching) return;
|
||||
var pos = geo.aircraft_position();
|
||||
var lat = pos.lat();
|
||||
var lon = pos.lon();
|
||||
var url = me.getWXRAPIUrl(lat, lon);
|
||||
var filePath = me.getWXRImageFilePath();
|
||||
if(url == nil) {
|
||||
print(me.name~': No URL!');
|
||||
return;
|
||||
}
|
||||
me.fetching = 1;
|
||||
http.save(url, filePath)
|
||||
.fail(func(){print(me.name~': Download failed!');})
|
||||
.done(func(){
|
||||
var sz = size * 2;
|
||||
var transl = -size;
|
||||
me.wxlayer.hide();
|
||||
me.wxlayer.setFile(filePath)
|
||||
.setSize(sz, sz)
|
||||
.setTranslation(transl, transl);
|
||||
me.wxlayer.show();
|
||||
me.last_request = getprop("/sim/time/elapsed-sec");
|
||||
})
|
||||
.always(func(){
|
||||
setprop("/instrumentation/wxr/center/latitude-deg", lat);
|
||||
setprop("/instrumentation/wxr/center/longitude-deg", lon);
|
||||
me.fetching = 0;
|
||||
print("[WXR] Live Layer Request: "~url); # Debugging
|
||||
});
|
||||
};
|
||||
|
||||
var init = func {
|
||||
#print('WXR init');
|
||||
me.fetching = 0;
|
||||
me.key = me.model.key; # API Key from Wunderground API Subscription
|
||||
me.res = me.model.res; # Resolution of image to fetch (default 2048)
|
||||
me.ltype = me.model.ltype; # Layer Type - radar, satellite
|
||||
me.smooth = me.model.smooth; # If we should fetch a smoothened image or the original
|
||||
me.fetchRad = me.model.fetchRad; # Radius of radar layer to fetch
|
||||
me.range = me.model.rangeNm; # Range of Navigation Display
|
||||
me.viewport_radius = me.getOption('viewport_radius', 670);
|
||||
|
||||
me.wxlayer = me.element.createChild("image").set("z-index", -100).hide();
|
||||
|
||||
me.last_request = -210;
|
||||
me.update_interval = 240;
|
||||
|
||||
var r_scaled = (me.fetchRad*me.viewport_radius)/me.range;
|
||||
me.fetchWXRMap(r_scaled);
|
||||
};
|
||||
|
||||
var draw = func {
|
||||
var range = me.layer.map.getRange(); # Range of Navigation Display
|
||||
var update_size = (range != me.range);
|
||||
me.range = range;
|
||||
me.fetchRad = me.model.fetchRad; # Radius of radar layer to fetch
|
||||
#var r_scaled = (me.fetchRad*670)/me.range;
|
||||
var r_scaled = (me.fetchRad*me.viewport_radius)/me.range;
|
||||
var hdg = me.layer.map.getHdg();
|
||||
var rot = 0 - hdg;
|
||||
if(rot < 0) rot = 360 + rot;
|
||||
me.element.setRotation(rot*D2R);
|
||||
if(update_size){
|
||||
print('WXR draw range:'~ me.range);
|
||||
print('Update size: '~r_scaled~'x2 = '~(r_scaled*2));
|
||||
me.wxlayer.hide();
|
||||
me.wxlayer.setSize(2*r_scaled, 2*r_scaled)
|
||||
.setTranslation(-r_scaled, -r_scaled);
|
||||
me.wxlayer.show();
|
||||
}
|
||||
|
||||
if(getprop("/sim/time/elapsed-sec") - me.last_request > me.update_interval) {
|
||||
#print('Fetching WXR map...');
|
||||
me.key = me.model.key; # API Key from Wunderground API Subscription
|
||||
me.res = me.model.res; # Resolution of image to fetch (default 2048)
|
||||
me.ltype = me.model.ltype; # Layer Type - radar, satellite
|
||||
me.smooth = me.model.smooth; # If we should fetch a smoothened image or the original
|
||||
|
||||
me.fetchWXRMap(r_scaled);
|
||||
}
|
||||
};
|
||||
|
|
@ -22,6 +22,8 @@ io.include("Nasal/canvas/map/navdisplay.styles");
|
|||
# encapsulate hdg/lat/lon source, so that the ND may also display AI/MP aircraft in a pilot-view at some point (aka stress-testing)
|
||||
# TODO: this predates aircraftpos.controller (MapStructure) should probably be unified to some degree ...
|
||||
|
||||
var wxr_live_tree = "/instrumentation/wxr";
|
||||
|
||||
var NDSourceDriver = {};
|
||||
NDSourceDriver.new = func {
|
||||
var m = {parents:[NDSourceDriver]};
|
||||
|
@ -78,6 +80,10 @@ var default_switches = {
|
|||
'toggle_true_north': {path: '/mfd/true-north', value:0, type:'BOOL'},
|
||||
'toggle_rangearc': {path: '/mfd/rangearc', value:0, type:'BOOL'},
|
||||
'toggle_track_heading':{path: '/trk-selected', value:0, type:'BOOL'},
|
||||
'toggle_weather_live': {path: '/mfd/wxr-live-enabled', value: 0, type: 'BOOL'},
|
||||
'toggle_chrono': {path: '/inputs/CHRONO', value: 0, type: 'INT'},
|
||||
'toggle_xtrk_error': {path: '/mfd/xtrk-error', value: 0, type: 'BOOL'},
|
||||
'toggle_trk_line': {path: '/mfd/trk-line', value: 0, type: 'BOOL'},
|
||||
};
|
||||
|
||||
##
|
||||
|
@ -118,6 +124,10 @@ var NavDisplay = {
|
|||
# listeners for cockpit switches
|
||||
listen_switch: func(s,c) {
|
||||
# print("event setup for: ", id(c));
|
||||
if (!contains(me.efis_switches, s)) {
|
||||
print('EFIS Switch not defined: '~ s);
|
||||
return;
|
||||
}
|
||||
me.listen( me.get_full_switch_path(s), func {
|
||||
# print("listen_switch triggered:", s, " callback id:", id(c) );
|
||||
c();
|
||||
|
@ -133,12 +143,23 @@ var NavDisplay = {
|
|||
# helper method for getting configurable cockpit switches (which are usually different in each aircraft)
|
||||
get_switch: func(s) {
|
||||
var switch = me.efis_switches[s];
|
||||
if(switch == nil) return nil;
|
||||
var path = me.efis_path ~ switch.path ;
|
||||
#print(s,":Getting switch prop:", path);
|
||||
|
||||
return getprop( path );
|
||||
},
|
||||
|
||||
# helper method for setting configurable cockpit switches (which are usually different in each aircraft)
|
||||
set_switch: func(s, v) {
|
||||
var switch = me.efis_switches[s];
|
||||
if(switch == nil) return nil;
|
||||
var path = me.efis_path ~ switch.path ;
|
||||
#print(s,":Getting switch prop:", path);
|
||||
|
||||
setprop( path, v );
|
||||
},
|
||||
|
||||
# for creating NDs that are driven by AI traffic instead of the main aircraft (generalization rocks!)
|
||||
connectAI: func(source=nil) {
|
||||
me.aircraft_source = {
|
||||
|
@ -159,6 +180,12 @@ var NavDisplay = {
|
|||
NavDisplay.id +=1;
|
||||
var m = { parents : [NavDisplay]};
|
||||
|
||||
var df_toggles = keys(default_switches);
|
||||
foreach(var toggle_name; df_toggles){
|
||||
if(!contains(switches, toggle_name))
|
||||
switches[toggle_name] = default_switches[toggle_name];
|
||||
}
|
||||
|
||||
m.inited = 0;
|
||||
|
||||
m.timers=[];
|
||||
|
@ -166,6 +193,7 @@ var NavDisplay = {
|
|||
m.aircraft_source = NDSourceDriver.new(); # uses the main aircraft as the driver/source (speeds, position, heading)
|
||||
|
||||
m.nd_style = NDStyles[style]; # look up ND specific stuff (file names etc)
|
||||
m.style_name = style;
|
||||
|
||||
m.radio_list=["instrumentation/comm/frequencies","instrumentation/comm[1]/frequencies",
|
||||
"instrumentation/nav/frequencies", "instrumentation/nav[1]/frequencies"];
|
||||
|
@ -197,7 +225,7 @@ var NavDisplay = {
|
|||
m.mk_minimums = props.globals.getNode("instrumentation/mk-viii/inputs/arinc429/decision-height");
|
||||
|
||||
# TODO: these are switches, can be unified with switch handling hash above (eventually):
|
||||
m.nd_plan_wpt = m.efis.initNode("inputs/plan-wpt-index", 0, "INT"); # not yet in switches hash
|
||||
m.nd_plan_wpt = m.efis.initNode("inputs/plan-wpt-index", -1, "INT"); # not yet in switches hash
|
||||
|
||||
###
|
||||
# initialize all switches based on the defaults specified in the switch hash
|
||||
|
@ -212,13 +240,28 @@ var NavDisplay = {
|
|||
|
||||
return m;
|
||||
},
|
||||
newMFD: func(canvas_group, parent=nil, options=nil, update_time=0.05)
|
||||
newMFD: func(canvas_group, parent=nil, nd_options=nil, update_time=0.05)
|
||||
{
|
||||
if (me.inited) die("MFD already was added to scene");
|
||||
me.inited = 1;
|
||||
me.range_dependant_layers = [];
|
||||
me.always_update_layers = {};
|
||||
me.update_timer = maketimer(update_time, func me.update() );
|
||||
me.nd = canvas_group;
|
||||
me.canvas_handle = parent;
|
||||
me.df_options = nil;
|
||||
if (contains(me.nd_style, 'options'))
|
||||
me.df_options = me.nd_style.options;
|
||||
nd_options = default_hash(nd_options, me.df_options);
|
||||
me.options = nd_options;
|
||||
me.route_driver = nil;
|
||||
if (contains(me.options, 'route_driver')) {
|
||||
me.route_driver = me.options.route_driver;
|
||||
}
|
||||
elsif (contains(me.options, 'defaults')) {
|
||||
if(contains(me.options.defaults, 'route_driver'))
|
||||
me.route_driver = me.options.defaults.route_driver;
|
||||
}
|
||||
|
||||
# load the specified SVG file into the me.nd group and populate all sub groups
|
||||
|
||||
|
@ -246,9 +289,18 @@ var NavDisplay = {
|
|||
"staArrowL","staArrowR","staToL","staFromL","staToR","staFromR"] )
|
||||
me.symbols[element] = me.nd.getElementById(element).updateCenter();
|
||||
|
||||
var map_rect = [124, 1024, 1024, 0];
|
||||
var map_opts = me.options.map;
|
||||
if (map_opts == nil) map_opts = {};
|
||||
if (typeof(map_opts.rect) == 'vector')
|
||||
map_rect = map_opts.rect;
|
||||
map_rect = join(', ', map_rect);
|
||||
|
||||
me.map = me.nd.createChild("map","map")
|
||||
.set("clip", "rect(124, 1024, 1024, 0)")
|
||||
.set("clip", map_rect)
|
||||
.set("screen-range", 700);
|
||||
var z_idx = map_opts['z-index'];
|
||||
if (z_idx != nil) me.map.set('z-index', z_idx);
|
||||
|
||||
me.update_sub(); # init some map properties based on switches
|
||||
|
||||
|
@ -323,6 +375,7 @@ var NavDisplay = {
|
|||
|
||||
me.layers={}; # storage container for all ND specific layers
|
||||
# look up all required layers as specified per the NDStyle hash and do the initial setup for event handling
|
||||
var default_opts = me.options != nil and contains(me.options, 'defaults') ? me.options.defaults : nil;
|
||||
foreach(var layer; me.nd_style.layers) {
|
||||
if(layer['disabled']) continue; # skip this layer
|
||||
#print("newMFD(): Setting up ND layer:", layer.name);
|
||||
|
@ -332,16 +385,33 @@ var NavDisplay = {
|
|||
the_layer = me.layers[layer.name] = canvas.MAP_LAYERS[layer.name].new( me.map, layer.name, controller );
|
||||
else {
|
||||
printlog(_MP_dbg_lvl, "Setting up MapStructure-based layer for ND, name:", layer.name);
|
||||
var opt = options != nil and options[layer.name] != nil ? options[layer.name] :nil;
|
||||
# print("Options is: ", opt!=nil?"enabled":"disabled");
|
||||
var opt = me.options != nil and me.options[layer.name] != nil ? me.options[layer.name] : nil;
|
||||
if (opt == nil and contains(layer, 'options'))
|
||||
opt = layer.options;
|
||||
if (opt != nil and default_opts != nil)
|
||||
opt = default_hash(opt, default_opts);
|
||||
#elsif(default_opts != nil)
|
||||
# opt = default_opts;
|
||||
var style = nil;
|
||||
if(contains(layer, 'style'))
|
||||
style = layer.style;
|
||||
#print("Options is: ", opt!=nil?"enabled":"disabled");
|
||||
#debug.dump(opt);
|
||||
me.map.addLayer(
|
||||
factory: canvas.SymbolLayer,
|
||||
type_arg: layer.name,
|
||||
options:opt,
|
||||
opts: opt,
|
||||
visible:0,
|
||||
style: style,
|
||||
priority: layer['z-index']
|
||||
);
|
||||
the_layer = me.layers[layer.name] = me.map.getLayer(layer.name);
|
||||
if(opt != nil and contains(opt, 'range_dependant')){
|
||||
if(opt.range_dependant)
|
||||
append(me.range_dependant_layers, the_layer);
|
||||
}
|
||||
if(contains(layer, 'always_update'))
|
||||
me.always_update_layers[layer.name] = layer.always_update;
|
||||
if (1) (func {
|
||||
var l = layer;
|
||||
var _predicate = l.predicate;
|
||||
|
@ -443,15 +513,28 @@ var NavDisplay = {
|
|||
}
|
||||
|
||||
# First, update the display position of the map
|
||||
var oldRange = me.map.getRange();
|
||||
var pos = {
|
||||
lat: nil, lon: nil,
|
||||
alt: nil, hdg: nil,
|
||||
range: nil,
|
||||
};
|
||||
# reposition the map, change heading & range:
|
||||
if(me.in_mode('toggle_display_mode', ['PLAN']) and getprop(me.efis_path ~ "/inputs/plan-wpt-index") >= 0) {
|
||||
pos.lat = getprop("/autopilot/route-manager/route/wp["~getprop(me.efis_path ~ "/inputs/plan-wpt-index")~"]/latitude-deg");
|
||||
pos.lon = getprop("/autopilot/route-manager/route/wp["~getprop(me.efis_path ~ "/inputs/plan-wpt-index")~"]/longitude-deg");
|
||||
var pln_wpt_idx = getprop(me.efis_path ~ "/inputs/plan-wpt-index");
|
||||
if(me.in_mode('toggle_display_mode', ['PLAN']) and pln_wpt_idx >= 0) {
|
||||
if(me.route_driver != nil){
|
||||
var wp = me.route_driver.getPlanModeWP(pln_wpt_idx);
|
||||
if(wp != nil){
|
||||
pos.lat = wp.wp_lat;
|
||||
pos.lon = wp.wp_lon;
|
||||
} else {
|
||||
pos.lat = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/latitude-deg");
|
||||
pos.lon = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/longitude-deg");
|
||||
}
|
||||
} else {
|
||||
pos.lat = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/latitude-deg");
|
||||
pos.lon = getprop("/autopilot/route-manager/route/wp["~pln_wpt_idx~"]/longitude-deg");
|
||||
}
|
||||
} else {
|
||||
pos.lat = userLat;
|
||||
pos.lon = userLon;
|
||||
|
@ -463,7 +546,14 @@ var NavDisplay = {
|
|||
pos.range = me.rangeNm(); # avoid this here, use a listener instead
|
||||
pos.hdg = userHdgTrkTru;
|
||||
}
|
||||
if(me.options != nil and (var pos_callback = me.options['position_callback']) != nil)
|
||||
pos_callback(me, pos);
|
||||
call(me.map.setPos, [pos.lat, pos.lon], me.map, pos);
|
||||
if(pos.range != oldRange){
|
||||
foreach(l; me.range_dependant_layers){
|
||||
l.update();
|
||||
}
|
||||
}
|
||||
},
|
||||
# each model should keep track of when it last got updated, using current lat/lon
|
||||
# in update(), we can then check if the aircraft has traveled more than 0.5-1 nm (depending on selected range)
|
||||
|
@ -472,6 +562,12 @@ var NavDisplay = {
|
|||
update: func() # FIXME: This stuff is still too aircraft specific, cannot easily be reused by other aircraft
|
||||
{
|
||||
var _time = systime();
|
||||
# Disables WXR Live if it's not enabled. The toggle_weather_live should be common to all
|
||||
# ND instances.
|
||||
var wxr_live_enabled = getprop(wxr_live_tree~'/enabled');
|
||||
if(wxr_live_enabled == nil or wxr_live_enabled == '')
|
||||
wxr_live_enabled = 0;
|
||||
me.set_switch('toggle_weather_live', wxr_live_enabled);
|
||||
|
||||
call(me.update_sub, nil, nil, caller(0)[0]); # call this in the same namespace to "steal" its variables
|
||||
|
||||
|
@ -481,17 +577,26 @@ var NavDisplay = {
|
|||
} else {
|
||||
# TODO: ugly list here
|
||||
# FIXME: use a VOLATILE layer helper here that handles TFC, APS, WXR etc ?
|
||||
me.map.update(func(layer) (var n=layer.type) == "TFC" or n == "APS");
|
||||
var update_layers = me.always_update_layers;
|
||||
me.map.update(func(layer) contains(update_layers, layer.type));
|
||||
}
|
||||
|
||||
# Other symbol update
|
||||
# TODO: should be refactored!
|
||||
if(me.in_mode('toggle_display_mode', ['PLAN']))
|
||||
me.map.setTranslation(512,512);
|
||||
elsif(me.get_switch('toggle_centered'))
|
||||
me.map.setTranslation(512,565);
|
||||
else
|
||||
me.map.setTranslation(512,824);
|
||||
var translation_callback = nil;
|
||||
if(me.options != nil)
|
||||
translation_callback = me.options['translation_callback'];
|
||||
if(typeof(translation_callback) == 'func'){
|
||||
var trsl = translation_callback(me);
|
||||
me.map.setTranslation(trsl.x, trsl.y);
|
||||
} else {
|
||||
if(me.in_mode('toggle_display_mode', ['PLAN']))
|
||||
me.map.setTranslation(512,512);
|
||||
elsif(me.get_switch('toggle_centered'))
|
||||
me.map.setTranslation(512,565);
|
||||
else
|
||||
me.map.setTranslation(512,824);
|
||||
}
|
||||
|
||||
if(me.get_switch('toggle_rh_vor_adf') == 1) {
|
||||
me.symbols.vorR.setText("VOR R");
|
||||
|
|