Generic MFD: Add Canvas NavDisplay
This links together the generic MFD and the NavDisplay; it allows a fairly easy method to add a Map page to an MFD device. ---------------------- See: http://wiki.flightgear.org/Canvas_MFD_Framework ---------------------- Instantiate parameters: 1. pfd_device (instance of PFD_Device) 2. instrument display ident (e.g. mfd-map, or mfd-map-left mfd-map-right for multiple displays) - used to map to the property tree 3. layer_id: main layer in the SVG 4. nd_group_ident : group (usually within the main layer) to place the NavDisplay 5. [optional] switches - used to connect the property tree to the nav display. see the canvas nav display. To add a canvas nav display page simply do me.some_page = PFD_NavDisplay.new(me.PFD,"Situation", "mpcd-sit", "ID", "jtids_main");
This commit is contained in:
parent
a6d7af5db6
commit
94334ec5fc
1 changed files with 166 additions and 81 deletions
|
@ -1,18 +1,18 @@
|
|||
# Generic Page switching cockpit display device.
|
||||
# I'm calling this a PFD as im Programmable Function Display.
|
||||
# ---------------------------
|
||||
# See FGAddon/Aircraft/F-15/Nasal/MPCD/MPCD_main.nas for an example usage
|
||||
# ---------------------------
|
||||
# This is but a straightforwards wrapper to provide the core logic that page switching displays require.
|
||||
# Page switching displays
|
||||
# * MFD
|
||||
# * PFD
|
||||
# * FMCS
|
||||
# etc.
|
||||
# Based on F-15 MPCD
|
||||
# ---------------------------
|
||||
# Richard Harrison: 2015-10-17 : rjh@zaretto.com
|
||||
# ---------------------------
|
||||
# I'm calling this a PFD as in Programmable Function Display.
|
||||
# ---------------------------
|
||||
# documentation: see http://wiki.flightgear.org/Canvas_MFD_Framework
|
||||
# See FGAddon/Aircraft/F-15/Nasal/MPCD/MPCD_main.nas for an example usage
|
||||
# ---------------------------
|
||||
# This is but a straightforwards wrapper to provide the core logic that page switching displays require.
|
||||
# Examples of Page switching displays
|
||||
# * MFD
|
||||
# * PFD
|
||||
# * FMCS
|
||||
# * F-15 MPCD
|
||||
|
||||
#
|
||||
# Menu Item. There is a list of these for each page changing button per display page
|
||||
|
@ -21,14 +21,14 @@
|
|||
# title : Title Text (for display on the device)
|
||||
# page : Instance of page usually returned from PFD.addPage
|
||||
|
||||
var PFD_MenuItem = {
|
||||
var PFD_MenuItem =
|
||||
{
|
||||
new : func (menu_id, title, page)
|
||||
{
|
||||
var obj = {parents : [PFD_MenuItem] };
|
||||
obj.page = page;
|
||||
obj.menu_id = menu_id;
|
||||
obj.title = title;
|
||||
# printf("New MenuItem %s,%s,%s",menu_id, title, page);
|
||||
return obj;
|
||||
},
|
||||
};
|
||||
|
@ -41,7 +41,8 @@ var PFD_MenuItem = {
|
|||
# - SVG element for the page
|
||||
# - Device to attach the page to
|
||||
|
||||
var PFD_Page = {
|
||||
var PFD_Page =
|
||||
{
|
||||
new : func (svg, title, layer_id, device)
|
||||
{
|
||||
var obj = {parents : [PFD_Page] };
|
||||
|
@ -49,14 +50,13 @@ var PFD_Page = {
|
|||
obj.device = device;
|
||||
obj.layer_id = layer_id;
|
||||
obj.menus = [];
|
||||
# print("Load page ",title);
|
||||
obj.svg = svg.getElementById(layer_id);
|
||||
if(obj.svg == nil)
|
||||
printf("PFD_Device: Error loading %s: svg layer %s ",title, layer_id);
|
||||
|
||||
return obj;
|
||||
},
|
||||
#
|
||||
|
||||
#
|
||||
# Makes a page visible.
|
||||
# It is the responsibility of the caller to manage the visibility of pages - i.e. to
|
||||
|
@ -68,20 +68,13 @@ var PFD_Page = {
|
|||
{
|
||||
if(me.svg != nil)
|
||||
me.svg.setVisible(vis);
|
||||
# print("Set visible ",me.layer_id);
|
||||
|
||||
if (vis)
|
||||
{
|
||||
me.ondisplay();
|
||||
foreach(mi ; me.menus)
|
||||
{
|
||||
# printf("load menu %s %\n",mi.title, mi);
|
||||
}
|
||||
}
|
||||
else
|
||||
me.offdisplay();
|
||||
},
|
||||
#
|
||||
|
||||
#
|
||||
# Perform action when button is pushed
|
||||
notifyButton : func(button_id)
|
||||
|
@ -89,7 +82,6 @@ var PFD_Page = {
|
|||
{
|
||||
if (mi.menu_id == button_id)
|
||||
{
|
||||
# printf("Page: found button %s, selecting page\n",mi.title);
|
||||
me.device.selectPage(mi.page);
|
||||
break;
|
||||
}
|
||||
|
@ -107,49 +99,52 @@ var PFD_Page = {
|
|||
addMenuItem : func(menu_id, title, page)
|
||||
{
|
||||
var nm = PFD_MenuItem.new(menu_id, title, page);
|
||||
# printf("New menu %s %s on page ", menu_id, title, page.layer_id);
|
||||
append(me.menus, nm);
|
||||
# printf("Page %s: add menu %s [%s]",me.layer_id, menu_id, title);
|
||||
# foreach(mi ; me.menus)
|
||||
# {
|
||||
# printf("--menu %s",mi.title);
|
||||
# }
|
||||
return nm;
|
||||
},
|
||||
|
||||
# base method for update; this can be overriden per page instance to provide update of the
|
||||
# elements on display (e.g. to display updated properties)
|
||||
update : func
|
||||
{
|
||||
},
|
||||
|
||||
#
|
||||
# notify the page that it is being displayed. use to load any static framework or perform one
|
||||
# time initialisation
|
||||
ondisplay : func
|
||||
{
|
||||
},
|
||||
|
||||
#
|
||||
# notify the page that it is going off display; use to clean up any created elements or perform
|
||||
# any other required functions
|
||||
|
||||
offdisplay : func
|
||||
{
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
#
|
||||
# Container device for pages.
|
||||
var PFD_Device =
|
||||
{
|
||||
#
|
||||
# create acontainer device for pages.
|
||||
# - svg is the page elements from the svg.
|
||||
# - num_menu_buttons is the Number of menu buttons; starting from the bottom left then right, then top, then left.
|
||||
# - button prefix (e.g MI_) is the prefix of the labels in the SVG for the menu boxes.
|
||||
new : func(svg, num_menu_buttons, button_prefix)
|
||||
# - _canvas is the canvas group.
|
||||
#NOTE:
|
||||
# This does not actually create the canvas elements, or parse the SVG, that would typically be done in
|
||||
# a higher level class that contains an instance of this class.
|
||||
# see: http://wiki.flightgear.org/Canvas_MFD_Framework
|
||||
new : func(svg, num_menu_buttons, button_prefix, _canvas)
|
||||
{
|
||||
var obj = {parents : [PFD_Device] };
|
||||
obj.svg = svg;
|
||||
obj.canvas = _canvas;
|
||||
obj.current_page = nil;
|
||||
obj.pages = [];
|
||||
obj.page_index = {};
|
||||
obj.buttons = setsize([], num_menu_buttons);
|
||||
|
||||
for(var idx = 0; idx < num_menu_buttons; idx += 1)
|
||||
|
@ -164,18 +159,13 @@ var PFD_Device =
|
|||
obj.buttons[idx].setText(sprintf("M",idx));
|
||||
}
|
||||
}
|
||||
# for(var idx = 0; idx < size(obj.buttons); idx += 1)
|
||||
# {
|
||||
# printf("Button %d %s",idx,obj.buttons[idx]);
|
||||
# }
|
||||
return obj;
|
||||
},
|
||||
#
|
||||
# called when a button is pushed
|
||||
# called when a button is pushed - connecting the property to this method is implemented in the outer class
|
||||
notifyButton : func(button_id)
|
||||
{
|
||||
#
|
||||
#
|
||||
# by convention the buttons we have are 0 based; however externally 0 is used
|
||||
# to indicate no button pushed.
|
||||
if (button_id > 0)
|
||||
|
@ -183,7 +173,6 @@ var PFD_Device =
|
|||
button_id = button_id - 1;
|
||||
if (me.current_page != nil)
|
||||
{
|
||||
# printf("Button routing to %s",me.current_page.title);
|
||||
me.current_page.notifyButton(button_id);
|
||||
}
|
||||
else
|
||||
|
@ -199,6 +188,7 @@ var PFD_Device =
|
|||
{
|
||||
var np = PFD_Page.new(me.svg, title, layer_id, me);
|
||||
append(me.pages, np);
|
||||
me.page_index[layer_id] = np;
|
||||
np.setVisible(0);
|
||||
return np;
|
||||
},
|
||||
|
@ -210,7 +200,8 @@ var PFD_Device =
|
|||
me.current_page.update();
|
||||
},
|
||||
#
|
||||
# select a page for display.
|
||||
# Change to display the selected page.
|
||||
# - the page object method controls the visibility
|
||||
selectPage : func(p)
|
||||
{
|
||||
if (me.current_page != nil)
|
||||
|
@ -223,7 +214,6 @@ var PFD_Device =
|
|||
|
||||
foreach(var mi ; p.menus)
|
||||
{
|
||||
# printf("selectPage: load menu %d %s",mi.menu_id, mi.title);
|
||||
if (me.buttons[mi.menu_id] != nil)
|
||||
{
|
||||
me.buttons[mi.menu_id].setText(mi.title);
|
||||
|
@ -236,5 +226,100 @@ var PFD_Device =
|
|||
p.setVisible(1);
|
||||
me.current_page = p;
|
||||
},
|
||||
#
|
||||
# ensure that the menus are display correctly for the current page.
|
||||
updateMenus : func
|
||||
{
|
||||
foreach(var mi ; me.current_page.menus)
|
||||
{
|
||||
if (me.buttons[mi.menu_id] != nil)
|
||||
{
|
||||
me.buttons[mi.menu_id].setText(mi.title);
|
||||
me.buttons[mi.menu_id].setVisible(1);
|
||||
}
|
||||
else
|
||||
printf("No corresponding item '%s'",mi.menu_id);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var PFD_NavDisplay =
|
||||
{
|
||||
#
|
||||
# Instantiate parameters:
|
||||
# 1. pfd_device (instance of PFD_Device)
|
||||
# 2. instrument display ident (e.g. mfd-map, or mfd-map-left mfd-map-right for multiple displays)
|
||||
# (this is used to map to the property tree)
|
||||
# 3. layer_id: main layer in the SVG
|
||||
# 4. nd_group_ident : group (usually within the main layer) to place the NavDisplay
|
||||
# 5. switches - used to connect the property tree to the nav display. see the canvas nav display
|
||||
# documentation
|
||||
new : func (pfd_device, title, instrument_ident, layer_id, nd_group_ident, switches=nil, map_style="Boeing")
|
||||
{
|
||||
var obj = pfd_device.addPage(title, layer_id);
|
||||
|
||||
# if no switches given then use a default set.
|
||||
if (switches != nil)
|
||||
obj.switches = switches;
|
||||
else
|
||||
obj.switches = {
|
||||
'toggle_range': { path: '/inputs/range-nm', value: 50, type: 'INT' },
|
||||
'toggle_weather': { path: '/inputs/wxr', value: 0, type: 'BOOL' },
|
||||
'toggle_airports': { path: '/inputs/arpt', value: 1, type: 'BOOL' },
|
||||
'toggle_stations': { path: '/inputs/sta', value: 1, type: 'BOOL' },
|
||||
'toggle_waypoints': { path: '/inputs/wpt', value: 1, type: 'BOOL' },
|
||||
'toggle_position': { path: '/inputs/pos', value: 0, type: 'BOOL' },
|
||||
'toggle_data': { path: '/inputs/data', value: 0, type: 'BOOL' },
|
||||
'toggle_terrain': { path: '/inputs/terr', value: 0, type: 'BOOL' },
|
||||
'toggle_traffic': { path: '/inputs/tfc', value: 1, type: 'BOOL' },
|
||||
'toggle_centered': { path: '/inputs/nd-centered', value: 1, type: 'BOOL' },
|
||||
'toggle_lh_vor_adf': { path: '/inputs/lh-vor-adf', value: 1, type: 'INT' },
|
||||
'toggle_rh_vor_adf': { path: '/inputs/rh-vor-adf', value: 1, type: 'INT' },
|
||||
'toggle_display_mode': { path: '/mfd/display-mode', value: 'MAP', type: 'STRING' },
|
||||
'toggle_display_type': { path: '/mfd/display-type', value: 'LCD', type: 'STRING' },
|
||||
'toggle_true_north': { path: '/mfd/true-north', value: 0, type: 'BOOL' },
|
||||
'toggle_rangearc': { path: '/mfd/rangearc', value: 0, type: 'BOOL' },
|
||||
'toggle_track_heading': { path: '/hdg-trk-selected', value: 1, type: 'BOOL' },
|
||||
};
|
||||
|
||||
obj.nd_initialised = 0;
|
||||
obj.nd_placeholder_ident = nd_group_ident;
|
||||
obj.nd_ident = instrument_ident;
|
||||
obj.pfd_device = pfd_device;
|
||||
|
||||
obj.nd_init = func
|
||||
{
|
||||
me.ND = canvas.NavDisplay;
|
||||
if (!me.nd_initialised)
|
||||
{
|
||||
me.nd_initialised = 1;
|
||||
|
||||
me.NDCpt = me.ND.new("instrumentation/"~me.nd_ident, me.switches,map_style);
|
||||
|
||||
me.group = me.pfd_device.svg.getElementById(me.nd_placeholder_ident);
|
||||
me.group.setScale(0.39,0.45);
|
||||
me.group.setTranslation(45,0);
|
||||
me.NDCpt.newMFD(me.group, pfd_device.canvas);
|
||||
}
|
||||
me.NDCpt.update();
|
||||
};
|
||||
#
|
||||
# Method overrides
|
||||
#-----------------------------------------------
|
||||
# Called when the page goes on display - need to delay initialization of the NavDisplay until later (it fails
|
||||
# if done too early).
|
||||
# NOTE: This causes a display "wobble" the first time on display as resizing happens. I've seen similar things
|
||||
# happen on real avionics (when switched on) so it's not necessarily unrealistic -)
|
||||
obj.ondisplay = func
|
||||
{
|
||||
if (!me.nd_initialised)
|
||||
me.nd_init();
|
||||
};
|
||||
#
|
||||
# most updates performed by the canvas nav display directly.
|
||||
obj.update = func
|
||||
{
|
||||
};
|
||||
return obj;
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue