the next airport or airport with METAR station, but about any type of
airport
- as a side effect this change makes it also 30 to 50% faster :-)
In the long run this linear search shall be replaced with a spatial
algorithm (like octree), which will be a much bigger performance gain.
Usage: airportinfo("KSFO");
airportinfo(37, 122); # airport closest to lat/lon
airportinfo(); # airport closest to current position
Returns nil on error, or a data hash otherwise. Example:
# length of runway 28R
var len = airportinfo("KSFO").runways["10L"].length;
Note that only one side of a runway is returned.
parser. Advantages over xml.nas: (reviewed and OK'ed by Andy)
- faster (33% ... only. I had hoped for more.)
- more standards compliant
- should support UTF
- I don't have to support it. ;-)
Usage: parsexml(<path> [, <start-tag> [, <end-tag> [, <data> [, <pi>]]]]);
<path> is an absolute file path, the rest are optional callback functions.
Example:
parsexml("/tmp/foo.xml", nil, nil, func(d) { print("DATA FOUND: ", d) });
or nil if no terrain intersection could be made (tile not loaded yet).
<matdata> is a hash with information about the surface material, or nil
if no material is assigned (shouldn't really happen, but one never knows).
Example:
var ac = geo.aircraft_position();
var data = geoddata(ac.lat(), ac.lon());
debug.dump(data);
# which outputs
[ 294.5862574369132, { light_coverage : 0, bumpiness : 0, load_resistance : 1e+30,
solid : 1, names : [ "pc_taxiway", "dirt_rwytaxiway" ], friction_factor : 1,
rolling_friction : 0.02 } ]
With this information it can be determined how far an object would sink in,
if the coordinate is on a runway, etc.
foreach (var n; data[1].names)
if (string.match(n, "p[ac]_*"))
im_on_a_runway();
IRC wanted this to be scritable) and add it back (as a tip popup) via
a little nasal in the keyboard handler. Also put the synthesis of
property nodes back into fgcommand(), because I got cold feet.
missing, for sanity. Note that this will pass the resulting NULL
pointer through into the underlying SGCommand handlers, some of which
may be unprepared for it. So basically this is now yet another way
you can use Nasal to exercise bugs and hose your sim; no biggie.
because nasal's f_interpolate() may be called in Nasal at times when the
GENERAL subsystem group is being deconstructed; access it by addressing
the group directly, as using globals->get_subsystem() does then not
work any more then; yeah, it's all for a rare border case ... :-)
NasalSys.cxx more robust instead. The reason for the crash was that during
fgfs shutdown destroyed subsystems (GENERAL group) still need Nasal access
(for AI Model destruction listeners), but at that point globals->get_subsystem()
can't even deliver the "nasal" subsystem (INIT group). One way to solve that
problem would have been to replace globals->get_subsystem("nasal") by
globals->get_subsystem_mgr()->get_group(SGSubsystemMgr::INIT)->get_subsystem("nasal"),
but Andy decided to store a pointer to the active "nasal" subsysten in
NasalSys.cxx instead, as the "nasal" subsystem needs to be accessed in
every single Nasal extension function, and multiple "nasal" subsystems are
out of the question, anyway.
getAttribute("archive") returns 1 if the attribute is set, and 0 otherwise.
Allow to query and to set all properties by not specifying an attribute
string: getAttribute() returns all attributes bit coded in an integer,
and setAttribute(attr) sets all attributes. No assumptions may be made
about the meaning of the bits -- they can be changed in future fgfs releases.
The only valid use is to compare or set attribute numbers obtained in the
same fgfs run. This is meant for allowing full copies of property branches.
Also add getAttribute query strings "children" for the number of children,
and "alias".
their XML wrapper/animation file. They can access their /ai/models node
via cmdarg() function. Example:
<nasal>
<load>
print("Hi, I'm the Nimitz. My data are under ",
cmdarg().getPath());
</load>
<unload>
...
</unload>
</nasal>
Note, however, that the <unload> block is only called on exit at the moment,
not when the tile is unloaded.
Nasal now supports calls to "subcontexts" and errors can be thrown
across them, leading to complete stack traces when call() is used,
instead of the truncated ones we now see.
Vectors can now be concatenated using the ~ operator that used to work
only for strings.
Better runtime error messages in general due to a fancier
naRuntimeError() implementation
A big data size shrink on 64 bit systems; the size of a naRef dropped
by a factor of two.
"Braceless code blocks" have been added to the parser, so you can
write expressions like "if(a) b();" just like in C. Note that there's
still a parser bug in there that fails when you nest a braced block
within a braceless one.
Character constants that appear in Nasal source code can now be
literal multibyte UTF8 characters (this was always supported for
string literals, but character constants were forced to be a single
byte).
New modules: "bits", "thread", "utf8" and (gulp...) "io". The bits
library might be useful to FlightGear, the utf8 one probably not as
Plib does not support wide character text rendering. The thread
library will work fine for spawning threads to do Nasal stuff, but
obviously contact with the rest of FlightGear must be
hand-synchronized as FlightGear isn't threadsafe. The io library is
no doubt the most useful, as it exposes all the basic stdio.h
facilities; it's also frighteningly dangerous when combined with
networked code...
done for performance reasons, but print() should be able to output any
valid string, and when SG_LOG uses strings and streams already, then we
can use that here, too. (Not discussed with Andy yet.)
before the property tree is stored away for reinit, so the signal would
be emitted again on reset.
- fix inconsistent style that sneaked in with a previous patch
in $FG_ROOT/Nasal/* were loaded and executed, and thus all Nasal library
functions are available. This was in the past only done with settimer(..., 0),
constructions, but suchlike triggered timer functions are executed
*after* aircraft specific Nasal files were loaded, so they can't be
used for internal library initialization, where e.g. props.Node() is
already needed.
value on a property. This becomes a NaN when converted to a numeric
value, which then percolated into the C++ world where it ultimately
caused a crash in YASim's turbulence code. While converting nil to
NaN isn't *strictly* wrong, it's dangerous for this reason. Toss a
Nasal exception instead. Hopefully this won't break too much
preexisting code.
maintainable. The rules are simple (extension functions are called
*with* the lock, which must be dropped before calling naCall(), which
grabs it) but the tracking of when the lock was held was getting a
little confused. Keep a "nasal call depth" count in the subsystem to
figure out whether we are making a sub-call and thus hold the lock.
SGPropertyNode to guarded ones. This is also done for JSBSim/JSBSim.hxx,
for which JSB had given explicit permission a while ago. I postponed that
back then, but now is the time.