Canvas EFIS framework: Difference between revisions

m
+cat: Electronic flight instrument systems
m (+cat: Electronic flight instrument systems)
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{Stub}}
{{Template:Canvas Navigation}}
{{Template:Canvas Navigation}}


Line 77: Line 75:
* If an animation is triggered only by one property and that property is unlikely to change often, remove the prop / animation from the update loop and use a listener instead. The listener may read other props as needed. A listener does not consume any CPU unless the property it listens to has changed, in which case the listener function is run.
* If an animation is triggered only by one property and that property is unlikely to change often, remove the prop / animation from the update loop and use a listener instead. The listener may read other props as needed. A listener does not consume any CPU unless the property it listens to has changed, in which case the listener function is run.


== Framework documentation ==
== Framework API documentation ==
This section documents the framework classes and their methods.
The following sections document the framework classes and their methods.


=== Class EFIS ===
== Class EFIS ==
This is the top level class which ties together the different parts like display units, sources and cockpit controls.  
This is the top level class which ties together the different parts like display units, sources and cockpit controls.  


==== new() ====
=== new() ===
{{Nasal doc
{{Nasal doc
|syntax = new(display_names, object_names, canvas_settings=nil);
|syntax = new(display_names, object_names, canvas_settings=nil);
Line 95: Line 93:
}}
}}


==== setPowerProp() ====
=== setPowerProp() ===
{{Nasal doc
{{Nasal doc
|syntax = setPowerProp(path);
|syntax = setPowerProp(path);
Line 103: Line 101:
}}
}}


==== setWindowSize() ====
=== setWindowSize() ===
{{Nasal doc
{{Nasal doc
|syntax = setWindowSize(window_size);
|syntax = setWindowSize(window_size);
Line 111: Line 109:
}}
}}


==== setDUPowerProps() ====
=== setDUPowerProps() ===
{{Nasal doc
{{Nasal doc
|syntax = setDUPowerProps(power_props, minimum_power=0);
|syntax = setDUPowerProps(power_props, minimum_power=0);
Line 121: Line 119:
}}
}}


==== addSource() ====
=== addSource() ===
{{Nasal doc
{{Nasal doc
|syntax = addSource(efis_canvas);
|syntax = addSource(efis_canvas);
Line 129: Line 127:
}}
}}


==== addDisplaySwapControl() ====
=== addDisplaySwapControl() ===
{{Nasal doc
{{Nasal doc
|syntax = addDisplaySwapControl(ctrl, mappings, callback=nil);
|syntax = addDisplaySwapControl(ctrl, mappings, callback=nil);
Line 141: Line 139:
}}
}}


==== addSourceSelector() ====
=== addSourceSelector() ===
{{Nasal doc
{{Nasal doc
|syntax = addSourceSelector(selected, target, sources=nil);
|syntax = addSourceSelector(selected, target, sources=nil);
Line 153: Line 151:
}}
}}


==== setDefaultMapping() ====
=== setDefaultMapping() ===
{{Nasal doc
{{Nasal doc
|syntax = setDefaultMapping(mapping);
|syntax = setDefaultMapping(mapping);
Line 161: Line 159:
}}
}}


