diff --git a/Aircraft/Instruments-3d/GPSmap196/animation.nas b/Aircraft/Instruments-3d/GPSmap196/animation.nas new file mode 100644 index 0000000..eaeda82 --- /dev/null +++ b/Aircraft/Instruments-3d/GPSmap196/animation.nas @@ -0,0 +1 @@ +print("Loading animation.nas"); diff --git a/Aircraft/Instruments-3d/GPSmap196/gpsmap196.nas b/Aircraft/Instruments-3d/GPSmap196/gpsmap196.nas index 27088bc..7bde67f 100644 --- a/Aircraft/Instruments-3d/GPSmap196/gpsmap196.nas +++ b/Aircraft/Instruments-3d/GPSmap196/gpsmap196.nas @@ -1,48 +1,83 @@ - - +## +# this is where we will handle all animations for instruments through properties & timers +# (yet to come) +# NOTE: this will file will be moved into $FG_ROOT/Nasal/canvas at some point +io.include("animation.nas"); + +### +# helpers for creating a MFD instrument with pages, modes, buttons etc +# NOTE: this will file will be moved into $FG_ROOT/Nasal/canvas at some point +io.include("mfd.nas"); + +## +# the setup of the various pages supported by this device +# +io.include("gpsmap196.pages"); + + +## +# top-level instrument class +# var GPSmap196 = { id:0, ############ - new: func(placement='gps196.screen') { - print("Load Garmin GPSmap196 canvas"); + new: func(placement='gps196.screen', name='GPSmap196-screen') { + print("Loading Garmin GPSmap196 canvas"); m = { parents : [GPSmap196] }; + m.buttons = {}; - m.pages = {panel:nil, map:nil, route:nil, position:nil}; m.gmt = props.globals.getNode("sim/time/gmt"); m.node = props.globals.initNode("/instrumentation/gps196",GPSmap196.id+=1); m.selectedPage = m.node.initNode("selected-page", 0, "INT"); + m.gpsmap196Screen = canvas.new({ + "name": name, + "size": [512, 512], # TODO: make configurable via ctor + "view": [320, 240], # TODO: make configurable via ctor + "mipmapping": 1 + }); + + m.gpsmap196Screen.addPlacement({"node": placement}); + m.root = m.gpsmap196Screen.createGroup(); + + # set up a page manager class for managing all our pages + m.page_mgr = MFDPageMgr.new( root:m.root ); + + ## initialize all button properties var buttons = [ 'rocker-up', 'button-in', 'button-dto', 'button-out', 'button-menu', 'button-nrst', 'button-page', 'button-quit', 'button-down', 'rocker-left', 'button-power', 'rocker-right', 'button-enter' ]; - # to access, use: m.buttons['rocker-up'] - foreach(var btn; buttons) - m.buttons[btn] = m.node.initNode("inputs/"~btn, 0, "BOOL"); + # to access, use e.g.: me.buttons['rocker-up'] + foreach(var btn; buttons) { + var p = m.buttons[btn] = m.node.initNode("inputs/"~btn, 0, "BOOL"); + # now set up a listener for each button so that the page manager gets notified for event handling + setlistener(p, m.page_mgr.makeEventHandler(btn) ) + } - m.gpsmap196Screen = canvas.new({ - "name": "GPSmap196-screen", - "size": [512, 512], - "view": [320, 240], - "mipmapping": 1 - }); - m.gpsmap196Screen.addPlacement({"node": placement}); - m.root = m.gpsmap196Screen.createGroup(); + # now add a few pages to the page manager, using a list with hashes containing a name and the class implementing the page + foreach(var page; [ + # you can uncomment these to add other pages (see gpsmap196.pages) + #{name:'page-position', class:MFDPositionPage}, + #{name:'page-route', class:MFDRoutePage}, + {name:'page-map', class:MFDMapPage}, + {name:'page-panel', class:MFDPanelPage}] ) # add new pages here (class names in gpsmap196.pages) + m.page_mgr.registerPage(page.name, page.class ); + + # set starting/main page + m.page_mgr.setActivePage("page-map"); m.timers = []; - m.initMap(); - m.initPanel(); -if(0){ - m.initRoute(); - m.initPosition(); -} - append( m.timers, var update_timer=maketimer(0.1, func m.update()) ); + +if(0) { + append( m.timers, var update_timer=maketimer(0.85, func m.update()) ); update_timer.start(); +} return m; }, @@ -51,79 +86,19 @@ if(0){ del: func { foreach(var t; me.timers) { t.stop(); - t=nil; } + me.timers = nil; print("GPSmap196: cleanup finished"); }, ############ - initRoute: func() { - canvas.parsesvg(var data = me.root.createChild("group", "page-route"), 'Aircraft/Instruments-3d/GPSmap196/pages/page-route.svg'); - me.pages.route = data; - data.hide(); - }, - - ############ - initPosition: func() { - canvas.parsesvg(var data = me.root.createChild("group", "page-position"), 'Aircraft/Instruments-3d/GPSmap196/pages/page-position.svg'); - me.pages.position = data; - data.hide(); - }, - - ############ - initPanel: func() { - canvas.parsesvg(var data = me.root.createChild("group", "page-panel"), 'Aircraft/Instruments-3d/GPSmap196/pages/page-panel.svg'); - me.pages.panel = data; - data.hide(); - }, - - ############ - initMap:func() { - me.pages.map = me.root.createChild("map").hide(); - me.pages.map.setController("Aircraft position"); - me.pages.map.setRange(10); - - me.pages.map.setTranslation( - me.gpsmap196Screen.get("view[0]")/2, - me.gpsmap196Screen.get("view[1]")/2 - ); - var style = {scale_factor:0.3, line_width:2, animation_test:0, color_default:[1,0,0], color_tuned:[0,1,1]}; - var r = func(name,vis=1,zindex=nil) return caller(0)[0]; - foreach(var type; [r('DME',0),r('APT'), ] ) - me.pages.map.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: type.zindex,style:style); - - canvas.parsesvg( var symbol=me.pages.map.createChild("group","airplane-symbol"), 'Nasal/canvas/map/boeingAirplane.svg'); - symbol.setScale( 0.25 ); - }, - - ############ update: func() { - - if(me.buttons['button-page'].getBoolValue()){ - me.selectedPage.setIntValue( me.selectedPage.getValue() + 1 ); - if(me.selectedPage.getValue() > 3) me.selectedPage.setIntValue(0); - } - - me.pages.map.hide(); - me.pages.panel.hide(); -if(0){ - me.pages.route.hide(); - me.pages.position.hide(); -} - - if(me.selectedPage.getValue() == 0) - me.pages.map.show(); - elsif(me.selectedPage.getValue() == 1) - me.pages.panel.show(); -# elsif(me.selectedPage.getValue() == 2) -# me.pages.route.show(); -# elsif(me.selectedPage.getValue() == 3) -# me.pages.position.show(); - + print("no longer used...."); } }; +# FIXME: handle reset/re-init setlistener("sim/signals/fdm-initialized", func() { gpsmap196Canvas = GPSmap196.new(); }); diff --git a/Aircraft/Instruments-3d/GPSmap196/gpsmap196.pages b/Aircraft/Instruments-3d/GPSmap196/gpsmap196.pages new file mode 100644 index 0000000..57c681f --- /dev/null +++ b/Aircraft/Instruments-3d/GPSmap196/gpsmap196.pages @@ -0,0 +1,109 @@ +## +# this file contains all MFD pages for the gpsmap196 +# for generic MFD functionality, please extend mfd.nas directly +# animations should not be handled here, see animation.nas instead + +var dummy_event_handler = func return func(event) { + print(me.page," event received of type:", event); +}; + + +## +# a MFD position page +var MFDPositionPage = { + new: func(group,page,mgr) { + return { manager:mgr, + parents: [MFDPositionPage, MFDPage.new( + root:group, + page:page, + filename:'Aircraft/Instruments-3d/GPSmap196/page-position.svg'), + MFDPositionPage], + }; + }, # new + handleEvent: dummy_event_handler(), +}; + + +## +# a MFD route page +var MFDRoutePage = { + new: func(group,page,mgr) { + return {manager:mgr, + parents: [MFDRoutePage, MFDPage.new( + root:group, + page:page, + filename:'Aircraft/Instruments-3d/GPSmap196/pages/page-route.svg')], + }; + }, # new + + handleEvent: dummy_event_handler(), +}; + + +## +# a MFD panel page +var MFDPanelPage = { + new: func(group,page, mgr) { + return { manager: mgr, + parents: [MFDPanelPage, MFDPage.new( + root:group, + page:page, + filename:'Aircraft/Instruments-3d/GPSmap196/pages/page-panel.svg')], + }; + }, # new + + handleEvent: func(event) { # dummy_event_handler(), + print("Panel page event triggered:", event); + + # NOTE: this is prepared to be fully replaced, but it's better than the old code + if (event == 'button-page') + me.manager.setActivePage('page-map'); + + },# handleEvent +}; + +## +# a MFD page for mapping +# this uses the MapStructure framework, so not a single SVG file here +# +var MFDMapPage = { + new: func(group, page, mgr) { + var m = {parents:[ MFDMapPage, MFDPage ]}; + + var map = group.createChild("map").hide(); + map.setController("Aircraft position"); + map.setRange(10); + + # FIXME + map.setTranslation( + 320 /2, # me.gpsmap196Screen.get("view[0]")/2, + 240 / 2 # me.gpsmap196Screen.get("view[1]")/2 + ); + # styling + var style = { scale_factor:0.3, line_width:2, animation_test:0, + color_default:[1,0,0], color_tuned:[0,1,1]}; + var r = func(name,vis=1,zindex=nil) return caller(0)[0]; + foreach(var type; [r('DME',0),r('VOR'), ] ) + map.addLayer( factory: canvas.SymbolLayer, + type_arg: type.name, + visible: type.vis, + priority: type.zindex, + style:style); + m.page = page; + m.group = map; + m.manager = mgr; + print("Map setup completed"); + return m; # ?? + }, + + handleEvent: func(event) { + print("Panel page event triggered:", event); + + # NOTE: this is prepared to be fully replaced, but it's better than the old code + if (event == 'button-page') + me.manager.setActivePage('page-panel'); + + }, # handleEvent +}; + + diff --git a/Aircraft/Instruments-3d/GPSmap196/gpsmap196.xml b/Aircraft/Instruments-3d/GPSmap196/gpsmap196.xml index 7267326..f53989a 100644 --- a/Aircraft/Instruments-3d/GPSmap196/gpsmap196.xml +++ b/Aircraft/Instruments-3d/GPSmap196/gpsmap196.xml @@ -153,6 +153,7 @@ instrumentation/gps196/inputs/button-page true + diff --git a/Aircraft/Instruments-3d/GPSmap196/mfd.nas b/Aircraft/Instruments-3d/GPSmap196/mfd.nas new file mode 100644 index 0000000..9d6604e --- /dev/null +++ b/Aircraft/Instruments-3d/GPSmap196/mfd.nas @@ -0,0 +1,95 @@ +## +# helpers for creating canvas-based multi-function-displays (MFDs) +# +# NOTE: this file should NOT contain anything that is specific to a single device +# move device-specific code into gpsmap196.nas, edit gpsmap196.pages to extend pages +# +# TODO: keep on extending this for instruments/frameworks like: +# +# - navdisplay.mfd +# - Avidyne/Entegra (extra500) +# - kln89 +# - Primus G1000 +# +var initPage = func(group, page, filename) { + canvas.parsesvg(var new_page = group.createChild("group", page), filename); + new_page.hide(); + return new_page; +}; + + +### +# MFD page helper class,needs to be implemented by all pages +# currently assumes that each page is SVG based (requires filenames) +var MFDPage = { + new: func(root, page, filename) { + var m = {parents:[MFDPage]}; + m.page = page; + m.group = initPage(root, page, filename); # FIXME + return m; + }, + hide: func me.group.hide(), + show: func me.group.show(), + + handleEvent: func die("abstract handleEvent() method not yet implemented by sub-class:",me.page), +}; + + + +## +# manages MFD pages +# TODO: add button handling here, along with event management +var MFDPageMgr = { + new: func(root) { + var m ={parents:[MFDPageMgr]}; + m.active=nil; + m.pagelist = []; + m.pages = {}; + m.listeners = []; + m.root = root; + return m; + }, + del: func { + foreach(var l; me.listeners) + removelistener(l); + }, + # FIXME: this is just to support all those button listeners for now ... + # will replace it sooner or later with a helper class for managing buttons/keys + registerEvent: func (node) { + append(me.listeners, setlistener(node, func me.handleEvents() )); + }, + registerPage: func(name, class) { + # call the constructor for the class to create a new page + append(me.pagelist, me.pages[name]=class.new(me.root, name, me)); + # initialize if needed + if (typeof(me.active) == nil) me.active=name; + }, + nextPage: func { + }, + prevPage: func { + + }, + setActivePage: func(name) { + # hide the currently active page + if (me.active and (var curr=me.pages[me.active]) != nil) curr.hide(); + # set the new active page + me.active=name; + # and show it + me.update(); + }, + getActivePageName: func return me.active, + getActivePage: func return me.pages[me.active], + update: func me.pages[me.active].show(), + + # TODO: we can filter events here to process them via the page manager + # and not pass them through onto the page ... + makeEventHandler: func(event) { + return func { + print(event, ":Active page:", me.getActivePageName()); + # dispatch events to active page + me.getActivePage().handleEvent(event); + } + }, +}; + + diff --git a/Aircraft/Instruments-3d/GPSmap196/widget/gpsmap196-widget.nas b/Aircraft/Instruments-3d/GPSmap196/widget/gpsmap196-widget.nas index 4ec98bd..0f13fe4 100644 --- a/Aircraft/Instruments-3d/GPSmap196/widget/gpsmap196-widget.nas +++ b/Aircraft/Instruments-3d/GPSmap196/widget/gpsmap196-widget.nas @@ -28,8 +28,8 @@ canvas.parsesvg(root, "Aircraft/Instruments-3d/GPSmap196/widget/gpsmap196-widget # An helper function who add the event listener for each button var setButtonListener = func(btn, prop) { - root.getElementById(btn).addEventListener("mousedown", func(e) { setprop("instrumentation/gps196/inputs/"~prop, 1); }); - root.getElementById(btn).addEventListener("mouseup", func(e) { setprop("instrumentation/gps196/inputs/"~prop, 0); }); + root.getElementById(btn).addEventListener("click", func(e) { setprop("instrumentation/gps196/inputs/"~prop, 1); }); + # root.getElementById(btn).addEventListener("mouseup", func(e) { setprop("instrumentation/gps196/inputs/"~prop, 0); }); root.getElementById(btn).set("z-index", 11); }