The add-on framework now uses the following files in each add-on
directory:
- addon-config.xml (previously: config.xml)
- addon-main.nas (previously: main.nas)
This is consistent with the addon-metadata.xml file that is already part
of the interface between FG core and add-ons. The goal is to make it
clearer, when browsing an add-on directory, which files belong to the
"FG core <-> add-on" interface and which files belong to the add-on
proper. This will be beneficial also when more files are added to the
"FG core <-> add-on" interface, such as possibly addon-events.xml in the
future.
This change is incompatible, thus it is the right time to do *before*
2018.2.1 is out, especially considering that this upcoming release
already has incompatible changes in the add-on API, namely the
requirement of the addon-metadata.xml file and the type of the argument
passed to each add-on's main() function. We'll try harder not to break
compatibility in the add-on API once 2018.2.1 is out. For now, it is
still a good time to try to get the API as clean as possible.
Prevent FDM-derived properties being sent at full speed (120Hz) which
overloads telnet connections. Instead track dirty properties and
send them at the protocol’s update rate (which is presumably what
the user expects)
the current timestamp used in mp protocol and in AImultiplayer is not a good one:
it can pause, or even change speed if we change warp value.
we want it to be used for network protocol lag and jitter estimation, and
a time flowing linearly on both side is needed, here's a first introduction
of this timestamp relates to real elapsed time.
here it's initialised to the system clock, then follow the monotonic clock.
in future improvement, it will allow time synchronisation betwen mp players,
to have a very good close formation flight experience.
The "Airbus" callouts ("2500", "hundred above", "retard") are not issued
by the original mk-viii unit, but adding support helps with better
simulation for Airbus a/c. The new callouts are disabled by default, and
are enabled by a specific setting of the GPWS "category-4" configuration
value (see Wiki).
- /sim/multiplay/transmit-filter-property-base can now filter based on property index; or have the previous mode of transmitting only generics by setting to 1.
- Move emesary MP bridge property base index to 12000 - to allow filtering of all except these (to reduce packet size).
- Modify global_mouseInput in init() and in shutdown(), because *these*
are the places where FGMouseInput is enabled or disabled.
- reinit() does shutdown() followed by init().
Note: the commented-out block starting with "FIXME: memory leak" that is
removed here was just an outdated comment, because SGBindingList
is an std::vector<SGBinding_ptr>, where SGBinding_ptr is a smart
pointer type (SGSharedPtr<SGBinding>). In other words, there was
no leak in this place---at least, not recently.
Create the FGMouseInputPrivate instance in FGMouseInput::init() instead
of in FGMouseInput's constructor. This will allow straightforward
implementation of reinit() via shutdown() and init().
Also get rid of the 'initialized' bool, since bool(d) is now equivalent
(d being the std::unique_ptr<FGMouseInputPrivate> data member of
FGMouseInput).
Using std::vector<mouse_mode> instead of std::unique_ptr<mouse_mode[]>
would have been possible of course, but a bit more awkward as
vector<>::size() returns an std::size_t but all the "adjacent" code is
based on the 'int' type.
Octal escape sequences can be as short as 2 bytes (\0, ..., \7),
therefore they allow one to generate shorter files than hex escapes, for
the same resource contents. The line lengths won't be as even, but this
is purely cosmetic, virtually no one will ever read the resource data
string literals, so this is quite a negligible drawback compared to the
advantage of using less space in the Git repository every time resource
files are committed.
These files were originally included for special trim routines. But these routines are no longer maintained in JSBSim and have already been partially removed from FlightGear.
If running with the launcher, and FG-home is read-only, show a warning
to the user, since this is probably a surprise to them.
(In non-launcher mode we don’t show the box, since it’s more likely to
be an intentional duplicate launch)
The previous priority was PRIORITY_NORMAL, which happens to be higher
than PRIORITY_DEFAULT. Even though the add-on resource provider should
be quite fast at rejecting resource paths that don't start with
'[addon=', I currently can't see any reason that justifies to give it a
higher priority than other paths added to the simgear::ResourceManager
with addBasePath(..., PRIORITY_DEFAULT).
This is another place where the add-on code uses regexps, and so far I
had forgotten to add the fallback code for compilers that don't support
<regex> as per the C++11 standard.
This method takes a string such as "this/is/a/relative/path" and returns
"[addon=ADDON_ID]this/is/a/relative/path", substituting the add-on
identifier for ADDON_ID.
This way, add-on authors don't even have to know the special syntax
'[addon=ADDON_ID]relative/path' used for add-on-specific resource paths,
and don't need to hardcode their add-on identifier inside each such path
either.
This makes it possible to look up files from add-on directories using
for instance FGGlobals::resolve_resource_path(), passing a string such
as "[addon=ADDON_ID]relative/path" as explained in the previous commit.
A resource can be specified with the syntax:
[addon=ADDON_ID]relative/path
Such a resource corresponds to the file $addon_base_path/relative/path
for the specific add-on whose identifier is ADDON_ID.
If the particular add-on isn't registered, looking up such a resource
throws sg_exception.
Replace the previously-written manual calls to "new SomeClass(...)" with
their equivalent using
flightgear::addons::shared_ptr_traits<>::makeStrongRef(). This way, when
SomeClassRef is changed from SGSharedPtr<SomeClass> to
std::shared_ptr<SomeClass>, these calls will magically use
std::make_shared<SomeClass>(...) instead of the "new SomeClass(...)"
call.
Change the arrestor wire handling as follows;
- expose property to indicate when arrestor wire has been snagged: /fdm/jsbsim/systems/hook/arrestor-wire-engaged-hook
- add property to allow the model to request that the wire is released: /fdm/jsbsim/systems/hook/tailhook-release-cmd. This permits an overspeed approach to catch the wire and then drop it.
Jean Pellotier, 2018-01-02 : we don't want interpolation for integer values, they are mostly used
for non linearly changing values (e.g. transponder etc ...)
ref: https://sourceforge.net/p/flightgear/codetickets/1885/
(everything described here lives in the namespace flightgear::addons)
New classes: Author, Maintainer, and Contact. Author and Maintainer
derive from Contact. For each contact, the following can be defined in
addon-metadata.xml: name, email, and url. See [1] for details about the
syntax and usage policy. Nasal bindings have been updated accordingly,
there are three new ghosts: addons.Contact, addons.Author and
addons.Maintainer.
The enum class UrlType has two new members: author and maintainer. The
Addon::getUrls() method has a new signature:
std::multimap<UrlType, QualifiedUrl> getUrls() const;
because non-empty 'url' fields for authors and maintainers contribute to
the result, and there can be an arbitrary number of authors and an
arbitrary number of maintainers defined for a given add-on---therefore,
std::map can't be used anymore.
Finally, QualifiedUrl has a new field (detail) which stores the author
name (resp. maintainer name) when the QualifiedUrl type is
UrlType::author (resp. UrlType::maintainer). Currently, this 'detail'
field is not used for other URL types, but this could be changed if
desired.
[1] https://sourceforge.net/p/flightgear/fgdata/ci/next/tree/Docs/README.add-ons
flightgear::addons::shared_ptr_traits allows one to easily switch for
instance from an SGSharedPtr<T> to an std::shared_ptr<T> for "all" uses
of a particular T, and automatically have std::make_shared<T>(...) used
instead of SGSharedPtr<T>(new T(...)) when creating a shared instance of
T. This is interesting because std::make_shared<T>() allocates all
needed memory as one block, whereas std::shared_ptr<T>(new T(args...))
would perform at least two allocations (one for the object T and one for
the control block of the shared pointer).
This is done via static methods (one for each kind of smart pointer):
shared_ptr_traits<SGSharedPtr<T>>::makeStrongRef()
shared_ptr_traits<std::shared_ptr<T>>::makeStrongRef()
that forward their arguments in the same way as std::make_shared<T>().
Normally, <regex> should be available and working in any compliant C++11
implementation, however at least g++ 4.8[1] lies about its C++11
compliance: its <regex> is utterly unusable, see [2] and [3] for
details.
This requires SimGear commit ab1e2d49abdf5b1aca9035a51d9d73d687f0eba7,
for the HAVE_WORKING_STD_REGEX preprocessor symbol.
[1] Which appears to be (precisely 4.8.5) the version shipped in
CentOS 7, and used on FlightGear's current Jenkins installation.
[2] https://stackoverflow.com/a/12665408/4756009
[3] https://sourceforge.net/p/flightgear/mailman/message/36170781/
Changes to test_AddonManagement.cxx:
- in testAddonVersionSuffix(), fgtest::initTestGlobals() was called
with the wrong test name (not used anyway, but might be in the
future);
- in testAddon():
* rename variable 'm' to 'addon' ('m' used to stand for the old
class name AddonMetadata);
* call fgtest::initTestGlobals() and fgtest::shutdownTestGlobals()
(not technically needed, but cleaner).
- The Emesary MP bridge can use any string property; however it seems sensible to separate the properties out into a distinct block.
- There is a now a type property for each bridge. This is to allow the bridge to identify its type based on what it can transfer based on function. This will allow rapid filtering of unrequired notifications within the bridge (NYI)
QualifiedUrl is essentially a pair containing an enum value
(addons::UrlType::homePage, addons::UrlType::download, etc.) and an
std::string for the URL per se, with adequate getters and setters.
Addon::getUrls() is for people who wish to process all non-empty URLs
occurring as part of the add-on metadata in batch.
Mailing-list discussion:
https://sourceforge.net/p/flightgear/mailman/message/36159711/
- Parsing of the addon-metadata.xml file is now handled by a new static
method of Addon:
static Addon fromAddonDir(const SGPath& addonPath);
This method will be reusable to gather all add-on metadata from a set
of add-on directories (just call the method once per add-on). This
change also simplifies AddonManager::registerAddonMetadata().
- New supported fields:
authors
maintainers
license/{designation,file,url}
url/{home-page,download,support,code-repository}
tags
See
https://sourceforge.net/p/flightgear/fgdata/ci/next/tree/Docs/README.add-ons
for documentation on these fields.
Mailing-list discussion:
around https://sourceforge.net/p/flightgear/mailman/message/36155660/
refactoring of FGFDM parser
replace old helpers with lib functions from <cstring>
remove typecast that kills 'const'
add some comments and clarify variable names
These methods were removed by mistake in commit 0dbb0dff9, which broke
code that relies on them (e.g., FMSDelegate.currentWaypointChanged() in
$FG_ROOT/Nasal/route_manager.nas).
Also remove 'waypointPrototype' from NasalPositioned.cxx, since it is
not used anymore.
Note: the methods can't be easily re-enabled by means of
'waypointPrototype', because for FPLeg ghosts, 'waypointPrototype'
was emulated as a parent class before this commit, and thus when
querying an FPLeg ghost for its 'airport', 'runway' or 'navaid'
member, the corresponding data member returned by
waypointCommonGetMember() would be found by legGhostGetMember()
*before* parent classes are searched. This commit prevents this
from happening by returning 'airport', 'runway' and 'navaid' as
member functions *directly* in legGhostGetMember(), before
waypointCommonGetMember() is queried as a fallback.
Thanks to Eric van den Berg for the bug report.
Move the format-version node inside /meta. It's not compatible of
course, but since the stuff this is breaking is only 2 or 3 days old,
let's go for it for nicer code and file format.
Sorry if you had already written an addon-metadata.xml file of your
own. In this case, just replace:
<format-version type="int">1</format-version>
with:
<meta>
<file-type type="string">FlightGear add-on metadata</file-type>
<format-version type="int">1</format-version>
</meta>
This should fix the following compilation error and other similar ones:
converting to ‘std::tuple<flightgear::AddonVersionSuffixPrereleaseType,
int, bool, int>’ from initializer list would use explicit constructor
‘constexpr std::tuple< <template-parameter-1-1> >::tuple(_UElements&&
...)
According to <https://stackoverflow.com/a/32084829/4756009>, the change
wouldn't be needed in C++14 (and it built fine with my g++) but we use
C++11.
This commit adds C++ classes for add-on management, most notably
AddonManager, Addon and AddonVersion. The AddonManager is used to
register add-ons. It relies on an std::map<std::string, AddonRef> to
hold the metadata of each registered add-on (keys of the std::map are
add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>).
Accessor methods are available for:
- retrieving the list of registered or loaded add-ons (terminology
explained in $FG_ROOT/Docs/README.add-ons);
- checking if a particular add-on has already been registered or
loaded;
- for each add-on, obtaining an Addon instance which can be queried
for its name, id, version, base path, the minimum and maximum
FlightGear versions it requires, its base node in the Property Tree,
its order in the load sequence, short and long description strings,
home page, etc.
The most important metadata is made accessible in the Property Tree
under /addons/by-id/<addon-id> and the property
/addons/by-id/<addon-id>/loaded can be checked or listened to, in
order to determine when a particular add-on is loaded. There is also a
Nasal interface to access add-on metadata in a convenient way.
In order to provide this metadata, each add-on must from now on have in
its base directory a file called 'addon-metadata.xml'.
All this is documented in much more detail in
$FG_ROOT/Docs/README.add-ons.
Mailing-list discussion:
https://sourceforge.net/p/flightgear/mailman/message/36146017/
The Garmin protocol implementation really is an NMEA protocol with a few
extra messages. Instead of duplicating the code, introduce the NMEA protocol
as a base class, which is reused for the Garmin class. The input/output
has not changed at all (and it maintains the FG-specific quirks, like our
NMEA class using LF-only linefeeds, while the Garmin protocol uses
CR-LF linefeeds.
Several checks were off by one, resulting in a segfault when only one
parameter was missing.
Also improve error messages, giving details about what is expected.
Waypoint objects used in Nasal code can now return their airport,
runway or navaid object (Nasal ghost). More precisely:
- if waypoint 'wpt' was made from an airport object[1], then
'wpt.airport' is this airport object;
- if waypoint 'wpt' was made from a runway object[2], then
'wpt.runway' is this runway object, and 'wpt.airport' is the
airport containing that runway;
- if waypoint 'wpt' was made from a navaid object[3], then
'wpt.navaid' is this navaid object.
When one of the three properties 'airport', 'runway', and 'navaid' is
not applicable to a given waypoint due to the type of the underlying
FGPositioned, its value is nil.
The code for these properties was already mostly there, but
unreachable from Nasal.
[1] For instance, with createWPFrom(airportinfo("LOWI"))
[2] For instance, with createWPFrom(airportinfo("LOWI").runway("26"))
[3] For instance, with:
var apt = airportinfo("LOWI");
var navaid = findNavaidByFrequencyMHz(apt, 109.7);
var navaidWpt = createWPFrom(navaid);
For consistency, define these three static methods in FGPositioned.
FGPositioned::isAirportType() is the same as FGAirport::isAirportType()
(piece of code moved from airport.cxx to positioned.cxx, and
FGAirport::isAirportType() now calls FGPositioned::isAirportType()).
- FGPositioned::isAirportType() returns true for AIRPORT, HELIPORT,
SEAPORT;
- FGPositioned::isRunwayType() returns true for RUNWAY;
- FGPositioned::isNavaidType() returns true for NDB, VOR, ILS, LOC, GS,
DME, TACAN.
The OSG Ctrl to right-click mapping was breaking this on Mac, but
changing that will break other things, so move the ruler feature from
‘ctrl left click’ to a simple ‘right click’ which ends up being the
same on Mac anyway.
Apply the device-pixel-ratio when calculating the initial position of
PUI dialogs, so they appear correctly (eg, centered) when running with
device-pixel-ratio != 1.0
The mapping from aircraft URI to name was wrong for local (non-package)
aircraft, as spotted by Thorsten Renk. Note other data (thumbnail) is
still incorrect, but another change I have pending will replace this
code anyway so only doing the simple fix for now.
Doing the option processing in Options::parseOption() has drawbacks:
- doesn't work well upon reset;
- doesn't work in the built-in launcher Additional Settings box.
Options::processOptions() is invoked both upon reset after the property
tree has been reset, and by the built-in launcher to process options
given in the Additional Settings box. This is not the case of
Options::parseOption() which is better for... parsing. :-)
Also use SGPath::fromLocal8Bit() to decode the path argument of --addon.
* Correct the filename case in the #include directive in PUICamera.cxx,
so that compilation succeeds on case-sensitive filesystems.
* Add the PU_SCROLL_UP_BUTTON and PU_SCROLL_DOWN_BUTTON #defines, as
they are missing from some systems which ship old versions of the PUI
library.
Move all PUI event and rendering into a custom camera, which can be
rendered via an FBO to account for display-resolution scaling (HiDPI).
Start wrapping PUI calls in #ifdefs so PUI can be disabled at compile
time; a run-time switch is trivial now but not implemented yet.
This makes it considerably easier to reference an item from the currently selected style without having to lookup the selected style index and then use that to select the appropriate element from the styles/ tree
Treat passing nil as clearing the speed / altitude restriction for
the leg. Also default the second arg to ‘at’, so calling these
methods with a single numerical arg is permitted.
Allows creating a new, inactive by empty Flightplan from Nasal. Can
also be used to load a flightplan:
var fp1 = createFlightplan();
var fp2 = createFlightplan("p3.xml");
Rewrite the position-init code for carrier starts, to precisely wait
on the carrier model being loaded, before proceeding with FDM init.
This allows the FDM to see the correct carrier model in the ground
cache, and hence avoids starting in the water.
To implement this, the CheckSceneryVisitor is used to force the carrier
model to be loaded while the splash-screen is visible.
In some testing, JSBsim sometimes passed extremely large values into
this function (larger than the radius of the earth). This causes
every tile on the planet to be scheduled if using the standard STG
terrain, effectively blocking startup.
This code allows us a chance to catch this case via logging, but does
not fix the underlying issues.
The problem is that the two aren't functionally equivalent; the Nasal version would fail silently - whereas the new C++ version gave a runtime error.
The immediate fix is therefore to simply remove the runtime error.
The bug fix is:
- if (!log.output) {
+ if ( !(*log.output) ) {
(i.e., testing the sg_ofstream instance instead of its address) and then
ensuring that the corresponding Log instance is removed from _logs and
destroyed.
The "destroy" part is made automatic by using std::unique_ptr instead of
raw pointers. This allows to simplify several areas of the code.
Don't provide custom definitions for the constructor and destructor of
FGLogger anymore, now that they don't need to do anything: IIRC, this
allows compilers to do some optimizations according to the C++ standard.
Since the paths of files overwritten by FGLogger come from the property
tree[1], they must be validated before we decide to write to these
files.
[1] Except for the "empty" case, which uses the default name
'fg_log.csv'. This file is deemed acceptable to overwrite in the
current directory, as the name is completely fixed and clearly
FG-specific.
Call fgInitAllowedPaths() right after Options::processOptions() (which,
among other things, determines $FG_ROOT and processes
--allow-nasal-read). This way, fgInitAllowedPaths() can be used in much
more code, such as when initializing subsystems.
Improve performance of Nasal properties access
by implementing the setValues/setChildren props.nas
functions in C++. Naive implementation effectively
copying the Nasal versions verbatim.
However, on a test suite writing 1000 Canvas paths,
results in a 50% reduction in runtime, and significant
reductions in memory occupancy.
On a much larger task (5500 paths) results in a 30%
reduction, probably due to Nasal GC.
Use base 26 numbering with letter-only digits for resource indices in
the C++ files generated by fgrcc. This is needed because, for instance,
'resource10' appears not to be a valid C++ variable name, mpfff...
Translations/en_US/FlightGear-nonQt.xlf is for a proper English
translation, where for instance "found %n airport(s)" would have two
plural forms, "found %n airport" and "found %n airports" (most
non-plural strings can be taken verbatim from the default translation,
and at this point there is no plural form at all yet).
As they are registered here, the files will have virtual paths such as:
/Translations/de/FlightGear-nonQt.xlf
/Translations/en_US/FlightGear-nonQt.xlf
etc.
for the EmbeddedResourceManager ('/' being the default virtual prefix).
This reduces the log noise in release builds, relating to AI ground-nets
with incomplete data, especially the commonly occurring ‘gate XYZ
doesn’t seem to have any routes associated with it’ message.
https://sourceforge.net/p/flightgear/codetickets/1974/
Updating the value takes immediately, as it did in 2017.1 and prior.
Additionally, passing —download-dir on the command-line is detected
and handled specially; the UI option is disabled, and no changes are
made to the value passed in. (The launcher does not override the value
with any value it has saved)
using --addon=/foo/bar does
* add /foo/bar/config.xml as propertyfile
* add /foo/bar to aircraft_paths to provide read-access
* sets property /addons/addon[n]/path = "/foo/bar"
* addons get initialized from addons.nas in FGDATA/Nasal
Change fgcommand to take an optional property tree root element.
This fixes the animation bindings to use the defined property tree root - to support multiplayer (or other) model that can bind to the correct part of the property tree.
Requires a corresponding fix in sg to allow the command methods to take an optional root parameter.
What this means is that when inside someone else's multiplayer model (e.g. backseat, or co-pilot), the multipalyer (AI) model will correctly modify properties inside the correct part of the property tree inside (/ai), rather than modifying the properties inside the same part of the tree as the non-ai model.
This means that a properly setup model will operate within it's own space in the property tree; and permit more generic multiplayer code to be written.
This is probably responsible for some of the pollution of the root property tree with MP aircraft properties.
Ground-bit is set manually (via the transponder GND knob position) or
automatically using a property referenced in instrumentation.xml.
Aircraft will only transmit these new properties when using the
multiplayer v2 protocol.
This adds console and message-box warnings, based upon aircraft
declaring the minimum FG version they support. A follow-up commit
will extend the launcher UI to warn the user about this in a nicer
way.
This is a headless mode, designed to be invoked from an installer, not
used directly by users. It doesn’t touch the ‘normal’ installation, but
rather removes the other files FG typically creates or downloads.
When building with MSVC, use the CMAKE_MSVCIDE_RUN_PATH variable to
prepend ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/bin to the PATH in
order to (hopefully) allow fgrcc to find the libraries it needs. We may
need to add something similar for SimGear---will see.
The use of CMAKE_MSVCIDE_RUN_PATH and other ways to address this problem
are discussed at
<https://stackoverflow.com/questions/28533012/how-to-set-runtime-path-for-cmake-custom-command-on-windows>.
${CMAKE_SOURCE_DIR}/src/EmbeddedResources/FlightGear-resources.xml
(currently empty) is automatically "compiled" into
${CMAKE_BINARY_DIR}/src/EmbeddedResources/FlightGear-resources.[ch]xx by
fgrcc inside the build directory. These files are incorporated into the
FlightGear build (FlightGear-resources.cxx is linked into FlightGear).
When the XML embedded resource declaration file added here,
FlightGear-resources.xml, is compiled, fgrcc is passed the
--root=${CMAKE_SOURCE_DIR} option, so that files referred to in
FlightGear-resources.xml are looked up relatively to the root directory
of the FlightGear repository. One could use a second XML embedded
resource declaration file compiled with a different --root option to
grab files from FGData, for instance. I would name such a file
FGData-resources.xml to be consistent with the current naming scheme.
Note: this --root option applies to the paths of real files. Don't
confuse it with the 'prefix' attribute of <qresource> elements
inside XML resource declaration files (such as
FlightGear-resources.xml), which applies to the virtual path of
each resource defined beneath.
The commands in src/Main/CMakeLists.txt ensure that
FlightGear-resources.xml is recompiled with fgrcc whenever it is
changed, and obviously also when FlightGear-resources.cxx or
FlightGear-resources.hxx is missing. However, CMake doesn't know how to
parse fgrcc XML resource declaration files, therefore when a resource is
modified but the XML file it is declared in is not (here,
FlightGear-resources.xml), you have to trigger yourself a recompilation
of the XML resource declaration file to see the new resource contents
inside FlightGear. The easiest ways to do so are:
- either update the timestamp of the XML resource declaration file;
- or remove one or both of the generated files
(FlightGear-resources.cxx and FlightGear-resources.hxx here).
The EmbeddedResourceManager is created in fgMainInit() just after
Options::processOptions() set the language that was either requested by
the user or obtained from the system (locales). Resources from
FlightGear-resources.cxx are added to it, after which
EmbeddedResourceManager::selectLocale() is called with the user's
preferred locale (obtained with FGLocale::getPreferredLanguage()).
Upon reset (fgStartNewReset()), EmbeddedResourceManager::selectLocale()
is called in a similar way after Options::processOptions(), however in
this case the EmbeddedResourceManager instance doesn't have to be
recreated.
- remove use of boost in src/Main/locale.cxx;
- add missing header <cstring> for std::strlen();
- replace NULL with nullptr;
- fix some broken indentation;
- other small readability improvements.
This function returns the preferred "locale"[1] according to user choice
and/or settings (i.e., it is influenced by --language if passed,
otherwise by current locale/system settings). The return value never has
an encoding part. It is the empty string if nothing could be found,
otherwise should look like fr_BE or it_IT.
[1] "language" term used in the function name for consistency with the
existing and related FGLocale::selectLanguage().
Windows and Mac implementations return a string without any encoding
specifier -> remove this specifier directly in the Unix/Linux
implementation for consistency.
Also do some small refactoring with the new static method
FGLocale::removeEncodingPart(). Slight difference with the previous
algorithm: if a '.' is found in the given locale spec, we assert() that
it is not the first character. The previous code in
FGLocale::findLocaleNode() used to consider such weird locale specs
starting with a dot as normal locale specs without any encoding part.
Note: the same change could be done where FGLocale::findLocaleNode()
looks for an underscore in order to prepare for the fallback
search (e.g., 'fr' after not finding translations for 'fr_FR').
The wake induced force and moment are computed as an external reaction to the JSBSim model. For these force and moment to be accounted for by JSBSim, the following external reaction needs to be added to FDM XML definition:
<external reaction>
<force name="ai-wake">
...
</force>
<moment name="ai-wake">
...
</moment>
</external reaction>
This is similar to how the hook and wire feature is modeled in JSBSim.
Wake computations are now performed for all AI aircrafts within a range lower or equal to the value indicated by the property /fdm/ai-wake/max-radius-nm.
These computations are triggered by the property /fdm/ai-wake/enabled (it is disabled by default).
The result of the wake computations is not yet used by the FDMs so do not expect the user aircraft to react to the AI wake.
AI wake code is still dead code except that it is now compiled with FG.
Input data for wake computations are extracted from the performance database. The data must be specified as follows (values are for illustration only) :
<geometry>
<wing>
<span-ft> 100. </span-ft>
<chord-ft> 12. <chord-ft>
</wing>
<weight-lbs> 90000. </weight-lbs>
</geometry>
At the moment, this is dead code: only the tests are compiled. FG is still compiled without this code.
A new directory is created that contains all the numerical computations made to estimate the wake induced by AI aircrafts. This is based on the venerable Vortex Lattice Method (VLM) which was all the rage in the 60's Computational Fluid Dynamics (CFD).
Even though quite old, the method is relevant to compute aircrafts wake in real time since 3D Navier-Stokes (NS3D) is out of reach for real time computations even with modern multicore personal computers and their GPUs.
Use owning pointers in GraphicsWinQt to own the GLwindow and QOGLContext,
so shutdown is more orderly, especially when driven from the OSG or
window-manager, as opposed to an ‘internal’ quit.
In order to compute the AI aircrafts wake, the FDM will need access to the list of AI aircrafts as well as being able to compute their range to discard aircrafts which are too far.
In the thread at
<https://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/87tw7sm5uw.fsf%40frougon.crabdance.com/#msg35673402>,
it was decided that alignLocaliserWithRunway() was a bad idea overall,
and should just be removed. The feature was already disabled by default
in recent releases via defaults.xml (since FlightGear 2017.1, precisely
FGData commit ea76305e42fd245e79a2b5bb569c8c61161f5721). Remove the code
entirely now.
The properties /sim/navdb/localizers/auto-align and
/sim/navdb/localizers/auto-align-threshold-deg have no effect anymore,
you may remove them from your configs if you somehow set them.
This goes with FGData commit 6dd9f6e8d962b00a1ccddc6af487c404cc935b92.
In case someone wanted to reuse the removed code, please consider
Szymon's proposed change at
<https://sourceforge.net/p/flightgear/flightgear/merge-requests/76/>,
which was:
,----
| Fixed bug in alignLocaliserWithRunway when building NavCacheDb
|
| The position of the localizer was converted to a distance from
| the displaced threshold, and then back to the posistion on the
| centerline, but the origin of the second computation was
| non-displaced threshold.
|
| --- a/src/Navaids/navdb.cxx
| +++ b/src/Navaids/navdb.cxx
| @@ -104,8 +104,8 @@
| void alignLocaliserWithRunway(FGRunway* rwy, const string& ident, SGGeod& pos, double& heading)
| {
| assert(rwy);
| - // find the distance from the threshold to the localizer
| - double dist = SGGeodesy::distanceM(pos, rwy->threshold());
| + // find the distance from the (non-displaced) threshold to the localizer
| + double dist = SGGeodesy::distanceM(pos, rwy->geod());
|
| // back project that distance along the runway center line
| SGGeod newPos = rwy->pointOnCenterline(dist);
`----
There was a couple of typos in the routine. This code will be used by the AI wake feature.
Also added a test for the matrix code to make sure they will be no regression.
External moments can now be specified in addition to external forces. This feature is needed for the AI wakes.
Headers clean up to reduce the amount of recompilation when modifying an header file.
Print an error message and exit if --{enable,disable}-enhanced-lighting
or --adf are used (those deprecated options will be removed in a future
version of FlightGear).
As spotted by Thorsten, reduce user annoyance by asking about FGData
when the built-in data is acceptable. (Advanced users can use the
launcher or other options to change FGdata as normal).
* Skip the gears when located over water. They will be skipped by the ground reactions anyway making the trim irrelevant.
* Ignore the ground bumpiness during the trim. The trim algorithm seems not to
be robust enough to handle that. This does not make much difference to the
converged solution anyway since the bumpiness is generally low.
* Fixed the WOW status for contacts over water (was 'false' is now 'true').
* All the gear/contact data are now properly reset when WOW==false. The reset
code is now common to all the case where WOW is false.
When the user specified an MP server without providing a port, the
launcher would pass a malformed command line, leading the the simulator
bailing out.
(Should go to the release branch)
Add defensive logic to ensure that a null pointer isn't dereferenced. This happened to me once or twice during a reinit (Location/Position In Air to the current position). It may be related to the model, but in any case the code needs to ensure that the static cast failure is handled correctly.
2017.2 in compatible mode was not compatible with 2017.1.x because the V1 packet had V2 properties in it; the protocol version and the new launchbar encoding - both of which should not be transmitted. This only affected 2017.1 because it discards the rest of the packet once an unknown property is encountered (to increase reliability).
Add support for per property encoding.
- encode_for_transmit - method that will convert from and to the packet for the value.
- decode_received - decodes received data
The options.cxx code is not ready to handle recursive use of --config
(for config files). Instead of failing in an ugly way, abort with a
clear error message in such situations. See discussion at
<https://sourceforge.net/p/flightgear/mailman/message/35838852/>.
Note: it *is* possible to load XML PropertyList files from config files,
so --config is not entirely "banned" from config files.
+ add missing include
New Nasal method get_cart_ground_intersection
Returns where the given position in the specified direction will intersect with the ground. Returns whether or not a certain position and direction pair intersect with the ground, and if so the intersection point.
Useful for radars, terrain avoidance (GPWS), etc.
Input parameters:
1. vec3d(x,y,z) position
2. vec3d(x,y,z) direction
Returns nil or geod hash (lat:rad,lon:rad,elevation:Meters) intersection
Example Usage:
var end = geo.Coord.new(start);
end.apply_course_distance(heading, speed_horz_fps*FT2M);
end.set_alt(end.alt() - speed_down_fps*FT2M);
var dir_x = end.x() - start.x();
var dir_y = end.y() - start.y();
var dir_z = end.z() - start.z();
var xyz = { "x":start.x(), "y" : start.y(), "z" : start.z() };
var dir = { "x":dir_x, "y" : dir_y, "z" : dir_z };
var geod = get_cart_ground_intersection(xyz, dir);
if (geod != nil) {
end.set_latlon(geod.lat, geod.lon, geod.elevation);
var dist = start.direct_distance_to(end)*M2FT;
var time = dist / speed_fps;
setprop("/sim/model/radar/time-until-impact", time);
}
-----------
Nasal method aircraftToCart : This allows easily computing offsets in aircraft-relative coordinates, and converting to global cartesian (ECEF) reference frame.
This has the advantage, according to my testing on Linux, that core
files obtained after a crash now point to the crashing thread again,
when one starts 'gdb' on the core file and runs the 'bt' command.
Apparently, when using kill(), the signal is seen as coming from the
outside and gdb's 'bt' command points to the wrong thread in general
when debugging using a core file (when debugging "live", gdb intercepts
the signal even before FG's signal handler is started).
See discussion starting at
<https://sourceforge.net/p/flightgear/mailman/message/35833221/>.
Add an additional visibility flag to the menubar implementations,
conditional on whether or not the menubar overlaps the window content.
(I.e for PUI but not Cocoa). This flag is linked to a new property
/sim/menubar/overlap-hide, which the renderer drives off the splash-
screen visibility.
On Windows, use:
- QtFileDialog if FG was built with Qt support;
- PUIFileDialog otherwise.
Behavior on other platforms is unchanged. This change is motivated by
the fact that some Windows users have reported[1][2] weird,
non-deterministic behavior of WindowsFileDialog and unfortunately, no
one seems to be willing and able to fix the problem. The Qt
implementation comes for free and should be quite robust. Of course, if
someone wants to maintain the WindowsFileDialog class again, the change
can be reverted.
See discussion at [3].
[1] https://forum.flightgear.org/viewtopic.php?f=25&t=31945
[2] https://sourceforge.net/p/flightgear/mailman/message/35761650/
[3] https://sourceforge.net/p/flightgear/mailman/message/35759819/
This fixes handling of non-ASCII splashscreen text for me (Debian
GNU/Linux). The XML input files don't technically *have* to be encoded
in UTF-8, as long as they properly declare the encoding and it is
supported by Expat. Of course, we prefer UTF-8 nowadays.
With this commit, startup tips and splash screen progress strings
("Loading scenery", "Initializing subsystems", etc.) can at last be
written correctly in languages that need non-ASCII characters.
The Expat doc is unfortunately unclear on its *output* encoding, saying
the following (expat.h):
The characters are passed exactly as they were in the XML document
except that they will be encoded in UTF-8 or UTF-16.
The only relevant header I can see in SimGear is
3rdparty/expat/sg_expat_external.h, which has interesting stuff around
XML_UNICODE, however it doesn't seem to take position.
I fear that whether UTF-8 or UTF-16 is used for Expat's output (and thus
for what easyxml.cxx gives us) depends on how it was compiled. Let's
hope everyone has it compiled for UTF-8 output...
In commit 15525aab58, a layer with
lapse=0.0 was added to ISA_def (atmosphere model). However, the last
layer *must* have lapse == -1.0, otherwise the code in PT_vs_hpt()
doesn't know when it's on the last element of ISA_def, and does an
illegal memory access with (pp+1)->height. This is why -1.0 is the
default value for lapse ('l') in the ISA_layer constructor.
Fix: add the -1.0 terminator to the last element of ISA_def.
When the test:
if (i == activeTraffic.end() || (activeTraffic.empty()))
was true, the iterator named 'current' was uninitialized and later
dereferenced.
Fix:
- when the previously-mentioned test is true, return;
- initialize 'current' only when it is really needed (i.e., later and
after the test), and since we don't need it for iterating, make it
an FGTrafficRecord&.
- Don't ignore pushbackRoute="0".
- Stricter parsing with precise log messages when the input is
incorrect.
- Add missing includes in src/Airports/dynamicloader.cxx.
See <https://sourceforge.net/p/flightgear/mailman/message/35788373/> for
the discussion about this change.