==== displayWindow() ====
=== displayWindow() ===
{{Nasal doc
{{Nasal doc
|syntax = displayWindow(id);
|syntax = displayWindow(id);
Line 170: Line 168:




=== Class EFISCanvas ===
== Class EFISCanvas ==
EFISCanvas manages a single canvas for you.  
EFISCanvas manages a single canvas for you.  
It offers a bunch of little helpers to make the live of an aircraft developer easier.  
It offers a bunch of little helpers to make the live of an aircraft developer easier.  
These helpers mostly do animation and update stuff on canvas elements in an efficient way.
These helpers mostly do animation and update stuff on canvas elements in an efficient way.


==== new() ====
=== new() ===
{{Nasal doc
{{Nasal doc
|syntax = new(name, svgfile);
|syntax = new(name, svgfile);
Line 185: Line 183:
}}
}}


==== getPath() ====
=== getPath() ===
returns path of canvas
returns path of canvas


==== getCanvas() ====
=== getCanvas() ===
returns canvas instance
returns canvas instance


==== getRoot() ====
=== getRoot() ===
returns root group of the canvas
returns root group of the canvas


==== setUpdateN() ====
=== setUpdateN() ===
{{Nasal doc
{{Nasal doc
|syntax = setUpdateN(node);
|syntax = setUpdateN(node);
Line 202: Line 200:
}}
}}


==== loadsvg() ====
=== loadsvg() ===
{{Nasal doc
{{Nasal doc
|syntax = loadsvg(file);
|syntax = loadsvg(file);
Line 210: Line 208:
}}
}}


==== addUpdateFunction() ====
=== addUpdateFunction() ===
{{Nasal doc
{{Nasal doc
|syntax = addUpdateFunction(f, interval);
|syntax = addUpdateFunction(f, interval);
Line 220: Line 218:
}}
}}


==== startUpdates() ====
=== startUpdates() ===
Start all update timers.
Start all update timers.


==== stopUpdates() ====
=== stopUpdates() ===
Stop all update timers.
Stop all update timers.


==== getInstr() ====
=== getInstr() ===
When updating EFIS displays, there is a need to access properties under /instrumentation very often.
When updating EFIS displays, there is a need to access properties under /instrumentation very often.
To avoid the rather expensive append operator ("~") and property path lookups, you should use this little helper.
To avoid the rather expensive append operator ("~") and property path lookups, you should use this little helper.
Line 244: Line 242:
}}
}}


==== updateTextElement() ====
=== updateTextElement() ===
{{Nasal doc
{{Nasal doc
|syntax = updateTextElement(svgkey, text, color=nil);
|syntax = updateTextElement(svgkey, text, color=nil);
Line 256: Line 254:
}}
}}


==== _updateClip() ====
=== _updateClip() ===
private function that sets clipping for an element, if there is another element with the same name extended by "_clip".
private function that sets clipping for an element, if there is another element with the same name extended by "_clip".


