Howto:Multi-instance Canvas use
|This article is a stub. You can help the wiki by|
We've seen a number of discussions where people wanted to share/sync (or replicate) a Canvas based features, such as an MFD like a NavDisplay or PFD across multiple fgfs instances . For the time being, this isn't explicitly supported by the Canvas system, so that a number of approaches/workarounds have been suggested/discussed, with different pros & cons.
However, it is clear that the Canvas system is likely going to become, and remain, the primary means to implement support for modern MFD-like avionics for, and inside, FlightGear.
- multi-instance setups like those used at FSWeekend/Linux
- home cockpit builders wanting to show existing MFDs on different screens/devices
This page is intended to introduce, and summarize, the different approaches that have so far been discussed (some of which have been prototyped/tested already), and provide a comparison in terms of the pros and cons of each approach.
Good to know
|Work in progress|
This article or section will be worked on in the upcoming hours or days.
See for the latest developments.
In FlightGear, a Canvas is just an abstraction mechanism built on top of the FlightGear property tree to encapsulate the concept of a RTT/FBO context. Basically, this means that we can easily create, modify and update textures at runtime without having to write any C++/OSG code. This works primarily in the form of a handful of so called 2D rendering elements which form the primitives supported by the Canvas system, mainly:
- text elements
- image elemeents
- path elements
- group/map elements
Internally, each Canvas must have a top-level group element, which in turn may contain an arbitrary number of child elements, including other group elements and so on.
A Canvas is created and modified by setting element-specific properties - these are internally parsed and processed by using FlightGear's built-in listener API (SGPropertyChangeListener), so that each element can basically look for certain types and names of properties to be set/updated, and validate the written values - to finally update the state of each element.
All of this is taking place behind the scenes because we do have some fairly convenient high-level wrappers implemented in FlightGear's scripting system (called Nasal). However, under the hood, what all those Nasal layers are really doing is primarily just updating element-specific properties (see api.nas).
Consequently, this also means that any FlightGear subsystem, and I/O or IPC mechanism, well integrated with the property tree can make use of FlightGear's 2D drawing API (Canvas), without having to use any C++/OSG code to do so.
When it comes to MFDs like a PFD or ND, these are usually split into two main components - artwork (usually created via Inkscape and textures via GIMP), and the code to add functionality to this artwork, mainly in the form of various callbacks that use timers and listeners to selectively update certain MFD elements to animate those.
This is working great, but when it comes to multi-instance setups, even our Canvas-based MFDs are suffering from the same limitations that hard-coded gauges are suffering from: we don't have any standard mechanism to set up these avionics in a master/slave fashion to selectively propagate relevant events/state across multiple fgfs clients in a scalable fashion.
However, due to the property-centric nature of the Canvas system, this is an unnecessary restriction, and one that can be easily addressed by reviewing the requirements to share/replicate properties across multiple fgfs instance.
This article is going to try to present some of the approaches we've seen discussed so far, as well compare the corresponding pros & cons.
Serialization to SVG