Canvas Nasal/JavaScript Subset
This article is a stub. You can help the wiki by expanding it. |
Note If you're interested in helping with this, just get in touch with Hooray and TheTom. |
The FlightGear forum has a subforum related to: Nasal Scripting |
Nasal scripting |
---|
Nasal internals |
---|
Memory Management (GC) |
Motivation
The Nasal/JavaScript subset approach discussed below is about refactoring existing Canvas MFDs (or the underlying framework) so that the corresponding Nasal code becomes a valid subset of JavaScript (and vice versa) - that's just an idea that we ended up discussing behind the scenes when Torsten began his Phi/MFD (browser-based) work, because he began duplicating functionality that already existed elsewhere. The main reason being that a Canvas is just a property tree - and most elements are just textures or SVG images. In other words, it would not be that far-fetched to come up with a really tiny wrapper/subset of both, Nasal and JavaScript, that can be processed by both - part of this could be machine generated actually, i.e. dynamically compiling a simple subset of a DSL into whatever target platform is desired. The main thing this would require is what Torsten implemented already: APIs for setting/getting properties and running fgcommands, in conjunction with serving fgdata resources like textures and SVG files: Canvas Nasal/JavaScript Subset[1]
Objective
Determine if it's feasible to come up with a minimal/safe subset of Nasal and JavaScript for sharing animation/update logic for SVG-based instruments that may be either implemented by the built-in Mongoose httpd or by the Canvas subsystem. Almost certainly, this would be a very restricted subset of Nasal, and even more so, of JavaScript - but there's really only a handful of functions that cannot be directly mapped to their corresponding equivalents in the other language. Internally, more complex constructs would be handled by JavaScripts eval() API or Nasal's compile(). So this would involve a fair bit of meta programming - primarily, we'd need building blocks to deal with animated SVGs. Internally, a Canvas should then be dealt with like a SVG, i.e. no direct usage of CanvasText/CanvasPath. As long as these are set up via the SVG file and turned into a Canvas property tree, we can easily serve the same SVG file to a web browser over http.
Some kind of animation framework could then rewrite the animation logic to be valid JavaScript, so that the httpd can serve the code to the browser - while Canvas would internally keep using Nasal.
Canvas
Animations
You would probably want to use something like SVG/SMIL to serve animated vector images, so would not even need to use HTML5/Canvas to recreate every instrument. |
For animations, it would make sense to come up with a subset of JavaScript and Nasal which wrappers to hide the differences between the browser and fgfs, i.e. by wrapping props.nas/maketimer and building an animation framework on top of this safe subset. That way, we could allow people to create MFDs/instruments in Inkscape and a restricted subset of JavaScript/Nasal, which would mean that we could collaborate and grow a shared library of instruments that would be useful to both "front-ends".
MFDs
Before any significant amount of time is spent on re-implementing functionality available available on Gijs' ND, I'd suggest to seriously consider collaborating whenever possible - all the artwork and animation logic can be easily made platform-agnostic, i.e. there's nothing Android/FlightGear or Canvas-specific about updating a SVG element and animating/transforming it. To make this work, you would merely need to use a tiny subset of JavaScript and Nasal and add a few of helper functions as wrappers for platform-specific functionality (think property tree access) - TorstenD has already written most of the code required for this as part of his mongoose work. That way, you could easily reuse the same SVG/artwork that's internally used by the Canvas ND.
Remote GUI
The only way for the Canvas UI to provide a remote UI would be to serve SVG files via httpd/mongoose and hook them up to a subset of Nasal/JavaScript that both languages "understand", i.e. to set/get properties and invoke RPC functionality (e.g. fgcommands).
In the days prior to Phi, we actually toyed with the idea of not just using SVG in FG to create/render a widget via Canvas (ShivaVG), but to also serve SVG files with embedded code - since Torsten's Phi effort, that idea has become kinda obsolete.
But technically it would be possible to serve a SVG-based widget to a browser - for that to work, all callbacks added to events, would need to be valid JavaScript AND Nasal - even though it would be possible to dynamically recompile Nasal to be valid JavaScript (in fact, you could make Phi work with existing PUI/XML dialogs, including Nasal, doing exactly that)
And once you think about it, any Canvas could be represented as a SVG in memory and vice versa - including evne complex MFDs - i.e. we already have a parser that turns svg/xml into Canvas nodes, we could just as well have a parser doing the opposite to serve a Canvas node/group as SVG using a little serialization scheme.
Had this relationship been obvious earlier, SVG could in fact be the internal representation format of any Canvas
Dialogs
there's an unfortunate amount of custom Nasal code embedded in all kinds of PUI dialogs and that it would be a good thing to get rid of that, or at least standardize on it - i.e. so that a safe subset of Nasal can be used that would also be valid JavaScript.
Background
Given the recent mongoose/httpd work, we've been seeing some overlapping functionality that's already available in Nasal space, for which Torsten specifically implemented JavaScript wrappers, i.e. to expose the Property Tree and its listeners to JavaScript.
One idea we discussed is to "compile" Nasal into Javascript and send it to the browser (together with the canvas as SVG), but we don't know yet if this is possible with a reasonable effort. Also we should ensure that the JavaScript API and Nasal API are identical, such the code can be easily converted/ported. So we need to define a safe subset of Nasal and JavaScript and come up with corresponding classes to wrap identical stuff. And there are a quite a few useful JS features that Nasal will never support, so we need to use factories for those to hide differences between both languages (sounds like something that Philosopher might enjoy), or someone will end up complaining that jQuery breaks Nasal...
I have uploaded a new free Android App in the Play Store. This time it is a NAV display for airliners. At the moment the App works with the Boeing 777 and Airbus 330 (Omega), but I will start adding support to other planes in the near future. Many details like fixes, nav aids, waypoints (up to 12) have been carefully implemented so that the App resembles as much fatefully as possible the Boeing NAV display. The modes APP,VOR,MAP, ARC views, etc. are controlled from the panel in flightgear.
— saul (Mon Nov 03). Flightgear Android Navigation Displays for Airliners.
(powered by Instant-Cquotes) |
in the long term it would however make sense to re-implement this on top of Torsten's mongoose work, and maybe reusing some of Gijs' Canvas/ND work (certainly the SVG stuff could be reused, maybe even some generic Nasal/JavaScript code).
— Hooray (Sat Nov 08). Re: Flightgear Android Navigation Displays for Airliners.
(powered by Instant-Cquotes) |
Would love to see future enhancements. Specifically ILS, QNS/STD and Roll Scale. If you need support, just let me know.
— dutchman (Fri Dec 12). Re: Flightgear Android Navigation Displays for Airliners.
(powered by Instant-Cquotes) |
Before any significant amount of time is spent on re-implementing functionality available available on Gijs' ND, I'd suggest to seriously consider collaborating whenever possible - all the artwork and animation logic can be easily made platform-agnostic, i.e. there's nothing Android/FlightGear or Canvas-specific about updating a SVG element and animating/transforming it. To make this work, you would merely need to use a tiny subset of JavaScript and Nasal and add a few of helper functions as wrappers for platform-specific functionality (think property tree access) - TorstenD has already written most of the code required for this as part of his mongoose work.
That way, you could easily reuse the same SVG/artwork that's internally used by the Canvas ND. — Hooray (Fri Dec 12). Re: Flightgear Android Navigation Displays for Airliners.
(powered by Instant-Cquotes) |
For animations, it would make sense to come up with a subset of JavaScript and Nasal which wrappers to hide the differences between the browser and fgfs, i.e. by wrapping props.nas/maketimer and building an animation framework on top of this safe subset. That way, we could allow people to create MFDs/instruments in Inkscape and a restricted subset of JavaScript/Nasal, which would mean that we could collaborate and grow a shared library of instruments that would be useful to both "front-ends".
— Hooray (Mon Sep 22). Re: FGWebPanel aka FGPanel 2.0 or: FGPanel goes html.
(powered by Instant-Cquotes) |
Understandably, all of this is still in a very early state, i.e. just being discussed currently - but it would obviously be great if we could work out a way to better collaborate, because ideally, we'd really become front-end agnostic, so that we can provide the infrastructure that would allow people to create MFDs/instruments using just SVGs and a subset of JavaScript/Nasal. Alternatively, we can dynamically rewrite a subset of Nasal code to turn it into valid JavaScript - e.g. props.nas would be mapped to your ported JavaScript props APIs. I am sufficiently familiar with both, JavaScript and Nasal, and both languages provide support for dynamically compiling program code at run-time - so we could just as well come up with a very limited "instrument animation markup" that is interpreted by roughly ~250 lines of Nasal code, and mapped to JavaScript or Nasal/Canvas animation logic respectively.
— Hooray (Mon Sep 22). Re: FGWebPanel aka FGPanel 2.0 or: FGPanel goes html.
(powered by Instant-Cquotes) |
If we could manage to pull this off, there'd no longer be any disparity between both approaches, and they would be fully compatible - and people interested in either method could help grow the library of instrument. The only thing that we might want to explore sooner or later is serializing a Canvas to a raster image that can be served by mongoose - you already seem to have code serializing screen shots to an osg::Image, so we could use the same method to serve an arbitrary Canvas to a browser, which will be useful for more complex layers that cannot be easily represented using just scripting (no matter if it's JavaScript or Nasal).
— Hooray (Mon Sep 22). Re: FGWebPanel aka FGPanel 2.0 or: FGPanel goes html.
(powered by Instant-Cquotes) |
Mapping
Note we should take a look at the existing JavaScript wrappers for props.nas etc) |
Nasal | JavaScript | Comments |
---|---|---|
var | var | |
func | function | |
call()/compile() | eval() | |
settimer/maketimer | setTimeout() | |
props.nas | jQuery/WebSockets |
var new_function = func(keyword) {
return
func(name, params, body)
print("var ", name, "=", keyword, "(",params,")", body);
}
##
# Nasal test case:
var make_nasal_function = new_function('func');
var test = make_nasal_function(name: "hello", params: "name", body: "print(name);");
var test_obj = compile(test);
Goals
Come up with a common Nasal/JavaScript subset that works in both environments (browser/fgfs), and use factories for hiding platform differences, for example:
- property tree
- listeners
- props.nas
For reference, look at TorstenD's WebGUI work which is heavily overlapping with props.nas stuff. However, we need to keep in mind that there are certain APIs that will never be supported out of the FG context, while others may simply be "delegated" via FlightGear (webSockets, e.g. timers/listeners).
So we kinda need to formalize both environments and come up with a minimal API subset that supports versioning.
We also need to keep in mind that props.nas may be updated using cppbind sooner or later to reduce Nasal space overhead.
APIs
- setprop/getprop
- setlistener
- settimer
(it might make sense to directly encapsulate those APIs and use helper objects, as discussed on the forum)
Design
Mongoose-based FGPanel
I have been dreaming of a cross-platform, simple solution to render 2d panels on a remote device. — Torsten Dreyer (2014-09-17). [Flightgear-devel] Goodbye fgpanel - hello fgpanel 2.0.
(powered by Instant-Cquotes) |
It runs on any device that has a web browser. So yes, if your FlightGear computer can run Firefox, Opera or alike you can run it on the same — Torsten Dreyer (2014-09-17). Re: [Flightgear-devel] Goodbye fgpanel - hello fgpanel 2.0.
(powered by Instant-Cquotes) |
References
References
|