==== Listener factories ====
=== Listener factories ===
{{note|
{{note|
The following listener factories will return a function. The general usage is  
The following listener factories will return a function. The general usage is  
Line 271: Line 269:




===== _makeListener_showHide() =====
==== _makeListener_showHide() ====
{{Nasal doc
{{Nasal doc
|syntax = _makeListener_showHide(svgkey, value=nil);
|syntax = _makeListener_showHide(svgkey, value=nil);
Line 281: Line 279:
}}
}}


===== _makeListener_rotate() =====
==== _makeListener_rotate() ====
{{Nasal doc
{{Nasal doc
|syntax = _makeListener_rotate(svgkey, factors=nil);
|syntax = _makeListener_rotate(svgkey, factors=nil);
Line 291: Line 289:
}}
}}


===== _makeListener_translate() =====
==== _makeListener_translate() ====
{{Nasal doc
{{Nasal doc
|syntax = _makeListener_translate(svgkey, fx, fy);
|syntax = _makeListener_translate(svgkey, fx, fy);
Line 303: Line 301:
}}
}}


===== _makeListener_setColor() =====
==== _makeListener_setColor() ====
{{Nasal doc
{{Nasal doc
|syntax = _makeListener_setColor(svgkey, color_true, color_false);
|syntax = _makeListener_setColor(svgkey, color_true, color_false);
Line 315: Line 313:
}}
}}


===== _makeListener_updateText() =====
==== _makeListener_updateText() ====
{{Nasal doc
{{Nasal doc
|syntax = _makeListener_updateText(svgkey, format="%s", default="");
|syntax = _makeListener_updateText(svgkey, format="%s", default="");
Line 328: Line 326:




=== Methods of class DisplayUnit ===
== Class DisplayUnit ==
This class is used by the EFIS class. DisplayUnit creates and places a canvas to a 3D object specified in new().
This class is used by the EFIS class. DisplayUnit creates and places a canvas to a 3D object specified in new().


==== new() ====
=== new() ===
{{Nasal doc
{{Nasal doc
|syntax = new(name, canvas_settings, screen_obj, parent_obj = nil);
|syntax = new(name, canvas_settings, screen_obj, parent_obj = nil);
Line 345: Line 343:
}}
}}


==== setSource() ====
=== setSource() ===
{{Nasal doc
{{Nasal doc
|syntax = display_unit.setSource(path);
|syntax = display_unit.setSource(path);
Line 353: Line 351:
}}
}}


==== setPowerSource() ====
=== setPowerSource() ===
{{Nasal doc
{{Nasal doc
|syntax = display_unit.setPowerSource(prop, min);
|syntax = display_unit.setPowerSource(prop, min);
Line 367: Line 365:
}}
}}


==== asWindow() ====
=== asWindow() ===
{{Nasal doc
{{Nasal doc
|syntax = display_unit.asWindow(window_size);
|syntax = display_unit.asWindow(window_size);
Line 376: Line 374:




=== EICAS message system ===
== EICAS message system ==
The message system decouples the update of canvas text elements (e.g. message lines) from the handling of messages.
The message system decouples the update of canvas text elements (e.g. message lines) from the handling of messages.
It is configured with the necessary message classes (e.g. warnings, caution messages, status messages) and a list of all possible messages.
It is configured with the necessary message classes (e.g. warnings, caution messages, status messages) and a list of all possible messages.
Line 382: Line 380:
Alternatively, a message can be shown or hidden via the Nasal methods (see also the HOWTO section for examples and best practices).
Alternatively, a message can be shown or hidden via the Nasal methods (see also the HOWTO section for examples and best practices).


==== Methods of class MessageSystem ====
=== Class MessageSystem ===
===== new() =====
==== new() ====
{{Nasal doc
{{Nasal doc
|syntax = new(page_length, prop_path);
|syntax = new(page_length, prop_path);
Line 393: Line 391:
}}
}}


===== setPowerProp() =====
==== setPowerProp() ====
{{Nasal doc
{{Nasal doc
|syntax = setPowerProp(prop_path);
|syntax = setPowerProp(prop_path);
Line 401: Line 399:
}}
}}


===== addMessageClass() =====
==== addMessageClass() ====
{{Nasal doc
{{Nasal doc
|syntax = addMessageClass(class_name, paging, color = nil);
|syntax = addMessageClass(class_name, paging, color = nil);
Line 409: Line 407:
}}
}}


===== addMessages() =====
==== addMessages() ====
{{Nasal doc
{{Nasal doc
|syntax = addMessages(class, messages);
|syntax = addMessages(class, messages);
Line 419: Line 417:
}}
}}


===== addAuralAlerts() =====
{{caution|Use setSoundPath() before addAuralAlert() or addAuralAlerts().}}
==== setSoundPath() ====
{{Nasal doc
|syntax = setSoundPath(path);
|text = Set aural alert configuration hash
|param1 = path
|param1text = Default path for aural alert audio files.
|example1 =
var sound_dir = getprop("sim/aircraft-dir")~"/Sounds/auralalerts/";
myMessageSystem..setSoundPath(sound_dir);
}}
 
==== addAuralAlert() ====
{{Nasal doc
|syntax = addAuralAlert(id, filename, volume=1.0, path=nil);
|text = Add a single aural alert.
|param1 = id
|param1text = Name of aural alert referenced in the message definitions or the auralAlert() method.
|param2 = filename
|param2text = Name of the sound file, e.g. "alert.wav"
|param3 = volume
|param3text = Sound volume for this alert, defaults to 1.0
|param4 = path
|param4text = Optional, override default path set with setSoundPath() before(!).
}}
 
{{note|If you want to store the alerts in a single hash you can pass this to the message system by calling addAuralAlerts(). Note the 's' at the end.}}
 
{{warning|addAuralAlerts() overwrites any previous alert config. If you want to add single alerts with addAuralAlert() this has to be done after calling addAuralAlerts(). }}
 
==== addAuralAlerts() ====
{{Nasal doc
{{Nasal doc
|syntax = addAuralAlerts(alert_hash);
|syntax = addAuralAlerts(alert_hash);
|text = Set aural alert configuration hash
|text = Set aural alert configuration hash
|param1 = alert_hash
|param1 = alert_hash
|param1text = Hash; aural_name: {path: "myAircraft/Sounds", file: "sound.wav", volume: 1.0 }
|param1text = Hash
|example1 =
var sound_dir = getprop("sim/aircraft-dir")~"/Sounds/auralalerts/";
# you can add aural alerts one by one...
myMessageSystem.addAuralAlert("firebell", "firebell.wav");
# ... or you can define everything in one hash and pass it to addAuralAlerts (mind the trailing 's')
var Alerts = {
    overspeed: {path: "/Sounds", file: "overspeed.wav", volume: 1.0 },
    alert1: {file: "sound.wav", volume: 0.8 },
    alert2: "sound2.wav",
};
myMessageSystem.setSoundPath(sound_dir);
myMessageSystem.addAuralAlerts(Alerts);
}}
}}


===== setMessage() =====
==== setMessage() ====
{{Nasal doc
{{Nasal doc
|syntax = setMessage(class, msg_id, visible=1);
|syntax = setMessage(class, msg_id, visible=1);
Line 439: Line 479:
}}
}}


===== init() =====
==== auralAlert() ====
{{Nasal doc
|syntax = auralAlert(id);
|text = Plays an aural alert.
|param1 = id
|param1text = Identifier of the aural alert (see addAuralAlert() ).
}}
 
==== init() ====
{{Nasal doc
{{Nasal doc
|syntax = init();
|syntax = init();
Line 445: Line 493:
}}
}}


===== hasUpdate() =====
==== hasUpdate() ====
{{Nasal doc
{{Nasal doc
|syntax = hasUpdate();
|syntax = hasUpdate();
Line 451: Line 499:
}}
}}


===== setPageLength() =====
==== setPageLength() ====
{{Nasal doc
{{Nasal doc
|syntax = setPageLength(length);
|syntax = setPageLength(length);
Line 459: Line 507:
}}
}}


===== getPageLength() =====
==== getPageLength() ====
{{Nasal doc
{{Nasal doc
|syntax = getPageLength();
|syntax = getPageLength();
Line 465: Line 513:
}}
}}


===== getFirstUpdateIndex() =====
==== getFirstUpdateIndex() ====
{{Nasal doc
{{Nasal doc
|syntax = getFirstUpdateIndex();
|syntax = getFirstUpdateIndex();
Line 471: Line 519:
}}
}}


===== getActiveMessages() =====
==== getActiveMessages() ====
{{Nasal doc
{{Nasal doc
|syntax = getActiveMessages();
|syntax = getActiveMessages();
Line 477: Line 525:
}}
}}


===== getMessageID() =====
==== getMessageID() ====
{{Nasal doc
{{Nasal doc
|syntax = getMessageID(class, msg_text);
|syntax = getMessageID(class, msg_text);
Line 487: Line 535:
}}
}}


===== disableMessage() =====
==== disableMessage() ====
{{Nasal doc
{{Nasal doc
|syntax = disableMessage(class, msg_id);
|syntax = disableMessage(class, msg_id);
Line 497: Line 545:
}}
}}


===== enableMessage() =====
==== enableMessage() ====
{{Nasal doc
{{Nasal doc
|syntax = enableMessage(class, msg_id);
|syntax = enableMessage(class, msg_id);
Line 509: Line 557:
'''-- following methods are for message output on a canvas --'''
'''-- following methods are for message output on a canvas --'''


===== setCanvasGroup() =====
==== setCanvasGroup() ====
{{Nasal doc
{{Nasal doc
|syntax = setCanvasGroup(group);
|syntax = setCanvasGroup(group);
Line 517: Line 565:
}}
}}


===== createCanvasTextLines() =====
==== createCanvasTextLines() ====
{{Nasal doc
{{Nasal doc
|syntax = createCanvasTextLines(left, top, line_spacing, font_size);
|syntax = createCanvasTextLines(left, top, line_spacing, font_size);
Line 529: Line 577:
}}
}}


===== createPageIndicator() =====
==== createPageIndicator() ====
{{Nasal doc
{{Nasal doc
|syntax = createPageIndicator(left, top, font_size, format_string = nil);
|syntax = createPageIndicator(left, top, font_size, format_string = nil);
Line 541: Line 589:
}}
}}


===== updateCanvas() =====
==== updateCanvas() ====
{{Nasal doc
{{Nasal doc
|syntax = updateCanvas();
|syntax = updateCanvas();
Line 547: Line 595:
}}
}}


===== updatePageIndicator() =====
==== updatePageIndicator() ====
{{Nasal doc
{{Nasal doc
|syntax = updatePageIndicator(current, total);
|syntax = updatePageIndicator(current, total);
Line 557: Line 605:
}}
}}


 
=== Format for message definitions ===
 
==== Format for message definitions ====
MessageSystem.addMessages() expects a vector of message definitions. A message definition is a hash with the keys ''msg'', ''prop'', ''aural'', ''condition'' (only msg is required, the rest is optional).
MessageSystem.addMessages() expects a vector of message definitions. A message definition is a hash with the keys ''msg'', ''prop'', ''aural'', ''condition'' (only msg is required, the rest is optional).


Line 572: Line 618:
The optional ''aural'' element can be any key of the aural configuration hash passed to MessageSystem.addAuralAlerts(). If the  
The optional ''aural'' element can be any key of the aural configuration hash passed to MessageSystem.addAuralAlerts(). If the  


<nowiki>
{{#tag:syntaxhighlight|
{
{
     msg: "Message Text",
     msg: "Message Text",
Line 587: Line 633:
var EICASMessages = [
var EICASMessages = [
     {msg: "APU FIRE", prop: "engines/engine[2]/on-fire", aural: "firebell"},
     {msg: "APU FIRE", prop: "engines/engine[2]/on-fire", aural: "firebell"},
     {msg: "AC 1 AUTOXFER", prop: "systems/AC/system[1]/serviceable", condition: {eq: 0}},
     {msg: "AC 1 AUTOXFER", prop: "systems/AC/system[1]/serviceable", condition: {eq: 0} },
     {msg: "AC BUS 1", prop: "systems/AC/outputs/bus1", condition: {lt: 100}},
     {msg: "AC BUS 1", prop: "systems/AC/outputs/bus1", condition: {lt: 100} },
     {msg: "ELT ON", prop: ""},
     {msg: "ELT ON", prop: ""},
];
];
</nowiki>
|lang="nasal"}}


 
=== Class MessageClass ===
==== Class MessageClass ====
Helper class for MessageSystem. Stores configuration data for a message class.
Helper class for MessageSystem. Stores configuration data for a message class.


==== Class Pager ====
=== Class Pager ===
Helper class for MessageSystem.
Helper class for MessageSystem.
The pager class takes a vector of messages and splits it into pages (sub vectors of defined length).
The pager class takes a vector of messages and splits it into pages (sub vectors of defined length).
Line 614: Line 659:
|}
|}


===== new() =====
==== new() ====
{{Nasal doc
{{Nasal doc
|syntax = new(page_length, prop_path);
|syntax = new(page_length, prop_path);
Line 624: Line 669:
}}
}}


===== page() =====
==== page() ====
{{Nasal doc
{{Nasal doc
|syntax = page(lines);
|syntax = page(lines);
Line 632: Line 677:
}}
}}


===== pageChanged() =====
==== pageChanged() ====
{{Nasal doc
{{Nasal doc
|syntax = pageChanged();
|syntax = pageChanged();
Line 638: Line 683:
}}
}}


===== setPageLength() =====
==== setPageLength() ====
{{Nasal doc
{{Nasal doc
|syntax = setPageLength(lines);
|syntax = setPageLength(lines);
Line 646: Line 691:
}}
}}


===== setPage() =====
==== setPage() ====
{{Nasal doc
{{Nasal doc
|syntax = setPage(page);
|syntax = setPage(page);
Line 654: Line 699:
}}
}}


===== getPageCount() =====
==== getPageCount() ====
Returns total number of pages, according to last run of page()
Returns total number of pages, according to last run of page()


===== getCurrentPage() =====
==== getCurrentPage() ====
Returns current page, according to last run of page()
Returns current page, according to last run of page()


== HOWTO and Examples ==
== HOWTO and Examples ==
to be written / reference implementation in CRJ700 familiy to be published after framework is published.
to be written / reference implementation in CRJ700 familiy to be published after framework is published.
[[Category:Electronic flight instrument systems]]