246
edits
No edit summary |
|||
Line 1: | Line 1: | ||
= Nasal runtime re-loadable modules = | = Nasal runtime re-loadable modules = | ||
== Introduction and motivation == | == Introduction and motivation == | ||
Nasal (Flightgears integrated scripting language) comes with a limited number of [[Nasal library|core functions]]. | Nasal (Flightgears integrated scripting language) comes with a limited number of [[Nasal library|core functions]]. | ||
Line 10: | Line 9: | ||
For more information on how and when these files are loaded see [[Nasal Initialization]]. | For more information on how and when these files are loaded see [[Nasal Initialization]]. | ||
== Differences between add-ons and modules == | |||
While there are many similarities between add-ons and modules, some words on the differences: | While there are many similarities between add-ons and modules, some words on the differences: | ||
Line 29: | Line 18: | ||
Add-ons are selected by the user before launching FlightGear, thus they may or may not be available at runtime. | Add-ons are selected by the user before launching FlightGear, thus they may or may not be available at runtime. | ||
A module must contain at least the file '''main.nas''' (default, other filename is possible) | = HowTo / Examples = | ||
First some examples, the API documentation follows below. | |||
== Nasal modules in an aircraft (e.g. for development) == | |||
Nasal code for an aircraft is usually loaded by a XML declaration in the <aircraft>-set.xml file like this: | |||
<syntaxhighlight lang="xml"> | |||
<PropertyList> | |||
<nasal> | |||
<foo> <!-- Nasal namespace foo --> | |||
<file>Nasal/foo.nas</file> | |||
</foo> | |||
<bar> <!-- Nasal namespace bar --> | |||
<file>Aircraft/Generic/foo.nas</file> | |||
</bar> | |||
<myAircraft> | |||
<file>Nasal/efis_module.nas</file> | |||
</myAircraft> | |||
</nasal> | |||
</PropertyList> | |||
</syntaxhighlight> | |||
This is fine unless you are developing a Nasal subsystem for the aircraft and have to restart FlightGear every time you edit a few lines. | |||
For this case you could consider to use the Module class (defined in FGDATA/Nasal/modules.nas) and make your code re-loadable at runtime, | |||
which means you do not have to restart whole FlightGear just for a few lines of edited Nasal code. | |||
'''Example Nasal/efis_module.nas:''' | |||
<syntaxhighlight lang="nasal"> | |||
#-- load EFIS as reloadable module | |||
var my_efis = modules.Module.new("myAircraft_EFIS"); # Module name | |||
my_efis.setDebug(1); # 0=(mostly) silent; 1=print setlistener and maketimer calls to console; 2=print also each listener hit, be very careful with this! | |||
my_efis.setFilePath(getprop("/sim/aircraft-dir")~"/Nasal/EFIS"); | |||
my_efis.setMainFile("myAircraft-efis.nas"); | |||
my_efis.load(); | |||
</syntaxhighlight> | |||
Now add a menu item for easy reloading like this: | |||
{{note| | |||
The module name in the property path must match the name passed to modules.Module.new() | |||
|margin=10px |width=50%}} | |||
<syntaxhighlight lang="xml"> | |||
<menubar> | |||
<default> | |||
<menu n=100> | |||
<!-- normal aircraft menu --> | |||
</menu> | |||
<menu n=101> | |||
<label>Aircraft Development</label> | |||
<item> | |||
<label>Reload EFIS</label> | |||
<binding> | |||
<command>property-assign</command> | |||
<property>/nasal/modules/myAircraft_EFIS/reload</property> | |||
<value>1</value> | |||
</binding> | |||
</item> | |||
</menu> | |||
</default> | |||
</menubar> | |||
</syntaxhighlight> | |||
{{tip| | |||
You can also call {{code| myAircraft.my_efis.reload();}} to trigger the reload. myAircraft is the namespace given in the <aircraft>-set.xml file, my_efis is the module object (see above). | |||
|margin=10px |width=50%}} | |||
= Structure of Nasal reloadable modules = | |||
A module must contain at least the file '''main.nas''' (default, other filename is possible) and should contain the functions {{code|main()}} and {{code|unload()}}. | |||
=== main() function === | === main() function === | ||
Line 50: | Line 100: | ||
# The name must contain at least one letter so it cannot be confused with a number | # The name must contain at least one letter so it cannot be confused with a number | ||
# The name shall not match any existing .nas file or directory in FGDATA/Nasal to avoid namespace clashes | # The name shall not match any existing .nas file or directory in FGDATA/Nasal to avoid namespace clashes | ||
{{note| | |||
Reloadable modules shipped with FlightGear are stored in subdirectories of FGDATA/Nasal/modules/ as these subdirectories will not be loaded automatically by Flightgear on start. | |||
However, modules.nas will scan this directory to create a list of available modules (= list of subdirectories). | |||
Each module correspondes to one subdirectory and the direcory name is also the module name. | |||
}} | |||
= modules.nas = | |||
In ''modules.nas'' the class ''Module'' is defined. | |||
A module object holds information about the path and filename of the Nasal script and supports unloading and reloading the code at runtime | |||
(e.g. without restarting Flightgear as a whole) by tracking some critical resources like [[Listeners|listeners]] and [[Timers|timers]]. | |||
{{note|Parts of this functionality were added to the [[Addons|addons]] manager earlier and have now been extracted to avoid code duplication.}} | |||
{{caution| Within a module {{code|setlistener()}} is overloaded and the default value for the 4th argument (runtime) is changed to 0, so the listener will run only if the property value has changed. | |||
}} | |||
== library functions == | == library functions == | ||
Line 153: | Line 219: | ||
var bar = foo.get("bar"); # get variable "bar" defined in FGDATA/Nasal/modules/foo/main.nas (or a file included by this file) | var bar = foo.get("bar"); # get variable "bar" defined in FGDATA/Nasal/modules/foo/main.nas (or a file included by this file) | ||
}} | }} | ||
= Existing modules = | = Existing modules = |
edits