diff --git a/Models/Instruments/ND/canvas/framework/canvas.nas b/Models/Instruments/ND/canvas/framework/canvas.nas index 402dff60..7dc6cf73 100644 --- a/Models/Instruments/ND/canvas/framework/canvas.nas +++ b/Models/Instruments/ND/canvas/framework/canvas.nas @@ -307,3 +307,70 @@ canvas.LineSymbol.draw = func() { me.callback("draw_after"); }; +# RacetrackSymbol + +canvas.RacetrackSymbol.new = func(group, layer, model, controller=nil) { + if (me == nil) __die("Need me reference for RacetrackSymbol.new()"); + if (typeof(model) != "vector") { + if(typeof(model) == "hash"){ + if(!contains(model, "path")) + canvas.__die("RacetrackSymbol.new(): model hash requires path"); + } + else canvas.__die("RacetrackSymbol.new(): need a vector of points or a hash"); + } + var m = { + parents: [me], + group: group, + layer: layer, + model: model, + controller: controller == nil ? me.df_controller : controller, + element: group.createChild( + "path", me.element_id + ), + }; + append(m.parents, m.element); + canvas.Symbol._new(m); + + m.init(); + return m; +}; + # Non-static: +canvas.RacetrackSymbol.draw = func() { + me.callback("draw_before"); + if (!me.needs_update) return; + #logprint(_MP_dbg_lvl, "redrawing a RacetrackSymbol "~me.layer.type); + me.element.reset(); + var cmds = []; + var coords = []; + var cmd = canvas.Path.VG_MOVE_TO; + var path = me.model; + if(typeof(path) == "hash"){ + path = me.model.path; + if(path == nil) + canvas.__die("RacetrackSymbol 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); + if (m[0] == 'R') cmd = canvas.Path.arcSmallCWTo; + else if (m[0] == 'L') cmd = canvas.Path.arcSmallCCWTo; + else cmd = canvas.Path.VG_LINE_TO; + } else { + cmd = canvas.Path.VG_MOVE_TO; + } + } + + # close racetrack + var (lat,lon) = me.controller.getpos(path[0]); + append(coords,"N"~lat); + append(coords,"E"~lon); + append(cmds,cmd); + + me.element.setDataGeo(cmds, coords); + me.element.update(); # this doesn"t help with flickering, it seems + me.callback("draw_after"); +}; + diff --git a/Models/Instruments/ND/canvas/map/HOLD.lcontroller b/Models/Instruments/ND/canvas/map/HOLD.lcontroller new file mode 100644 index 00000000..6189d87d --- /dev/null +++ b/Models/Instruments/ND/canvas/map/HOLD.lcontroller @@ -0,0 +1,91 @@ +# See: http://wiki.flightgear.org/MapStructure +# TODO: this layer doesn't make sense to support for AI/MP traffic, because we don't currently have access to flightplan/routing info +# that also applies to other layers like WPT or even navaid layers that handle station tuning based on local radio settings +# +# Class things: +var name = 'HOLD'; +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 + active_node: "/FMGC/flightplan[2]/active", + #current_wp_node: "/FMGC/flightplan[2]/current-wp", + #wp_num: "/FMGC/flightplan[2]/num", + display_inactive_rte: 0 + } +}); +var new = func(layer) { + var m = { + parents: [__self__], + layer: layer, + map: layer.map, + 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(); + var driver = opt_member(m.layer.options, 'route_driver'); + if(driver == nil){ + driver = A3XXRouteDriver.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 last_result = []; + +var searchCmd = func { + # FIXME: do we return the active route even if it isn't active? + logprint(_MP_dbg_lvl, "Running query: ", name); + var plans = []; + var driver = me.route_driver; + if(!driver.shouldUpdate()) return me.last_result; + driver.update(); + # http://wiki.flightgear.org/Nasal_Flightplan + 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 = 'active'; + if (!getprop(me.layer.options.active_node) and + type == 'active' and + !me.layer.options.display_inactive_rte) fpSize = 0; + var coords = []; + #var hold_wp = me.layer.options.hold_wp; + var path = nil; + if (getprop(me.layer.options.hold_wp) != nil) { + var pdir = (getprop(me.layer.options.hold_direction) == "Right") ? 'R' : 'L'; + for (var a = 0; a<6; a += 1) { + var point = props.globals.getNode(me.layer.options.points_node~'['~a~']'); + path = [(a==2 or a==5) ? '' : pdir, {lon:point.lon, lat:point.lat}]; + coords ~= path; + } + } + append(plans, { + id: type, + #name: type, + type: type, + path: coords, + #size: fpSize, + equals: func(o){ + me.id == o.id# and me.size == o.size + } + }); + } + me.last_result = plans; + return plans; +}; \ No newline at end of file diff --git a/Models/Instruments/ND/canvas/map/HOLD.symbol b/Models/Instruments/ND/canvas/map/HOLD.symbol new file mode 100644 index 00000000..15dfa1ed --- /dev/null +++ b/Models/Instruments/ND/canvas/map/HOLD.symbol @@ -0,0 +1,46 @@ +# See: http://wiki.flightgear.org/MapStructure + +# Class things: +var name = 'HOLD'; +var parents = [RacetrackSymbol]; +var __self__ = caller(0)[0]; +RacetrackSymbol.makeinstance( name, __self__ ); + +SymbolLayer.get(name).df_style = { # style to use by default + line_width: 5, + color: [1,0,1] +}; + +var getLineStyle = func(property, df_val){ + var type = nil; + if(typeof(me.model) == 'hash'){ + type = me.model.type; + } + if(type != nil and type != 'active'){ + 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(); +}; + +#var draw = func { +# me.setRouteStyle(); +#}; + diff --git a/Models/Instruments/ND/canvas/style.nas b/Models/Instruments/ND/canvas/style.nas index 7f4579f9..dd880013 100644 --- a/Models/Instruments/ND/canvas/style.nas +++ b/Models/Instruments/ND/canvas/style.nas @@ -459,12 +459,13 @@ canvas.NDStyles["Airbus"] = { } }, options: { - hold_node: "/flight-management/hold", - hold_init: "flight-management/hold/init", - points_node: "/flight-management/hold/points", - first_point_node: "/flight-management/hold/points/point/lat", - hold_wp: "/flight-management/hold/wp", - hold_wp_idx: "/flight-management/hold/wp_id", + hold_node: "/autopilot/hold/", + hold_init: "/autopilot/hold/init", #NOT EXISTS?? + hold_direction: "/autopilot/hold/hold-direction" + points_node: "autopilot/auto-hold/point", + first_point_node: "autopilot/hold/entry", #CHECKME + hold_wp: "autopilot/hold/fix", + #hold_wp_idx: "autopilot/hold/wp_id", range_dependant: 1, listen: [ "first_point_node",