37c005c222
See the clone at https://gitorious.org/fg/canvas-hackers-fgdata/source/topics/canvas-radar:
133 lines
4.6 KiB
Text
133 lines
4.6 KiB
Text
# See: http://wiki.flightgear.org/MapStructure
|
|
# Class things:
|
|
var name = 'VOR';
|
|
var parents = [DotSym];
|
|
var __self__ = caller(0)[0];
|
|
DotSym.makeinstance( name, __self__ );
|
|
|
|
var element_type = "group"; # we want a group, becomes "me.element"
|
|
var icon_vor = nil; # a handle to the cached icon
|
|
var range_vor = nil; # two elements that get drawn when needed
|
|
var radial_vor = nil; # if one is nil, the other has to be nil
|
|
var active = -1;
|
|
|
|
###
|
|
# this function returns a new function that renders the symbol
|
|
# into a canvas group
|
|
# the signature of the first func should contain all customizable
|
|
# parameters (such as color/width etc)
|
|
#
|
|
# you will typically have one such function for each cacheable symbol
|
|
# and only call it once during initialization (once for each cached style/variation)
|
|
# the signature of the 2nd func remains untouched, it's internally used
|
|
#
|
|
# NOTE: callbacks that create symbols for caching MUST render them using a
|
|
# transparent background !!
|
|
#
|
|
var drawVOR = func(color, width=3) return func(group) {
|
|
|
|
# init_calls += 1; # TODO: doing this here is too fragile, this should be done by MapStructure ...
|
|
# if( init_calls >= 2)
|
|
# print("Warning: draw() routine for a cached element has been called more than once, should only happen during reset/reinit");
|
|
|
|
# print("drawing vor");
|
|
var symbol = group.createChild("path")
|
|
.moveTo(-15,0)
|
|
.lineTo(-7.5,12.5)
|
|
.lineTo(7.5,12.5)
|
|
.lineTo(15,0)
|
|
.lineTo(7.5,-12.5)
|
|
.lineTo(-7.5,-12.5)
|
|
.close()
|
|
.setStrokeLineWidth(width)
|
|
.setColor( color );
|
|
|
|
return symbol; # make this explicit, not everybody knows Nasal internals inside/out ...
|
|
};
|
|
|
|
##
|
|
# a vector with pre-created symbols that are cached during initialization
|
|
# this needs to be done for each variation of each symbol, i.e. color/width etc
|
|
# note that scaling should not be done here, likewise for positioning via setGeoPosition()
|
|
#
|
|
# FIXME: We still need to encode styling information as part of the key/name lookup
|
|
# so that the cache entry's name contains styling info, or different maps/layers may
|
|
# overwrite their symbols
|
|
#
|
|
# icon_vor_cache[0] - inactive symbol
|
|
# icon_vor_cache[1] - active symbol
|
|
var icon_vor_cached = [
|
|
SymbolCache32x32.add(
|
|
name: "VOR-INACTIVE",
|
|
callback: drawVOR( color:[0, 0.6, 0.85], width:3 ),
|
|
draw_mode: SymbolCache.DRAW_CENTERED
|
|
),
|
|
SymbolCache32x32.add(
|
|
name: "VOR-ACTIVE",
|
|
callback: drawVOR( color:[0, 1, 0], width:3 ),
|
|
draw_mode: SymbolCache.DRAW_CENTERED
|
|
),
|
|
];
|
|
|
|
##
|
|
# TODO: make this a part of the framework, for use by other layers/symbols etc
|
|
#
|
|
var controller_check = func(layer, controller, arg...) {
|
|
var ret = call(compile("call(layer.controller."~controller~", arg, layer.controller)", "<test>"), arg, var err=[]);
|
|
|
|
if (size(err))
|
|
if (err[0] == "No such member: "~controller)
|
|
print("MapStructure Warning: Required controller not found: ", name, ":", controller);
|
|
else die(err[0]); # rethrow
|
|
|
|
return ret; # nil if not found
|
|
}
|
|
|
|
var draw = func {
|
|
# Init
|
|
if (0 and me.model.id == "SAC") # hack to test isActive() around KSMF
|
|
setprop("instrumentation/nav[0]/frequencies/selected-mhz", me.model.frequency/100);
|
|
var active = controller_check(me.layer, 'isActive', me.model);
|
|
#print(me.model.id,"/", me.model.frequency/100, " isActive:", active);
|
|
if (active != me.active) {
|
|
#print("VOR.symbol: active != me.active: del/render event triggered");
|
|
if (me.icon_vor != nil) me.icon_vor.del();
|
|
# look up the correct symbol from the cache and render it into the group as a raster image
|
|
me.icon_vor = icon_vor_cached[active or 0].render(me.element);
|
|
me.active = active; # update me.active flag
|
|
}
|
|
# Update (also handles non-cached stuff, such as text labels or animations)
|
|
# TODO: we can use a func generator to pre-create the callback/data structure for this
|
|
if (active) {
|
|
if (me.range_vor == nil) {
|
|
# initialize me.range and me.radial_vor
|
|
var rangeNm = me.layer.map.getRange();
|
|
# print("VOR is tuned:", me.model.id);
|
|
var radius = (me.model.range_nm/rangeNm)*345;
|
|
me.range_vor = me.element.createChild("path")
|
|
.moveTo(-radius,0)
|
|
.arcSmallCW(radius,radius,0,2*radius,0)
|
|
.arcSmallCW(radius,radius,0,-2*radius,0)
|
|
.setStrokeLineWidth(3)
|
|
.setStrokeDashArray([5, 15, 5, 15, 5])
|
|
.setColor(0,1,0);
|
|
|
|
var course = me.layer.map.controller.get_tuned_course(me.model.frequency/100);
|
|
me.radial_vor = me.element.createChild("path")
|
|
.moveTo(0,-radius)
|
|
.vert(2*radius)
|
|
.setStrokeLineWidth(3)
|
|
.setStrokeDashArray([15, 5, 15, 5, 15])
|
|
.setColor(0,1,0)
|
|
.setRotation(course*D2R);
|
|
}
|
|
me.range_vor.show();
|
|
me.radial_vor.show();
|
|
} else { # inactive station (not tuned)
|
|
if (me.range_vor != nil) {
|
|
me.range_vor.hide();
|
|
me.radial_vor.hide();
|
|
}
|
|
}
|
|
};
|
|
|