Richard Harrison:
Add generic version of a canvas MFD (based on the F-15) It has a fairly simple class structure and hopefully is reasonably easy to understand; Thorsten's using it on the Shuttle and Hooray mentioned that it'd be a good idea to make it generic. It provides a device, that has pages and a set of buttons. The set of buttons control the page that is selected (i.e. a menu). Each page has its own set of menus. A menu defines a label and a page that is displayed. I intend to document it on the wiki once its added.
This commit is contained in:
parent
def0ee20d4
commit
34315227c1
1 changed files with 240 additions and 0 deletions
240
Nasal/canvas/MFD_Generic.nas
Normal file
240
Nasal/canvas/MFD_Generic.nas
Normal file
|
@ -0,0 +1,240 @@
|
|||
# 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
|
||||
# ---------------------------
|
||||
|
||||
#
|
||||
# Menu Item. There is a list of these for each page changing button per display page
|
||||
# Parameters:
|
||||
# menu_id : page change event id for this menu item. e.g. button number
|
||||
# title : Title Text (for display on the device)
|
||||
# page : Instance of page usually returned from PFD.addPage
|
||||
|
||||
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;
|
||||
},
|
||||
};
|
||||
|
||||
#
|
||||
#
|
||||
# Create a new PFD Page
|
||||
# - related svg
|
||||
# - Title: Page title
|
||||
# - SVG element for the page
|
||||
# - Device to attach the page to
|
||||
|
||||
var PFD_Page = {
|
||||
new : func (svg, title, layer_id, device)
|
||||
{
|
||||
var obj = {parents : [PFD_Page] };
|
||||
obj.title = title;
|
||||
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
|
||||
# make a page that is currenty visible not visible before making a new page visible,
|
||||
# however more than one page could be visible - but only one set of menu buttons can be active
|
||||
# so if two pages are visible (e.g. an overlay) then when the overlay removed it would be necessary
|
||||
# to call setVisible on the base page to ensure that the menus are seutp
|
||||
setVisible : func(vis)
|
||||
{
|
||||
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)
|
||||
{ foreach(var mi; me.menus)
|
||||
{
|
||||
if (mi.menu_id == button_id)
|
||||
{
|
||||
# printf("Page: found button %s, selecting page\n",mi.title);
|
||||
me.device.selectPage(mi.page);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#
|
||||
# Add an item to a menu
|
||||
# Params:
|
||||
# menu button id (that is set in controls/PFD/button-pressed by the model)
|
||||
# title of the menu for the label
|
||||
# page that will be selected when pressed
|
||||
#
|
||||
# The corresponding menu for the selected page will automatically be loaded
|
||||
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
|
||||
{
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
var obj = {parents : [PFD_Device] };
|
||||
obj.svg = svg;
|
||||
obj.current_page = nil;
|
||||
obj.pages = [];
|
||||
obj.buttons = setsize([], num_menu_buttons);
|
||||
|
||||
for(var idx = 0; idx < num_menu_buttons; idx += 1)
|
||||
{
|
||||
var label_name = sprintf(button_prefix~"%d",idx);
|
||||
var msvg = obj.svg.getElementById(label_name);
|
||||
if (msvg == nil)
|
||||
printf("PFD_Device: Failed to load %s",label_name);
|
||||
else
|
||||
{
|
||||
obj.buttons[idx] = msvg;
|
||||
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
|
||||
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)
|
||||
{
|
||||
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
|
||||
printf("PFD_Device: Could not locate page for button ",button_id);
|
||||
}
|
||||
},
|
||||
#
|
||||
#
|
||||
# add a page to the device.
|
||||
# - page title.
|
||||
# - svg element id
|
||||
addPage : func(title, layer_id)
|
||||
{
|
||||
var np = PFD_Page.new(me.svg, title, layer_id, me);
|
||||
append(me.pages, np);
|
||||
np.setVisible(0);
|
||||
return np;
|
||||
},
|
||||
#
|
||||
# manage the update of the currently selected page
|
||||
update : func
|
||||
{
|
||||
if (me.current_page != nil)
|
||||
me.current_page.update();
|
||||
},
|
||||
#
|
||||
# select a page for display.
|
||||
selectPage : func(p)
|
||||
{
|
||||
if (me.current_page != nil)
|
||||
me.current_page.setVisible(0);
|
||||
if (me.buttons != nil)
|
||||
{
|
||||
foreach(var mb ; me.buttons)
|
||||
if (mb != nil)
|
||||
mb.setVisible(0);
|
||||
|
||||
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);
|
||||
me.buttons[mi.menu_id].setVisible(1);
|
||||
}
|
||||
else
|
||||
printf("PFD_device: Menu for button not found. Menu ID '%s'",mi.menu_id);
|
||||
}
|
||||
}
|
||||
p.setVisible(1);
|
||||
me.current_page = p;
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in a new issue