As of 2020-08-01, OpenBSD's system zlib is 1.2.3 which doesn't
have gzoffset(). However we can get away with this by making
gzfilebuf::approxOffset() always return zero.
Avoid a central hash cache becoming enormous, now we use the selective
download scheme for the tile dirs.
Hash name is changed to co-exist with older versions.
Use the top-level dirIndex files to determine if a 1x1 tile dir
exists, instead of proving the server via a 404. This reduces the
number of requests we make considerably, which is … important.
Add a process() method to HTTPRepository, and use this to
incrementally validate subdirs after the .dirIndex is received. This
avoids large pauses of the TerraSync thread, when all of Airports/
is validated at once.
When doing a catalog migration to a new ID (eg, 2018 -> 2020), also
mark the installed packages for installation, on the new catalog.
Related to this, when manually removing a catalog, record this fact,
so we don’t re-add it automatically due to migration.
Add unit-tests covering both of these cases.
Trying to fix a reported crash, in this code. malloc() returning null
seems unlikely but worth checking for. ALso use a unique_ptr with
a custom deleter to avoid a leak if we throw.
Sentry-Id: FLIGHTGEAR-3Y
If TerraSync/Airports is missing, download Airport_archive.tgz instead.
In all other cases update as normal. This has the effect, that fresh
installs make many fewer requests to TerraSync servers.
Re-add (with some tweaks) the persistent tile-cache code, so that
TerraSync checks the server at most once per 24 hour period, for a
given repository path.
(Disbale the cache by setting /sim/terrasync/enable-persistent-cache=0)
New log-level to avoid using ‘ALERT’ for expected mandatory messages,
since I want to do error collection on real alerts in a future commit.
As part of this, split logstream.hxx into separate header files, and
add a new virtual hook to LogCallback which takes the complete log-entry
Ensure that if we copy file-names of log entries while startup
logging is active, we free them, but only once startup logging is
disabled, or on shutdown. This is needed to avoid crashes when
we use file-name copying for the Qt message handler.
Previous additional checks for a value BUILDING_LIST entry
used an enum incorrectly, resulting in all BUILDING_LIST entries
failing. Now fixed to check bad() / fail() which are bool.
Caching it complicates add/remove command logic, so making a simple
fix for now, which can be back-ported to 2020.2; ideally we would
cache the pointer but have an invalidation scheme, but that’s
considerably more work and risk.
Relates to Sentry crash:
https://sentry.io/organizations/flightgear/issues/1858764364
Spotted by valgrind, w00t. If you used a numerical formatter, such
as f,d or g, with. a nil value, we would read uninitialised data, and
generally get confused.
We had some confusion between two error codes, meaning we would log an
error (and treat as a failure) a pure ocean 1x1 area, even though this
was entirely correct and expected behaviour.
Terrasync.cxx expected REPO_ERROR_NOT_FOUND, we need to convert the
file-level error to that, and avoid logging a warning.
Fix various cases where re-init could get things blocked. Remove the
duplicate storage of the active paths; now we always check the primary
data, and hence it can’t be out of sync.
Also remove the obsolete persistent cache code.
Fixes some of the issues discussed in:
https://sourceforge.net/p/flightgear/codetickets/2308/
Further improvements still to come, especially to retry on a better
schedule for intermittent connections.
It seems that clang++ headers #include <version>, which found simgear/version
because we need to put singear/ in include path for some code to compile.
simgear/props/props_test.cxx: test for self-unregister.
SGPropertyNode::removeChangeListener() used to modify the _listeners vector or
even delete it and set _listeners to NULL, if a listener was removed.
This could cause a SEGV if removeChangeListener() was called from
a listener, because listeners are called from methods such as
SGPropertyNode::fireValueChanged() which iterate through _listeners and don't
expect it to be changed to NULL.
The fix here is to keep a track of whether we are iterating through the
_listeners vector; if we are, SGPropertyNode::removeChangeListener() sets the
entry to NULL, instead of removing it.
We have a new internal function forEachListener() which takes
care of the iterating details - incrementing/decrementing the new
_listeners->_num_iterators count and skipping NULL entries. Before returning,
if _num_iterators is now zero it removes any NULL entries in the vector of
listeners.
The nListeners() member is no longer inline, because it needs to ignore NULL
entries in the vector. And _listeners now points to an internally-defined
struct which contains a new _num_iterators as well as the vector of listeners.
Added self-unregister test to simgear/props/props_test.cxx.
It is possible to have a property tree with
/sim/rendering/scenery-path-suffix[n]/enabled=true
/sim/rendering/scenery-path-suffix[n]/name=<blank>
Previously this would be downloaded as scenery//[tile]
Now we just ignore such invalid paths.
Previously we required 6 shader attributes to pass
in all the required information for the building shader.
By using packing techniques this has been reduced to 4.
This should improve support for integrated graphics cards.
making the build between Simgear and Flightgear consistent.
- Fix an issue with lib/lib64 path between CentOS/RedHat distributions
and Debian derived distributions.
Some AMD drivers do not like triangles for point sprites, which
breaks directional lights. This works around this by allowing
users to set /rendering/triangle-directional-lights=false which
falls back to the non-directional implementation of a point.
logstream::LogStreamPrivate::log() sets line=-1 to turn off both filename and
line numbers in log output, if m_fileLine is false.
StderrLogCallback::operator() already omits both file and line if line == -1;
this commit does the same thing for FileLogCallback::operator().
E.g. this fixes output e.g. to ~/.fgfs/fgfs.log.
The deadlock is possibly caused by the thread not being joined, or because of an implementation difference with phtreads.
So this fix adds a call to release the background thread when terminating it and then also joins the thread to await for the completion of the background thread.
As before this works fine under Win32 (x64)
Previously the front and side faces of random/OSM buildings
had identical texture coordinates. This resulted in the sides
of buildings texture mapping being squeezed or stretched.
This change generates a separate texture mapping for the sides
of the buildings.
Plantations are regularly spaced vegetation. This effect is switched
on by the is_plantation material property. Vegetation is laid out
at integer spacings in x and y, with the spacing determined by the
usual coverage properties.
remove special characters from output. We used to include 0xb0 characters -
small 'o' degree symbol, but this isn't reliable and looks bad in flightgear's
weather window.
Consistently use space between number and its unit.
remove 'METAR Report' header.
Fix a bug in the roof transformation that meant the
roof ridges were not sized correctly. Also change
the texture "unit" width for small buildings from 6m
to 5m following discussions with Rick Gruber-Riemer.
Now we no longer list OpenAL a s apublic dependency of SimGear, we
need to explicitly link the tests against OpenAL, since they use it
directly, in all cases.
Previously the width was set as the x-axis and
depth for the y-axis when passed through to the
shader. This was incorrect, as the x-axis is actually
the depth of the building.
Previously there was very limited texture variations
as a given texture index was used for both the wall
and ceiling. Now these can be specified separately,
allowing for more variation in both STG defined and
random buildings.
Replace existing random buildings implementation with one using
proper instancing. This allows better control of the buildings
themselves and allows BUILDING_LIST STG verb to specify
individual building dimensions. See README.scenery for details.
The updateInterval argument is used a lot less than the dependency list, so
these have been swapped. That simplifies the registration code in the subsystem
implementations as the updateInterval default of 0.0 no longer need to be
supplied.
This is a partial reversion of c1dd8faa29 and a
complete reversion of caea68007e and
846f024e91. These changes are incompatible with
the subsystem class IDs.
This is a clean up commit prior to the subsystem API standardisation to simplify
the diffs. It includes all SGSubsystem and SGSubsystemGroup derived classes.
This uses an SGThreadExclusive controlled by Emesary notifications that are received from the main loop.
When active at the end of a frame the garbage collection thread will be released; if it is already running this will do nothing. Optionally at the start of the mainloop we can wait for the previous GC to finish.
The actions of the background GC is controlled by notifications - again received from the main loop which in turn uses properties.
I initially thought that the wait at the start of the frame would be necessary; however in 100 or so hours of flight without the await for completion at the start of frame no threading problems (or any other problems) were shown; so nasal-gc-threaded-wait is defaulted to false which gives a slight boost in performance.
So what this does is to it removes the GC pause of 10-20ms every 4 seconds (test using the F-15). This change doesn't really give much extra performance per frame because normally GC is only performed when needed.
An exclusive thread is one that is suited to being used where the thread needs to be activated at a certain point, and also that the code activating the thread may also need to wait for thread completion.
Example of this is the new background garbage collection for Nasal. The thread will be activated at the end of the frame processing and at the start of the next frame the thread can be awaited - thus allowing the thread to work in parallel with the rendering.
rework to measure the required length (vsnsprintf does this with a size of zero and a nullptr as the first parameters) - and then just alloc the required space. Should be more efficient than the looping version.
- Added light definitions to the model XML files. This is not compatible with Rembrandt.
- Added depth slicing.
- Added threading support. For now it's faster to run everything on the main thread since there aren't many lights.
derived from: https://github.com/Zaretto/Emesary/tree/master/src/Emesary/EmesaryC++
This is a similar implementation to that in Nasal; currently this is only for use in C++ modules as there is no Nasal interface - however this is something that may be added later.
The basic premise of the Emesary messaging system is to allow the decoupled operation of the various components that comprise any system - usually within the same process.
The basic unit of communication is a Notification, which is passed around to any and or all objects that implement the IReceive interface (pure virtual class). Using Interfaces and ihneritance
it is possible to pass around Notifications that have special meanings to certain objects and allow them to perform the appropriate function.
Notifications are created and sent via a call to NotifyAll. Any object within the system can inherit from IReceive and register itself with a Transmitter to receive all notifications that are sent out.
The underlying concept is that one part of a system knows that something needs to be done without needing to know how to do it. The part of the system that needs something done simply creates a notification and sends it out. Once received by the part of the system that is capable of performing the requested Notification the relevant actions will be carried out and a status of OK or Finished returned.
The return code from the Receive method must follow the guidlines as follows:
If a notification is not recognised in the recipient must return ReceiptStatusNotProcessed. Normally a recipient will return ReceiptStatusOK, sometimes ReceiptStatusFail to indicate that the recipient could not properly process the notification.
The overall result of a call to NotifyAll is a composite of the results of each individual recipient's return value; and generally OK or Fail. It is acceptable to use the return code to ascertain success or failure and take appropriate action.
It is generally recommended that more detail specific to the particular purpose be included within the Notification to allow more control.
Notifications can be modified during processing to permit a multistage process; however this needs to be designed correctly.
* ReceiptStatusOK : Notification processed fine by Receive, transmitter continues with next recipient
* ReceiptStatusFail : Notification processed but failed, transmitter continues with next recipient
* ReceiptStatusAbort : Notification processed and the receive method declares a fatal error; the transmitter will stop notifying recipients
* ReceiptStatusFinished : Notification processed and the recipient declares that the processing is completed, the transmitter will stop notifying recipients
* ReceiptStatusNotProcessed : receive method does not recognise the notification
These status are for later implmentation.
* ReceiptStatusPending : (future ues); notification been sent but the return status cannot be determined as it has been queued for later processing, transmitter continues with next recipient
* ReceiptStatusPendingFinished : Message has been definitively handled but the return value cannot be determined. the transmitter will stop notifying recipients
- change to always use the SG create mipmap function as it works better (no purple clouds)
- when enabled always generate a mipmap even if the file couldn't be compressed
- adjust level of log messages
- move lru_cache into its own header file.
The following changes fixes a case for me where I hear the sound change levels up and down for each pause un-pause cycle.
Patch provided by daniel.c.wickstrom@gmail.com.
Effect schemes are a way of rendering an object in different ways depending on the Compositor pipeline. A new <scheme> tag in the Compositor pipeline definition allows the user to choose which Effect scheme is going to be used for that pass. Every Effect will then be rendered using the technique that has a matching scheme name. If no valid technique is found, it won't be rendered. Since it would be a pain to define a valid technique for every scheme and for every Effect, the file '$FG_ROOT/Effects/schemes.xml' is introduced:
<scheme>
<name>test</name>
<fallback>Effects/test</fallback>
</scheme>
If an Effect doesn't have a valid technique for the 'test' scheme, the 'Effects/test.eff' Effect will be merged with it. This process is done at initialization when techniques are being realized.
Previously, these two files were only added when SG was built with
-DUSE_AEONWAVE:BOOL=OFF, because the SG code in use when USE_AEONWAVE is
set to ON doesn't need readwav.hxx nor readwav.cxx. However, readwav.hxx
and readwav.cxx are not only used in SG, but also in FG (at least by
flightgear/src/Sound/VoiceSynthesizer.cxx), and this was causing a build
failure when SG's USE_AEONWAVE and FG's ENABLE_FLITE flags were both set
to ON:
https://forum.flightgear.org/viewtopic.php?f=45&t=35672#p346633
and
https://sourceforge.net/p/flightgear/mailman/message/36645567/
This commit should fix this build failure.
- remove the old svn properties; a scan of FGAddon and FGdata showed these are not in use except for the dialog
- new property "active" - which is true when the worker thread is running.
- changes to enabled now take effect immediately; whereas before a reinit had to be issued. This could lead to confusing GUI state as the enabled property would be true but without closing the dialog (e.g. cancelling it) terrasync could be in a different state.
- use property nodes (performance optimisation)
Extend the command API to allow posting commands from arbitrary threads,
for deferred execution on the main thread. Additional pieces on the FG
side to follow shortly.
changed to use const char* rather than const std::string & as this doesn't work on GCC; and besides std::string converts nicely to const char* and most of the times this is used it is actually a string literal.
Set the filename back to what it was after loading - seems sensible and as yet no side effects.
Also the previous commit that included the handling of sgio_exceptions also broke the DDS-TC pretty much completely.
State machines will now throw exceptions if errors are encountered
when loading the XML file.
This includes:
- Unknown <source> or <target> states referenced by transitions
- States and transitions without <name> elements
- Transitions without <target> or <condition> elements
- State machines with fewer than two states
Previously the state machine would load and then crash when hitting
such malformed states or transitions. Now it will refuse to load,
while providing useful error messages as to the problem.
This is to help diagnose where performance is being used and augments the current performance monitor.
The easiest way to active this is to open the performance monitor; however setting the enable property will enable less intrusive logging and overrun detection.
Using the GUI performance monitor itself affects the performance when it updates.
Properties
/sim/performance-monitor/enabled - need to be true to be active (unchanged)
/sim/performance-monitor/dump-stats - hierarchical dump to console of all current timing stats for all subsysems
/sim/performance-monitor/interval-s - reporting interval (unchanged)
/sim/performance-monitor/max-time-per-frame-ms - any subsystem that takes more than this amount of will be logged to the console
This will use the inherently unsafe versions of the load methods which can result in deleting an object (from the cache) that has just been loaded in the database thread.
Symptom OSG WARN deleting still referenced object.
- use a file contents hash instead of filepath.
- add a local lru cache for filepath->hash (for performance improvements)
- calculate and resize to nearest power of two
- handle normal maps and images from effects differently.
- when cache is active any image that can't be converted to a dds will have a mipmap generated (which still helps the loading process); although this may be responsible for introducing purple into transparent images..
This should have been in the previous commit - However I managed to mess up the merging of this module due to other changes related to the DDS texture cache.
Possibly this could be fixed better by using the plugin string data - but there is nothing that currently set this; and it seems easier to use the particle callback enabled flag.
Remove would_log() : callbacks receive all log messages so they can
do custom filtering individually.
Also move popup message handling into the private (d-ptr) of sglog(),
to keep the header as minimal impossible (no include of <vector>)
1. Anything that comes in from OSG will always be logged; it seems
somewhat redundant to have to set the FG log level to be identical to
the OSG log level to see these messages.
2. Console output will now have delta time (since start), priority and class.
3. Log file output wil also have delta time (since start), priority and class.
Times are displayed as delta decimal seconds since the logger was created
e.g.
1294.06 [INFO]:terrain Some log message
This is a performance improvement that reduces the amount of frame pauses which are related to mipmap creation when the geometry (osg::Texture) is added to the scene graph within osg::Texture::applyTexImage2D_load
The texture cache is configured from FG as follows
- /sim/rendering/texture-cache/cache-enabled
- /sim/rendering/texture-cache/compress-transparent
- /sim/rendering/texture-cache/compress-solid
- /sim/rendering/texture-cache/compress
These properties are set via the SGSceneFeatures singleton.
When the texture cache is enabled it will auto convert files from any supported osg::Image format that can be read and store the resulting (compressed or raw) file in the texture cache.
The texture cache uses osg_nvtt to perform texture compression (and mipmap generation) if available. When not available simgear::effect::computeMipmap is used to make mimaps but compression isn't available.
The texture cache filename ends with .TIME.cache.dds where TIME is the hex modtime of the original file. As yet there isn't a clean way to maintain the texture cache to ensure that stale files are removed; and in fact this is quite difficult to do because of the dynamic nature of the cache.
The texture cache will be stored in download_dir/texture-cache unless --texture-cache is passed on the command line.
The UI has a single checkbox to turn the texture cache on or off.
This was something that happened when random vegetation was off, but tree shadows was on.
Adding random vegetation would then reliably cause an exception.
Under Basic Weather, the cloudfield is finite size and clouds
are shifted as the viewpoint changes. Previously each cloud
was checked every frame to determine if it should be shifted.
Not this only occurs if the viewpoint has moved a non-trivial
distance.
Note that this is separate from the clouds moving due to the wind.
This is fixing an issue identified in the launcher in a secondary way,
to ensure if another user of the API tries to schedule an already
scheduled package, we ignore the second request.
When adding/remove subsystems to a group which is already bound or
inited, transition the subsystem automatically. This removes the
need to manually transition the subsystem in various places in
Flightgear.
The vector is now a static function variable that is returned by reference by
the new getGlobalRegistrations() function, which remains in the anonymous
namespace.
This solves the issue of the global_registrations vector being populated during
static init, but then been subsequently allocated and hence reset at the end of
static init.
Migrate and update these commands from FlightGear’s subsystem factory.
Currently disabled until subsystem-factory is removed, to avoid
duplicate registration.
Groups track their state, which will enable them to correctly transition
added and removed children in the future. Only stubbed for now, to avoid
breakage on the FG side.
- track more meta-data and a factory function for each subsystem,
registered either explicitly or via a helper static class.
- add a delegate to receive notifications of subsystem changes
- make sub-grouped subsystems work more naturally, especially for
child lookups
- add some test coverage for all of this
When CMAKE_BUILD_TYPE is Debug and we are compiling with GCC, add the
following options to CMAKE_C_FLAGS and CMAKE_CXX_FLAGS:
-O0 -fno-omit-frame-pointer -fno-inline
Ditto for Clang, except that -fno-inline-functions is used instead of
-fno-inline.
cf. thread starting at
https://sourceforge.net/p/flightgear/mailman/message/36295412/
The new function logstream::setTestingMode() has been created to allow for a
testing mode to be set. This stores a boolean in the private logstream thread
which modifies the behaviour of the would_log() function, allowing for
everything to be logged. The removeCallbacks() function has also been added,
allowing for the default fgfs output to STDOUT and STDERR to be silenced when
calling setTestingMode().
Add test coverage for disabling a catalog due to version, and also
for auto-migrating to a new version. Expose disabled catalogs on the
Root, so they can be checked for.
Since the dawn of times (FG commit
1bcaf4bfdd38f18ac7c375dd9319935ff3df56ac, where SGBinding was called
FGBinding), SGBinding's destructor has had a strange behavior:
SGBinding::~SGBinding()
{
if(_arg && _arg->getParent())
_arg->getParent()->removeChild(_arg->getName(), _arg->getIndex());
}
In other words, it used to remove the passed-in <binding> node from its
parent node (if any) once the SGBinding instance got destroyed. This
behavior is very unintuitive to several people and has resulted in a few
workarounds in the FG code base just to cope with this strangeness.
This commit gives SGBinding the implictly-generated destructor,
therefore SGBinding::~SGBinding() does not attempt to remove the
property node anymore.
See disussion at:
https://sourceforge.net/p/flightgear/mailman/flightgear-devel/thread/87d12b1h0h.fsf%40frougon.crabdance.com/#msg36190666
this is to use some kind of utc time for timestamps in mp protocol,
to improve the lag correction system for mp planes, using a
"real time" mode when possible.
Remove an apparently bogus portability workaround (which was presumably
targetting one of the bugs fixed in the previous commit [1]) and further
simplify the code using std::find().
[1] da099d4312/
Explicitly enable the CMP0067 policy to have try_compile use the correct
C/C++ standard flags; otherwise, CMake will default to not honoring those,
causing the C/C++ checks to be compiled with no standard flags and SimGear
to be compiled with them. This causes errors if we try to detect a new
prototype which is only present in C++14 and above).
Indent the test code in a nicer way and shorten it, taking advantage of
this guarantee from the C++ standard:
If control reaches the end of main without encountering a return
statement, the effect is that of executing return 0.
-> no need for "#include <cstdlib>" nor for "return EXIT_SUCCESS".
Define HAVE_WORKING_STD_REGEX if, and only if <regex> is usable.
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.
[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/
Calling a virtual method in a destructor has undefined behaviour.
Furthermore passing 'this' to nasal from within the destructor
is not safe. 'onRemove' is called for widgets within layouts
on destruction anyhow, so no need to call it here again. If widgets
are arranged manually without any layout 'onRemoved' should be
called upon removing them from a dialog.
This allows one to use SGPath in containers such as std::map,
std::unordered_map and std::unordered_set.
Like the existing == and !=, all these operators rely solely on the
UTF-8 internal representation of the path.
We'll use this to cleanly declare std::hash<SGPath> as 'noexcept' in the
next commit, which appears to be desirable for std::hash template
specializations, according to:
http://en.cppreference.com/w/cpp/utility/hash
This is done by simply not user-defining the copy constructor,
copy-assignment operator and destructor. See [1] for more info.
[1] http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
For the benchmark below (compiled with the next commit to allow sorting
SGPath instances), on Linux amd64 with g++ 6.3.0, I observe that
enabling SGPath move operations with this commit increases the
performance by 31% or 28% respectively, depending on whether I use this:
// Typical code that creates a data structure in several steps and
// benefits from move operations (the std::move() does nothing when
// running the test with move operations disabled: a copy is made).
auto p = SGPath::fromUtf8(randomString(0, 30));
v.emplace_back(std::move(p));
or that:
v.emplace_back(randomString(0, 30))
for the initialization code. Now the benchmark code:
using std::string;
static std::default_random_engine randomNumbersGenerator;
// Utility function: generate a random string whose length is in the
// [minLen, maxLen] range.
string randomString(string::size_type minLen, string::size_type maxLen)
{
std::uniform_int_distribution<string::size_type> sLenDist(minLen, maxLen);
std::uniform_int_distribution<int> byteDist(0, 255);
auto randomByte = std::bind(byteDist, randomNumbersGenerator);
string::size_type len = sLenDist(randomNumbersGenerator);
string str;
while (str.size() < len) {
str += std::char_traits<char>::to_char_type(randomByte());
}
return str;
}
// The test function, run with nbIterations = 500000, minSize = 0 and
// maxSize = 200 to obtain the figures given above.
void SGPath_perfTest(std::size_t nbIterations,
std::size_t minSize, std::size_t maxSize)
{
std::uniform_int_distribution<std::size_t> sizeDist(minSize, maxSize);
auto randomSize = std::bind(sizeDist, randomNumbersGenerator);
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
vector<SGPath> v;
for (std::size_t i=0; i < nbIterations; i++) {
v = vector<SGPath>{}; // start anew
for (std::size_t j=0; j < randomSize(); j++) {
v.emplace_back(randomString(0, 30));
}
std::shuffle(v.begin(), v.end(), randomNumbersGenerator);
std::sort(v.begin(), v.end());
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsedSecs = end - start;
std::cout << elapsedSecs.count() << "\n"; // duration in seconds
}
With this simple change, the speedup as compared to commit 18f048424 is
now 37 % for the benchmark given in the previous commit. This is because
optimized swap() only needs to swap the raw pointers, which is certainly
less work than the three move assignments on SGSharedPtr (not raw
pointers) done by std::swap().
To benefit from this, write code like:
using std::swap; // now useless for SGSharedPtr, but idiomatic
swap(ptr1, ptr2); // *not* std::swap()!
This automatically makes SGSharedPtr more efficient when used in
standard containers (among others). See below for the benchmark details.
Mark as 'noexcept' (after checking it's legitimate!) the SGSharedPtr and
SGReferenced methods required for SGSharedPtr's move constructor and
move assignment operator to be guaranteed 'noexcept'.
Benchmark
---------
I measured a 25 % speedup with g++ 6.3.0 on Linux amd64, CFLAGS=-Wall -O2
as compared to commit 18f0484249 (which is
just before my changes to SGSharedPtr.hxx) on the following test code,
called with:
nbIterations = 3000000
minSize = 0
maxSize = 200
------------------------------------------------------------------------
static std::default_random_engine randomNumbersGenerator;
class SGReferencedTestClass : public SGReferenced
{ int i; };
void SGSharedPtr_perfTest(std::size_t nbIterations,
std::size_t minSize, std::size_t maxSize)
{
using Ref = SGSharedPtr<SGReferencedTestClass>;
std::uniform_int_distribution<std::size_t> sizeDist(minSize, maxSize);
auto randomSize = std::bind(sizeDist, randomNumbersGenerator);
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
std::vector<Ref> v;
for (std::size_t i=0; i < nbIterations; i++) {
v = std::vector<Ref>{}; // start anew
for (std::size_t j=0; j < randomSize(); j++) {
auto p = Ref(new SGReferencedTestClass());
v.emplace_back(std::move(p));
}
std::shuffle(v.begin(), v.end(), randomNumbersGenerator);
std::sort(v.begin(), v.end());
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsedSecs = end - start;
std::cout << elapsedSecs.count() << "\n"; // duration in seconds
}
------------------------------------------------------------------------
Basically, these gains can be explained by the fact that copying an
SGSharedPtr requires to test SGReferenced::ref, increase the refcount,
and then when the object is destroyed, test again SGReferenced::ref,
decrease the refcount and test it in order to maybe delete. With the
move constructor and move assignment operator, copying the argument is
never necessary: its raw pointer can be swapped with the one contained
in *this, which is very fast. For the move constructor, this is all that
is needed; move assignment just needs one reset() call after that in
order to release the resource from the moved-from shared pointer.
The copy-and-swap idiom is certainly very cute, but often causes
unnecessary copies. My commit fedafb9352
did exactly that, unfortunately.
Restore the exact same code for the copy-assignment operator as before
commit fedafb935, and add a more efficient implementation for the
move-assignment operator.
As explained by Howard Hinnant in [1] and [2], if some particular piece
of code really needs a strong exception safety guarantee, one can easily
add a specific method for that; this is not a valid reason to make the
code slower for all other places that have no use for such a guarantee!
[1] http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014
[2] https://stackoverflow.com/a/9322542/4756009
In C++11, destructors are 'noexcept' by default -> remove useless
throw() specifiers. There was one case that wasn't about a destructor: I
replaced the 'throw()' with 'noexcept' because this use of 'throw()' is
deprecated and 'noexcept' offers the intended meaning as far as I can
guess (in C++17, 'throw()' will be equivalent to 'noexcept' anyway). For
more info, see:
http://en.cppreference.com/w/cpp/language/noexcept_spechttps://akrzemi1.wordpress.com/2013/08/20/noexcept-destructors/
Avoids codecvt dependency on Unix where it might not be present, eg
with GCC 4.8; on Windows we use <codecvt> since it’s present in VS2015
to avoid writing a seperate UTF-16 <-> UTF-8 conversion.
Designed for 2d objects, such as a canvas placements, this permits the receipt of touch (mouse click) events to enable the simulation of avionics with a touchscreen.
The coordinates are passed in as arguments to the action; these can be accessed with Nasal via the cmdarg() method.
example:
<animation>
<type>touch</type>
<visible>true</visible>
<object-name>VSDImage</object-name>
<action>
<touch>0</touch>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>print("touch input
(",cmdarg().getNode("x").getValue(),",",cmdarg().getNode("y").getValue())</script>
</binding>
</action>
</animation>
simgear::Dir::isEmpty() used to make up to 5 calls to readdir(), while 3
are enough to say whether the directory has entries other than '.' and
'..'.
Also add an automated test for this method.
This is done so as to avoid confusion with the unrelated classes
ResourceProvider and ResourceManager already present in SimGear.
Despite this new name, EmbeddedResourceProxy is a proxy not only for
embedded resources, but also for real files (hence the initial name
choice): its purpose is precisely to allow zero-work switching from one
data source to the other.
The ResourceProxy class allows one to access real files or embedded
resources in a unified way. When using it, one can switch from one data
source to the other with minimal code changes, possibly even at runtime
(in which case there is obviously no code change at all).
Sample usage (from FlightGear for the globals->get_fg_root() bit):
simgear::ResourceProxy proxy(globals->get_fg_root(), "/FGData");
std::string s = proxy.getString("/some/path");
std::unique_ptr<std::istream> streamp = proxy.getIStream("/some/path");
The methods ResourceProxy::getString(const std::string& path) and
ResourceProxy::getIStream(const std::string& path) decide whether to use
embedded resources or real files depending on the boolean value passed
to ResourceProxy::setUseEmbeddedResources() (also available as an
optional parameter to the ResourceProxy constructor, defaulting to
true). It is often most convenient to set this boolean once and don't
worry about it anymore---it's stored inside the ResourceProxy object.
Otherwise, if you want to fetch resources some times from real files,
other times from embedded resources, you may use the following methods:
// Retrieve contents using embedded resources
std:string s = proxy.getString("/some/path", true);
std:string s = proxy.getStringDecideOnPrefix(":/some/path");
// Retrieve contents using real files
std:string s = proxy.getString("/some/path", false);
std:string s = proxy.getStringDecideOnPrefix("/some/path");
(alternatively, you could use several ResourceProxy objects with
different values for the constructor's third parameter)
By default you can either do
1. axis -> object-name ...
2. axis -> x-m ...
3. omit axis. This will now try to find an 'object-name' with -axis appended. If this can't be found then no message will be output; and the default behaviour of just using (0,0,0) will appyl.
Add a rehash() method to EmbeddedResourceManager::Impl to update
'poolSearchList'. Introduce a 'dirty' flag so that
EmbeddedResourceManager::Impl::rehash() is automatically called whenever
needed. It is not necessary anymore to call
EmbeddedResourceManager::selectLocale() after adding resources: changing
the EmbeddedResourceManager's locale or adding resources are both
operations that set the dirty flag. Whenever someone tries to fetch a
resource for the selected locale and the dirty flag is set, a rehash is
triggered before the actual fetching so as to ensure it is correct.
This should reduce the load on Ibiblio when browsing aircraft, the
package system caches thumbnails for seven days. Also we detect for
certain failure conditions and retry, to deal with Ibiblio’s rate-
limiting mechanism.
MSVC really needs these methods to be out of line, to avoid generating code for the shared pointers
in each translation unit which includes the header.
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 fg 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 /sim property tree with MP aircraft properties.
The previous fix was successful, but a priori doesn't need to be applied
to *all* compilers that define _WIN32. Apply it only when _MSC_VER is
defined, and only to the template instantiations that MSVC doesn't
recognize (i.e., those that use a parameter from the variadic template).
The MS compiler doesn't seem to recognize our templates here:
g:\jenkins\workspace\simgear-win\source\simgear\embedded_resources\EmbeddedResourceManager.hxx(169): error C3190: 'std::shared_ptr<const simgear::AbstractEmbeddedResource> simgear::EmbeddedResourceManager::getResource(const std::string &,const std::string &) const' with the provided template arguments is not the explicit instantiation of any member function of 'simgear::EmbeddedResourceManager' (compiling source file G:\Jenkins\workspace\SimGear-Win\source\simgear\embedded_resources\EmbeddedResourceManager.cxx) [G:\Jenkins\workspace\SimGear-Win\build32\simgear\SimGearCore.vcxproj]
g:\jenkins\workspace\simgear-win\source\simgear\embedded_resources\EmbeddedResourceManager.hxx(169): error C2945: explicit instantiation does not refer to a template-class specialization (compiling source file G:\Jenkins\workspace\SimGear-Win\source\simgear\embedded_resources\EmbeddedResourceManager.cxx) [G:\Jenkins\workspace\SimGear-Win\build32\simgear\SimGearCore.vcxproj]
-> try without the explicit instantiations on Windows.
Add the EmbeddedResourceManager class as well as
AbstractEmbeddedResource and two derived concrete classes:
RawEmbeddedResource and ZlibEmbeddedResource.
The purpose of this is to provide a way for FlightGear to use data from
files without relying on FG_ROOT to be set. The whole system (SimGear
and FlightGear parts) was described in detail at [1]. I'll probably
include a copy in $FG_ROOT/Docs too for fear of the link becoming dead
one day.
Basically, classes derived from AbstractEmbeddedResource provide access
to some data---the source of which is a priori of static storage
class---and handle the conversion from whatever format it is stored in
to allow convenient use of said data. At the very least, they allow
obtaining ready-to-use data as an std::string, as well as reading it
incrementally via an std::streambuf or an std::istream interface.
ZlibEmbeddedResource instances also provide access to the compressed
size of the data (i.e., as stored in static memory) as well as its
uncompressed size, without requiring any prior decompression.
EmbeddedResourceManager is a class which FlightGear will normally
instantiate exactly once---it has createInstance() and instance() static
methods for this. It maintains a map between resource paths and
instances of concrete classes derived from AbstractEmbeddedResource. It
also provides convenience methods allowing to access a resource data in
one step (not requiring to manually fetch the
AbstractEmbeddedResource-derived object corresponding to the given
resource path before calling the appropriate method of this object).
From the EmbeddedResourceManager's point of view, resource paths (keys
of the map) are just plain std::string instances in the current
implementation. However, unless there is a good reason not to, I think
it's a good idea to only use values obtained with SGPath::utf8Str()[2].
This is precisely what fgrcc, the resource compiler in the FlightGear
repository, does; so, unless you register resources manually, your
resource paths will automatically comply with this suggestion.
[1] https://sourceforge.net/p/flightgear/mailman/message/35870025/
[2] This allows later addition of methods listing all resources under a
given virtual path, as well as optimized resource lookup using a
tree-like data structure instead of an std::unordered_map (not
justified now IMO).
Add the following classes in the 'simgear' namespace:
- CharArrayStreambuf subclass of std::streambuf stream buffer
- ROCharArrayStreambuf subclass of CharArrayStreambuf stream buffer
- CharArrayIStream subclass of std::istream input stream
- CharArrayOStream subclass of std::ostream output stream
- CharArrayIOStream subclass of std::iostream input/output stream
CharArrayStreambuf is a stream buffer class allowing to read from, and
write to char arrays (std::strstream has been deprecated since C++98).
Contrary to std::strstream, this class does no dynamic allocation: it is
very simple, strictly staying for both reads and writes within the
limits of the buffer specified in the constructor. Contrary to
std::stringstream, CharArrayStreambuf allows one to work on an array of
char (that could be static data or on the stack) without having to make
a whole copy of it.
CharArrayStreambuf supports reading and writing (including efficient
implementations of xsgetn() and xsputn()), seeking (with independent
read and write stream pointers, as for std::stringstream) and putting
back chars up to the beginning of the char array. The internal buffer
for both reads and writes is defined to be the whole buffer specified in
the constructor call. As a consequence, flushing the stream buffer with
pubsync() is useless: data is always written directly to the buffer
passed to the constructor, never to an intermediate buffer.
Of course, this buffer must remain available as long as the stream
buffer object is used.
ROCharArrayStreambuf is a read-only subclass of CharArrayStreambuf.
CharArrayIStream, CharArrayOStream and CharArrayIOStream are very simple
convenience stream classes using either CharArrayStreambuf or
ROCharArrayStreambuf as their stream buffer class.
Applicable to / works with rotate, translate and knob. Once the axis object-name has been used it will be hidden, however it still can be used for object-name animations. The hiding of the axis object is a useful guide as to what is left to be wired up to animations.
This allows the follow to work (on a combined ASI / Mach instrument).
<animation>
<type>rotate</type>
<object-name>asi-needle</object-name>
...
<axis>
<object-name>airspeed-asi-axis</object-name>
</axis>
</animation>
<animation>
<type>rotate</type>
<object-name>asi-mach-scale</object-name>
...
<axis>
<object-name>airspeed-asi-axis</object-name>
</axis>
</animation>
This function is similar to simgear::strutils::to_int(), except it is:
- generic: the return type, selected with the first template
parameter, can be an arbitrary integral type. This type also defines
the set of accepted input strings ("values").
- stricter regarding the input: it must be non-empty and contain only
valid digits for the specified base (second template parameter). If
the input doesn't conform to these constraints or is too large to
fit into the specified type, an exception with a suitable error
message is raised.
- faster (12 to 17 times as fast as simgear::strutils::to_int() on my
system, depending on compilation flags): this is probably a
consequence of not using std::stringstream to do the conversion.
The function template is only instantiated for <int, 10> and
<unsigned int, 10> in order to be sure not to waste memory (see comments
in strutils.cxx). If you need it for other combinations of type and
base, just enable them by adjusting the corresponding '#if 0 / #endif'
pairs in strutils.cxx and strutils_test.cxx.
The existance of a dns entry with a protocol defined caused the
naptr callback being terminated early and the request never completed.
This patch also adds a unit test for this particular case.
test_dns now also accepts up to two command line parameters:
first: dns DN to query for NAPTR records (default: terrasync.flightgear.org)
second: service to query (default: empty)
Since the virtuality of a method is inherited by derived classes, this
makes the virtual status of such methods clearly visible in the
declarations of derived classes.
The Windows and Mac builders on jenkins complain that '\U12345678' is
an invalid universal character; let's try with '\U000000E9' instead,
which should be LATIN SMALL LETTER E WITH ACUTE.
Also replace '\uab42' with '\u00e0' to remove a warning on the Windows
builder, due to the fact that '\uab42' cannot be represented in the
current code page (1252). This doesn't mean '\uab42' was incorrect,
though; I'm only changing this to make the warning disappear.
This function complements the existing strutils::unescape(). It
backslash-escapes a string for C/C++ string literal syntax.
For every std::string s, the following holds:
unescape(escape(s)) == s
(not the other way around, because there are many ways to escape a given
character in a string literal)
An octal escape sequence in a string literal can't have more than 3
octal digits after the backslash. The previous code was using up to 4
digits per octal escape sequence.
Such an argument is /a priori/ perfectly valid, and not an option.
Typical use in a command line:
-o -
equivalent to:
-o-
The former way wasn't accepted before this commit; now it is (also
'--output -', equivalent to '--output=-').
If the last option is followed by an argument consisting of a single
'-', this argument marks the end of options and is the first non-option
argument (contrary to '--' which, given its special status, would mark
the end of options but would *not* count as a non-option argument).
This commit also adds an std::string length check in
ArgumentParser::parseArgs() that was missing before using operator[]()
(important difference between operator[]() for std::string and std::map
or std::unordered_map!).
Previously, SGPath::pathListSep was a char in static memory, that could
be followed by anything (often '\0', as it seems... but not always).
This is (was) dangerous, because it is then tempting to take its address
and pass it to functions expecting a char * corresponding to a
null-terminated string (C-style).
SGPath::pathListSep is now a static array of two const chars: the path
list separator followed by a '\0'. This implies that
&SGPath::pathListSep can now be reliably interpreted as a C-style string
of length 1 (not counting the null terminator), containing only the path
list separator.
See simgear/misc/argparse.hxx for API and documentation
(simgear/misc/argparse_test.cxx also has examples, although argparse.hxx
features a very simple one at the top).
These classes were also presented in
<https://sourceforge.net/p/flightgear/mailman/message/35785019/>.
The popup/no popup logic in SG_LOG() could be wrong before this commit,
because of missing parentheses around uses of the second macro argument.
For instance, this:
SG_LOG(SG_NAVCACHE, t == 0 ? SG_WARN : SG_ALERT, "Message");
could cause a popup window to be displayed even though neither SG_WARN
nor SG_ALERT should do that in the current state of the logging system.
Thanks to Szymon Acedański for finding this.
Add an alternate constructor to each of the following classes:
ZlibAbstractIStreambuf, ZlibCompressorIStreambuf,
ZlibDecompressorIStreambuf, ZlibCompressorIStream and
ZlibDecompressorIStream. These new constructors are passed the source
std::istream wrapped inside an std::unique_ptr instead of by reference,
and store the unique_ptr object as an instance member. This ensures that
the source std::istream object is available as long as the
ZlibDecompressorIStreambuf, etc. instance is alive (which is necessary
for its getInputData() method) without any additional work for callers,
and that it is automatically destroyed afterwards.
This is particularly useful when writing functions that create and
return an object 'zobj' whose type is a subclass of
ZlibAbstractIStreambuf, when the source std::istream is only of interest
for its role of feeding data to 'zobj'. For instance:
std::unique_ptr<simgear::ZlibCompressorIStream>
myZlibCompressorIStreamProducer(std::string str)
{
std::unique_ptr<std::istringstream> iss(new std::istringstream(str));
return std::unique_ptr<simgear::ZlibCompressorIStream>(
new simgear::ZlibCompressorIStream(std::move(iss))); // new ctor here
}
Callers of such a function get access to a new ZlibCompressorIStream
instance fed by an std::istringstream object ('iss'), but they don't
even have to know this detail, nor to take any measure to ensure that
'iss' lives at least as long as the ZlibCompressorIStream object. The
std::unique_ptr<std::istream> pointing to 'iss' and stored as a member
of the ZlibCompressorIStream object by its constructor automatically
takes care of this lifetime problem.
New automated test for ZlibDecompressorIStreambuf::xsgetn(). xsgetn() is
called by sgetn() from the base class std::streambuf. In our case,
xsgetn() is actually defined in the base class ZlibAbstractIStreambuf
(subclass of std::streambuf), therefore this new test also applies to
ZlibCompressorIStreambuf and the two other related classes,
ZlibCompressorIStream and ZlibDecompressorIStream.
This test asks [x]sgetn() the largest possible amount of chars every
time it is called, i.e., the largest value that can be represented by
std::streamsize. This exercises the code in interesting ways due to the
various types involved (zlib's uInt, std::size_t and std::streamsize,
which have various sizes depending on the platform).
Compilation of these files was disabled in commit
e21ad4b5c1.
Fix build errors and warnings:
- Ambiguous template parameters for std::min();
- No appropriate default constructor available for
std::basic_istream<char,std::char_traits<char>> (the std::istream
subclasses didn't explicitly call the std::istream constructor,
which requires an argument). This is presumably exactly the reason
why sg_gzifstream is declared like this:
class sg_gzifstream : private gzifstream_base, public std::istream
where gzifstream_base is an empty shell for a stream buffer object:
struct gzifstream_base
{
gzifstream_base() {}
gzfilebuf gzbuf;
};
This ensures that the stream buffer object (gzbuf) is initialized
before std::istream's constructor is called. I solved this problem
in a different way, hopefully easier to understand, and requiring
neither an additional class nor multiple inheritance: first, we
initialize the std::istream base with a nullptr as the
std::streambuf * argument (this is valid C++11), then in the
constructor bodies for ZlibCompressorIStream and
ZlibDecompressorIStream, we call std::istream::rdbuf() to attach the
std::istream instance to the now-initialized stream buffer object.
- Possible truncation of constant value on 32 bits systems (this was
in zlibMaxChunkSize() which is now removed, see below).
Type-related improvements:
- Remove zlibMaxChunkSize() and zlibMaxChunk: in C++, one can simply
use std::numeric_limits<uInt>::max()---most of the code in
zlibMaxChunkSize() was there only to find this value via a zlib
function call.
- Add helper function templates zlibChunk() and clipCast().
- Split preparation of the putback area out of
ZlibAbstractIStreambuf::xsgetn() to a new utility method:
xsgetn_preparePutbackArea().
- More rigorous type handling in zlibstream_test.cxx.
Some precautions are necessary because the IOStreams API uses
std::streamsize in many places (e.g., the return value of
std::istream::gcount()), but functions such as the following
std::string constructor:
std::string(const char* s, std::size_t n);
work with std::size_t instead. Since these types are different and
opaque, this requires some care!
Add:
- two stream buffer classes (ZlibCompressorIStreambuf and
ZlibDecompressorIStreambuf), both based on the same abstract class:
ZlibAbstractIStreambuf;
- two std::istream subclasses (ZlibCompressorIStream and
ZlibDecompressorIStream), each creating and using the corresponding
stream buffer class from the previous item.
All these allow one to work with RFC 1950 and RFC 1952 compression
formats, respectively known as the zlib and gzip formats.
These classes are *input* streaming classes, which means they can
efficiently handle arbitrary amounts of data without using any disk
space nor increasing amounts of memory, and allow "client code" to pull
exactly as much data as it wants at any given time, resuming later when
it is ready to handle the next chunk.
See comments in simgear/io/iostreams/zlibstream.hxx for more details.
- Rename zfstream.cxx (resp. zfstream.hxx) to gzfstream.cxx (resp.
gzfstream.hxx)
This is because these files only deal with the gzip format (RFC 1952),
while zlib can actually read and write two slightly different formats:
this one and the "ZLIB Compressed Data Format" (RFC 1950). Since I am
going to add std::streambuf and std::istream subclasses able to deal
with both formats (and supporting data sources that are general
std::istream instances, not just files), this renaming will make
things a bit clearer, I hope.
- Add new folder simgear/io/iostreams and move the following files to
this folder:
simgear/misc/gzcontainerfile.cxx
simgear/misc/gzcontainerfile.hxx
simgear/misc/gzfstream.cxx
simgear/misc/gzfstream.hxx
simgear/misc/sgstream.cxx
simgear/misc/sgstream.hxx
simgear/misc/sgstream_test.cxx
- Adapt other files accordingly (mainly #includes and CMakeLists.txt
files).
HTTP/1.0 and HTTP/1.1 allow the reason string to be empty.
Some servers produce empty reason strings on success,
e.g. "HTTP/1.1 200 ", which throws a "bad HTTP response"
exception.
From the specification:
"Reason-Phrase = *<TEXT, excluding CR, LF>"
From notational conventions:
"*(element) allows any number, including zero"
References:
www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2
www.w3.org/Protocols/HTTP/1.0/spec.html
www.w3.org/Protocols/rfc2616/rfc2616-sec6.html
- Create "testfile" in a temporary directory (and make sure the temp dir
and the file it contains are both removed when the test program exits).
- Use test macros such as SG_CHECK_EQUAL() instead of by-hand checks and
"return EXIT_FAILURE" statements.
- Use sg_ofstream instead of plain std::ostream. This simplifies things
a tiny bit, because one SGPath instance is enough to create both the
sg_ofstream instance and the sg_gzifstream instance used afterwards to
reread the created file.
- Don't call (sg_)ofstream::close() at the end of the block the instance
is declared in: this is entirely unnecessary, since sg_ofstream
derives from std::ofstream, which is automatically close()d when
destroyed (RAII behavior).
- Add method simgear::Dir::isNull(), analogous to SGPath::isNull().
- Make sure that simgear::Dir::tempDir() returns a null simgear::Dir
instance when creation of the directory failed (so far, this was only
the case on systems where HAVE_MKDTEMP is defined).
- Use simgear::strutils::error_string() instead of strerror() (the
latter is not guaranteed to be thread-safe).
- Make sure <cerrno> is #included, regardless of the platform.
- Add automated tests for isNull(), setRemoveOnDestroy() and tempDir().
This was triggered by the TU154B; probably related to the console error
* "Image loading failed:Warning: reading "fgdata\AI\Aircraft\tu154b\Model" not supported.
This avoids an XML naming clash, and allows both systems to exist in
parallel peacefully. Update the tests to check both the thumbnails
and preview system in parallel with each other.
In pt_lights.cxx in SGLightFactory::getOdal, at segment "centerline lights",
the decrement loop index i is initialized with lights.getNumLights(), then is used at lights.getLight. (ERROR)
The function getNumLights is set to the size of the vector which is one more than the max index refernce.
This restores the behavior that was in place before commit 8ddb99f62f
BoostTestTargets.cmake requires the CMake-configurable form of the Boost
test framework to be used (i.e. "#include <BoostTestTargetConfig.h>"), and
checks each test source code file for this, outputting a warning in case
this requirement is not met.
Unfortunately, a conditional in the check is badly specified (the CMake
variable syntax is not followed), so the warning is emitted even when it
should not be.
This patch fixes this bug and restores the correct behavior.
Submitted upstream at https://github.com/rpavlik/cmake-modules/pull/44
Want to verify this is the cause of crashes inside the property code,
since if it's not we have a much bigger problem.
This means all listeners are recursive, with a parent-chain walk on each
setValue call, as has been the case since 'forever'.
- osg::Vec4 objects can't be output to a stream -> use the _NOSTREAM
variant of the test macro.
- ditto for the NULL... thing -> use SG_CHECK_IS_NULL().
- Add an _NOSTREAM variant for each macro (except for SG_TEST_FAIL, that
doesn't take any argument, and for SG_VERIFY, which doesn't attempt to
print its argument to a stream---doesn't sound very useful). So, if a
and b can be output to a stream (without any undesirable side effect,
of course), use for instance SG_CHECK_EQUAL(a, b); otherwise, use
SG_CHECK_EQUAL_NOSTREAM(a, b).
- Add test macros SG_CHECK_IS_NULL, SG_CHECK_IS_NULL_NOSTREAM,
SG_CHECK_IS_NOT_NULL and SG_CHECK_IS_NOT_NULL_NOSTREAM.
- Add a few comments.
- Because of possible operator overloading, make SG_CHECK_EQUAL(a, b)
fail if, and only if (a) == (b) is false (testing if (a) != (b) for
this macro is not correct in general).
- For clarity and consistency, change the messages printed when some
tests fail: SG_VERIFY(some_test) prints 'failed: some_test' (okay),
but SG_CHECK_EQUAL(a, b) used to print 'failed: a != b', which is
inconsistent. Instead, print: 'failed: a == b' because this is what we
know that failed (again, because of possible operator overloading,
pretending we know the the logical value of (a != b) after testing
(a == b) is not correct in general.
Similarly, the "approximate equality tests" SG_CHECK_EQUAL_EP() and
SG_CHECK_EQUAL_EP2() now print something like 'failed: a ~= b' when
they fail, instead of 'failed with epsilon: a != b'.
- The header is needed for std::cerr.
- Also improve the messages when tests fail (spacing, and in some cases
an argument was missing).
- Reorder the macros a tiny bit.
Some of the modules where I previously removed duplicate private
definitions of these macros had these features, and since they seem wise
to me, I'm applying them to the canonical SG_CHECK_EQUAL_EP() and
SG_CHECK_EQUAL_EP2() macros defined in simgear/misc/test_macros.hxx.
COMPARE -> SG_CHECK_EQUAL
COMPARE_EP -> SG_CHECK_EQUAL_EP
COMPARE_EP2 -> SG_CHECK_EQUAL_EP2
VERIFY -> SG_VERIFY
Also remove duplicate private definitions of these macros in test
modules, using instead those defined in simgear/misc/test_macros.hxx.
Only handle PackageRef by reference in the header file, so we don’t
create calls to the copy constructor and/or destructor. If this doesn’t
work will need to create a stub implementation file.
This is a number ranging between 0 and 1 based on the log of the illuminance of
the moon outside the atmosphere. It is calculated as
factor = (log(I) - max_loglux) / (max_loglux - min_loglux) + 1.0,
where I is the illuminance of the moon outside the atmosphere and min_loglux and
max_loglux are hardcoded to -0.504030345621 and -4.39964634562 respectively.
Although the value should never be outside of [0, 1], for safety it is clipped
to be between these values. For more background, see
http://forum.flightgear.org/viewtopic.php?f=47&t=28201&start=60#p270516 .
This is the base 10 log of equation 20, converted from foot-candles to lux,
from:
Krisciunas K. and Schaefer B.E. (1991). A model of the brightness of
moonlight, Publ. Astron. Soc. Pacif. 103(667), 1033-1039 (DOI:
http://dx.doi.org/10.1086/132921).
To obtain the sun's true longitude, the Star::getlonEcl() function has been
created. The moon's age is then calculated as the difference between the moon's
and sun's true longitudes. The phase is then simply half of one minus the
cosine of the age. Hence these calculations are very cheap compared to the rest
of the moon position calculations. The algorithm is from:
Duffett-Smith, Peter. Practical Astronomy With Your Calculator. 3rd ed.
Cambridge: Cambridge University Press, 1981. ISBN 0-521-28411-2.
The code can replicate the example in the book of Feb 26, 1979 at 16h UT, with
an age of -0.4767 degrees a phase of 0.0:
$ fgfs --aircraft=UFO --start-date-gmt=1979:02:26:16:00:00 --airport=EGLL \
--altitude=50000 --enable-hud
The calculated phase is 1.459e-5 and the age is -6.2908 (which is -0.43628
degrees). For a recent full moon:
$ fgfs --aircraft=UFO --start-date-gmt=2015:11:25:22:44:00 --airport=EGLL \
--altitude=50000 --enable-hud
The calculated age is -3.1413 and the phase is 0.9999999778.
By storing repetitive intermediate calculations, the number of mathematical
operations for a single call to CelestialBody::updatePosition() has decreased by
12. This matches the changes to MoonPos::updatePosition().
The following functions have been added: MoonPos::getM(), MoonPos::getw(),
MoonPos::getxg(), MoonPos::getyg(), MoonPos::getye(), MoonPos::getze(),
MoonPos::getDistance(). These are copied from and match the Star class
functions (but with xs and ys replaced by xg and yg).
By storing repetitive intermediate calculations, the number of mathematical
operations for a single call to MoonPos::updatePosition() has decreased by 32.
Commit 8277857827 relies on zlib's
gzoffset() function (not just offset(): that was a typo in the commit
message, sorry). This function appeared in zlib 1.2.4 (which dates from
2010). Enforce this requirement with CMake.
This way, one can easily use the OS-dependent separarator for path lists in
other places to build and split path lists in an optimal way (e.g., not
sacrificing ';' on Unix, since the path list separator is ':' on this
platform).
- When started from the console use the console (when no --console)
- When started from the GUI (with --console) open a new console window
- When started from the GUI (without --console) don't open a new console window; stdout/stderr will not appear (except in logfiles as they do now). This opens stderr/stdout on the NUL device to alleviate any potential issues
- When started from the Console (with --console) open a new console window
- Ensure that IO redirection still works when started from the console. When redirecting stdout stderr will also be redirected (providing it wasn't already via 2>&1) - otherwise output from stderr will be lost.
- When using redirection from the command prompt --console will produce an error message box.
Notes:
- fgfs needs to be a linked as Win32 GUI subsystem app - which it already is
- What can't be done is to make the cmd prompt run fgfs synchronously; this is only something that can be done via "start /wait fgfs"
Basically the way that Win32 works is quite sensible, but slightly at odds with the unix nature of the C-RTL; so the standard streams sort of get lost for GUI apps. AttachConsole and AllocConsole are provided to address this - but they do slightly different things. AttachConsole will attach to the cmd.exe (or any console related to the parent process), whereas AllocConsole will open a new one. Depending on where the application was launched from it makes sense to use AttachConsole for a cmd.exe launch and do nothing (unless --console is given) for a GUI launch.
Redirection is not available from the GUI (unless set in the Process Create block) - so really only available when launched from the command line. If any stream is redirected then all must be otherwise it appears that AttachConsole will undo the redirection by changing the standard handles.
set /sim/terrasync/scenery-version=ws30 to filter the DNS NAPTR
records for service=ws30
current default (and only available) scenery version is ws20
This enables usage of multiple scenery repositories
Allows repositories to be initialised based on data in the install.
This avoids duplicate downloading of the Model and Airport data,
and the starting scenery.
Requires a corresponding FlightGear change to be functional.
SGPath and simgear::Dir use ‘w’ versions of POSIX APIs on Windows,
and convert UTF-8 SGPath to wide-strings as part of this.
Includes improved unit-tests for this code, with some very basic
tests of creating and iterating files with Unicode characters in
their names.
No user-visible changes should result from this, on any platform; in
particular wide-string support is still incomplete so FlightGear will
not yet work with arbitrary Unicode paths on Windows.
Change most places we control (i.e not helper libs) to use SGPath
to represent a path, instead of using std::string. Extend SGPath
API to explicitly expose the path in either UTF-8 or the
system 8-bit encoding.
Since Cygwin has SG_WINDOWS defined but is likely to expose a POSIX or
GNU-like interface, using _WIN32 to decide whether Windows-specific
functions are available seems more appropriate than SG_WINDOWS to me.
strutils_test.cxx uses std::string but doesn't include <string>
directly. This doesn't cause any error because it includes this header
indirectly via "strutils.hxx". However, I believe relying on this is bad
practice, hence the tiny fix.
Uses:
- strerror_s() on Windows;
- the GNU strerror_r() on non-Windows systems where _GNU_SOURCE is
defined (which is currently the case when the GNU libstdc++ is used,
even if one doesn't explicitely define _GNU_SOURCE, cf.
<https://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.predefined>);
- the XSI-compliant strerror_r() on other systems, as long as
_POSIX_C_SOURCE >= 200112L (otherwise, the compilation will abort
due to a #error preprocessor instruction).
For Windows, default file mode is TEXT.
If binary files should be created _O_BINARY shall be or'ed to the open
flags. This is not necessary on *nixes.
Introduce a SGBinaryFile as extension to SGFile which adds the flag
upon construction on Windows.
This should keep existing behaviour for all other usages of SGFile.
Let terrasync use the http repository if
/sim/terrasync/http-server == "automatic"
resolve DNS NAPTR RR for terrasync.flightgear.org with service "ws20"
and flags "U". Pick one of the returned entries with lowest order
and preference. If more than one entry with the same order and
preference is returned, pick a random entry of those returned.
or if
/sim/terrasync/http-server != "automatic"
explicitly use the value of that property as the http server
if
/sim/terrasync/http-server is empty, fall back to the legacy
SVN repository
Fix bug reported by Thorsten RENK on the mailing list
that random objects were only being displayed if random
objects were also present for the tile. Also fix crash
if none of the random object models were found.
- import udns library
(http://www.corpit.ru/mjt/udns.html)
- initial draft for a DNSClient (derived from HTTPClient)
Enable compile and test by adding -D ENABLE_DNS=Yes to cmake flags
When a catalog version is stale, disable it but don’t remove it,
and still try to refresh it. This should give much better behaviour
when the FG version changes, should behave as users expect.
Avoids very long pauses blocking the terrasync thread, while existing
file trees are verified.
Also split the request queue so we don’t submit vary large numbers of
requests from a single repository, and hence block other repositories
from getting traffic.
For HTTP repositories, support some additional metrics about ongoing
transfers. Not currently exposed via properties / TerraSync API, but
will be shortly.
- since the root-level request for an HTTP repo is small, and static,
it doesn’t make sense to use the same persistent cache, especially
for initial testing.
A plain-HTTP terrasync repository implementation, using the
SimGear HTTP abstraction. File validity is based on SHA hashes,
and existing files are not re-downloaded if their hash matches,
so soft upgrade from an SVN checkout is possible.
- handle closed connections equivalent to IDLE, for timeout purposes
- if the server closes the socket in WAITING_FOR_RESPONSE state, fail
the first sent request when restoring.
Note this does not explain why the server sometimes closes the socket
in this way, but at least it now causes a detectable failure.
QuadTree relies on a bounding box to set up correctly.
ProxyNodes don't have a BB until the model is loaded,
causing the QuadTree to collapse if the DB loader can't
keep up with the STG loader.
Fix this by creating a default BB before the model
is loaded.
Using a weak pointer is the best way to ensure no invalid
pointer is used. This also fixes a possible crash in
simgear::canvas::Element::getParentStyle on destructing
canvas elements.
- check the catalog version explicitly when refreshing
- handle packages with distinct dir name / primary ID correctly
(requires an updated catalog XML format)
- rename failure code to status code, and add more to handle
cancellation.
- change caching of active Installs from Catalog to Root, to clarify
ownership
- expose download status on Install
- adjust Delegate signatures to pass more information
Add a 4th layer to the sun (next to disc, inner halo and outer halo). While the inner/outer halos change with atmosphere conditions, the new layer is supposed to represent the effect of blinding brilliance - ideally it adds a suitable ray structure to the sun. The effect is most prominent in space (where I'm most keen on seeing it admittedly) because there all atmospheric halo effects are absent and we end with a really unrealistic white disc.
Some screenshots and discussion there
http://forum.flightgear.org/viewtopic.php?f=47&t=27216
add a create-flag to the node() method of a PropertyObject,
defaulting to false to maintain existing behaviour.
This could be used to add a listener to a non-existing property
without having to write a dummy-value beforehand.
Usage:
myPropertyObject->node() returns the corresponding node or NULL if
does not exist or has not been accessed before.
myPropertyObject->node(true) returns the corresponding node, never NULL.
If the property does not exist, it will gets created.
- do not save the TileGeometryBin and matcach in the randomObjectCallback
- recreate matcache, and get TileGeometry from scenegraph
- split obj.cxx into three distinct files - loadBTG, load surface geometry, and load tile details
- includes fix for sceneries that have missing materials
This allows for binding the lifetime of any nasal object to
the lifetime of a ghost. Otherwise circular references from
objects saved within the ghost would prevent the ghost from
being garbage collected.
Our paged models used the default minimumExpiryTime of zero seconds
which caused frequent stutter with AI traffic loaded.
This patch sets the minimumExpiryTime to 180 seconds, more than enough
to hold the models in memory during a full standard rate turn.
The property to set the expiry time is
/sim/rendering/plod-minimum-expiry-time-secs
Since the consensus seems to be that the precipitation clipping issue is with the panel code, attached is my proposed update for the precipitation system in SG and FG
* without corresponding control structures in FGData it falls back to default, except I have fixed an inconsistency in freezing behavior - previously rain changed suddenly to snow when the temperature dropped below zero, but the reverse transition was dragged out and gave odd visible motion with the wind as snow gradually changed back to rain with the particle speed not well defined. Now both transitions are sudden. And I see no more particles flow against the wind
* with
<!-- definitions for the detailed precipitation manager -->
<precipitation-control>
<rain-droplet-size type="float" userarchive="n">0.015</rain-droplet-size>
<snow-flake-size type="float" userarchive="n">0.03</snow-flake-size>
<detailed-precipitation type="bool" userarchive="n">false</detailed-precipitation>
<illumination type="float" userarchive="n">1.0</illumination>
<clip-distance type="float" userarchive="n">5.0</clip-distance>
</precipitation-control>
added to Environment/environment.xml, the new system allows to switch more detailed management on. This provides
* explicit setting of rain droplet size and snow flake size by the weather system
* automatic sqrt(r) scaling of the vertical speed of raindrops
* automatic transition to snow when freezing for small droplets but hail for large droplet sizes (looks like snow, but has different particle dynamics)
* an illumination scaling factor to dim the precipitating based on the light we have in the scene (I still need to devise a property rule to set this automatically)
The clip distance is also exposed now and considered at startup of the system - might be useful for e.g. airships when the gas bag provides rain cover (?) or to be simply off for open airplanes
Thorsten Renk:
The following patch sets the sun color to alpha=0 when
the sun is below the local horizon, removing the oddity
that the sun is seen 'through' the terrain when the terrain
at large distance is rendered by the skydome.
Stuart has improved the UniformCache approach, here are his
changes:
- We have a UniformCache so that each unique Uniform is only created once
- As part of the UniformFactory we also have a queue of listeners that are still to be added
- When the main thread sends an Update node visitor across the Effects,
all queued listeners are de-queued and added.
- Throw an exception if converting an object
from Nasal fails due to a wrong type (nil
does not throw).
- Update cppbind test cases accordingly (and
refactor another test suite to use Boost.
Test).
The effect system used Listeners on property nodes to get the values
for shader uniforms. These listeners get deleted by an osg thread
causing access to freed memory when this happens while the main thread
calls fireValueChanged.
This patch changes the update method to polling for scalar properties.
This isn't 100% threadsafe, too. But at least it does not crash anymore.
GL_SCISSOR itself only supports integer coordinates, but
with reference frames different from GLOBAL transforms
influence the position of the clipping frame, possibly
resulting in wrong positions due to too low precision.
Using just 0 as prefix for octal number can lead to confusion
where numbers could be interpreted the wrong way (oct instead of
dec).
Lets follow the same convention as Python 3 and Ecma 262 level 6
and use '0o' as prefix which can not be confused inadvertently.
No need for this anymore as PRESERVE now works as expected.
Otherwise old canvasses are restored and do not work anymore
as the placements of the new canvasses do not apply.
Keep a list of callbacks to allow registering multiple callbacks
to the same event. This is consistent with eg. jQuery.Deferred
and is needed for example to open multiple dialogs showing the
progress of installing a package at the same time.
Parse the same number formats (octal, dec, hex) in literals and tokens. Was
previously quite a mess, and is still not the best solution, as lexing and
string parsing uses different implementations, although they are meant to
do exactly the same conversions.
- Just increment/decrement reference count for intrusive
smart pointers. No need to create an additional object
on the heap.
- Keep strong reference for weak pointer based ghosts
to prevent destroying objects while beeing used.
- Catalog keeps a map from variant IDs to packages
- Package caches its ID
- Refreshing a catalog updates existing Package instances
Dropping a package from a Catalog will now warn, need to decide
a real policy for this scenario.
Parse just a tiny subset of Markdown, to basically collapse
multiple whitespace and do paragraphs only after two newlines.
Also one-level, unordered lists are supported. The output can
be eg. directly forwarded to canvas::Text.
We do not use the image rendering part anyhow, so
just disable it for now. If we want to use it we
will need a modified implementation anyhow to
integrate with OpenSceneGraph threaded OpenGL
resource management.
- Add SGVirtualWeakReferenced to be used as base class
for reference counted objects supporting weak references
and virtual base classes.
- Modify SGWeakPtr to copy with SGVirtualWeakReferenced
objects.
- allow placing SGWeakPtr in sorted STL containers (eg. requiring
operator<)
- add reset() like for boost::shared_ptr/boost::weak_ptr
- add helper to extract pointer from SGWeakPtr
- Do not enable any multisampling as for FBOs it is not
supported anyhow.
- Just restore GL_BLEND and GL_STENCIL_TEST manually
=> Getting rid of the huge load of glPushAttrib/glPopAttrib
gets us a huge performance boost, especially for drivers
with slow state stack implementations.
- Prevent writing to property tree in wrong thread.
- Add Element::getBoundingBox and
Element::getTightBoundingBox as uniform way to
retrieve bounding boxes of all canvas elements.
- Update path bounding boxe in update traversal.
Returning somehow valid data in case it is used unchecked was
probably not a good idea. Better fix the code using it^^
This fixes#1421.
This reverts commit 3525fff8d0.
Return an invalid bounding box can lead to problems
if used unchecked. Just returning an empty bounding
box (size 0x0 and position at the origin of the
element) is much safer.
- Calculate local/client position for every drag event
instead of just reporting the position of the initial
mousedown event.
- Only pressing the same button multiple times increases
the mouse clickcount.
Get rid of the possibilty to keep delted children. This was not
used actively, required unnecessary memory for each property node
and lead to subtile bugs, as creating a node after a node with
the same path has been deleted resulted in getting the old node
back instead of a cleanly initialized one.
- remove the 0.5 degree offset away from the equator, which was
causing wrap-around at the poles
- add a new helper to get the highest latitude of a tile (which may
be +/- 90 for the polar cap tiles), and use this to compute radius
- special case the polar-caps and return a fixed, small width so
the tile-manager loads all tiles.
- sink some inline methods into the .cxx file
- add isValid test to SGBucket
- sgGetBuckets won't return invalid buckets near the poles
- additional unit tests
- as part of looking at polar behaviour, start testing the
bucket code since the code has subtleties which it would be unwise
to change.
- remove a legacy setter on SGBucket (taking two doubles as a C-array)
Store unhandled xml attributes in a subnode named _attr_ for each
node on parsing propertylist files. This allows retrieving them at
a later stage where there is no access to the source xml file any
more.
Needed to bug-fix a problem with the menubar on Mac - post-3.0 I will
change the behaviour of SGBinding's destructor to avoid the property
copies in other use-cases.
Writing to a closed socket on all Unix/Linux systems raises
a SIGPIPE signal which immediately closes the program. Disabling
raising of SIGPIPE allows proper error handling by checking the
return values of send/sendto and getting the EPIPE in errno.
Add a thread-safe cache of the currently valid materials, to avoid
the osgDB thread making repeated SGCondition evaluations in conflict
with the main thread.
(Requires an accompanying FG change)
Only apply the fix for time-zone offsetting on Windows, since Unix
is handling mktime differently. (Arguably we should also apply a
conversion for Unix systems, but the previous logic worked)
Without this, various sky rendering modes exhibit artefacts in low-
visibility conditions. The cost of always rendering the dome is
negligible. (And Rembrandt already had to work this way)
Search the tree for leaves / sub-trees with a particular attribute set.
This permits both sparse selection as well as selection by sub-tree.
(This is needed for PRESERVE attribute, and once new reset is switched
on, will enable 'normal' copyProperties to revert to ignoring
attributes completely)
- without this change, elements aren't un-ref-ed and hence destroyed
until the actual dtor runs, which is too late (other systems may be
destroyed already)
Using a static naGhostType ensures that always the same
address is used for the same ghost and prevents ghost_types
from getting invalid (eg. on reset).
Change the subsystem-group and manager code to use shared-ptr references
to subsystems, instead of holding a raw pointer. Hence the manager becomes
the owning ref to most subsystems.
Slave objects can now rotate around two axis to always track the
target - even when it is outside the plane perpendicular to the
lock-axis of the root object. This allows for example animating
levers with non-parallel axis of rotation connected with a rod.
Check explicitly for the 'no channels' case and
sleep instead, to avoid busy-waiting. (This is a work-
around, the underlying issue still be be traced)
- Update clipping rect if canvas view or texture size
changes.
- Add new property "clip-frame" to specify coordinate
frame for "clip" coordinates. Coordinates can be
global, relative to the parent or relative to the
element itself.
- refactor code used multiple times spread over sg/fg into
one single location.
- allow aborting requests.
- Provide two common request types:
* FileRequest: Save response into file
* MemoryRequest: Keep resonse in memory (std::string)
- extend HTTP::Client interface:
* urlretrieve: Save url to file (shortcut for making a
FileRequest)
* urlload: Get respons into memory (shortcut for making
a MemoryRequest)
Windows handling of ::rename differs from POSIX when the new name
exists. Check for this case on Windows and remove the file manually.
(This allows a work-around in SVNDirectory to be removed)
Bug 1190, fix route-manager -> GPS activation on Windows
(and probably a couple of unrelated issues).
SGPropertyChangeCallback was missing a suitable copy-constructor,
leading to incorrect behaviour on compilers where the operation
is not elided. Such as MSVC.
Test result of GetLastError so we don't log a warning in the
'nothing matched' case. Makes early startup logging much
more pleasant, especially when scanning aircraft dirs.
Encountered while testing v850 airports; some airports
generate materials with no tris, and hence no indices.
This causes a divide-by-zero when computing the index stride.
Detect this, and convert the BTG reader to throw exceptions
in error conditions, and to catch this and report the
appropriate result code.
This is some initial pieces to synchronise other pieces of base
data than scenery via the sync mechanism. An additional sync slot is
added to avoid scenery or other data blocking each other.
New functions naCallMethodCtx and naCallMethod to replace
NasalSystem::callMethod from FlightGear. This has just added an
unneeded level of indirection and fits better directly into Nasal.
naSetErrorHandler can be used to register an error handler/logging
function.
These new functions are meant to replace the gcSave/gcRelease
methods of the NasalSystem class in FlightGear, as passing an
adapter to SimGear from FlightGear is quite a lot of useless work
just for being able to save objects.
Move content-encoding handler into its own file, which
simplifies the main code. As part of this, fix a bug where we
didn't flush the ZLIB buffers on response completion.
- rename mod() to fmod() to prevent collisions with the
version in math.nas (which has different handling of negatives)
- implement pow, tan, acos and asin natively
- add round(x, [p]), which rounds away from 0.0, and takes an
option precision. I.e you can round(479, 50) and get '500'; useful
in many digital cockpit displays.
Provide an API to query which tiles are currently being synced. This
allows the higher levels (TileManager in FlightGear) to safely wait on
TerraSync before loading tiles.
Doing this exposed some bugs in scheduling tiles to sync by integer
lat/lon, related to round-towards-zero with -ve values (western /
souther hemispheres). To resolve these, and also reduce spurious
syncs, switch to an explicit API for requesting tiles by SGBucket.
This keeps TerraSync fully aligned with the TileManager queue, which
has many benefits for both high and low visibility situations.
Prefer existing, idle connections to creating new connections,
even when below the max-connection limit. Gives much better re-use
and pipeline-ing, and hence reduced setup time/trips.
When re-init-ing the sim, tell TerraSync what's going on (we don't want
to actually reset it, since that would disturb in-flight downloads).
Add an explicit method so it can reset its last lon/lat, and hence do
the initial sync at the new location correctly.
Track 'waiting for response' state explicitly, so we don't
falsely report IDLE when waiting for a response.
Expose bytes-per-second download rate as metric.
Add explicit subsystem state tracking so we can safely init()
terrasync very early during startup, and hence overlap lengthy operations
(Shared Models sync and initial NavCache build)
When using built-in sync code, separate items into distinct slots.
Slots process items sequentially, but each slot works in parallel (using
a single shared HTTP engine). This allows tiles to be synced in parallel
with airports/shared models data, greatly increasing responsiveness
to get tiles synced on initial launch.
We already synchronise other things besides tiles, and will soon want different
behaviour based on the type of item we're syncing (so we can synchronize some items in parallel). Rename the struct to be clearer, and add an enum encoding the type of item for future use.
Hopefully this tells the Expat headers not to do any clever
declspec(import) or export stuff, which we don't want since we only
use the symbols within SimGearCore, and don't export them.
Switch back to including the bundled expat sources directly in the
targets, since transitive linking of static libs is very awkward.
Makes static build happy again (let's see what else breaks)
Renamed bundled Expat headers to avoid any
possibility of accidental including system headers when
using bundled Expat, or vice-versa. Should help with SVN
crashes reported by Thomas.
Make the already present cache of updated URLs persistent, with a
definable lifetime, currently 24 hours. This ensures terrasync-ed
resources are checked less often (max once per day) instead of each
FGFS launch, which should greatly cut down requests to the backend.
- max connections limit, and parallel connections to a single host where possible.
(Will permit updating terrain and Models / Airports / data in parallel)
- add LGPL headers
- give HTTP::Client a private impl class, to keep header simple.
Slightly simplistic, but definitiely correct, method
for ensuring singleton creation is threadsafe. Can
be optimised if lock contention is ever an issue.
If setting properties on a group a check is performed if
this property exists on any possible child element, and
only if this is the case the property is stored in the
groups style.
Previously elements have been only initialized during
their first usage, leading to ignored styles if they
have been set on a parent element before instantiating
an instance of the actual element type.
Removing text elements failed due to prefering removing the
style property with the same name. Add a flag to each style
indicating whether it can be inherited. The text property
is only applicable to text elements and can not be inherited.
Now groups can not have a text property, avoiding the name
clash with the text element.
Ensure pick callbacks work over the whole pick group, otherwise
the visible render group is hit first, and resolves to the ground
pick callback instead.
This fixes the hangar doors at KSFO and Moffett.
Basic SHGetSpecialFolderPath wrapper, with dynamic
finding of the function since linking to shell32.dll
is painful. Obviously could be generalised to other
CSIDLs in the future.
Nodes inside the osg scenegraph now hold a strong reference to
the according canvas element. Canvas elements in turn now only
hold a weak reference to the according node. This simplifies
for example the canvas::Group as it does not need to keep a
list of children on its own anymore. This is now stored inside
the scenegraph (as it was already before).
The restructuring will also allow to use a canvas::Group for
the canvas gui inside FlightGear and share for example the
handling of stacking based on z-index.
Removing all event listeneres on destroying a canvas
prevents circular references due to Nasal event listeners
keeping a reference to the canvas in their closure.
Also fix event handling with direct children of the root
group and add some more helpers to the Canvas.
This allows tracking elements while at the same time changing the
rotation of both animated elements to fill the available distance
to the target element. This allows for example animating gear
scissors or other connected objects like gear doors and their
actuators/arms (possibly connected to the gear strut).
Style setters are now only setup once for each element type and
not for each element instance as before. A static map holds the
setters for each element type. Also an animation type is stored
which will later allow to animate properties of Canvas elements
without specifying and animation type.
Create a pick group for each object, instead of a single one. This
can be optimised in the future but this structure is backwards-
compatible with existing usage, which is more important.
Pick, knob and slider animations support additional object-names,
which are always invisible and untransformed (in the case of knobs/
sliders). These objects act to extend the hover/pick area, making small
switches and knobs more usable. (Especially for users with smaller
screens / windows).
This makes Nasal unload hooks of scenery objects working again.
Previously the same SGModelData instance was used for all objects
which never got destroyed and therefore was not able to call any
unload callback.
Inspired by jQuery.animate() properties can be interpolated using
different easing functions and specifying an animation duration.
Additionally animations can be chained to get table-based
animations like with the current SGInterpolator, or also create
looped animations or other more complicated curves.
Currently this system is not used yet, but it is intended to
replace SGInterpolator and allow more advanced animations of
eg. also colors, for example, for the canvas.
Initial ground-work to support efficient updating of condition/expression results; allow collecting all the dependent property values from the hierarchy, so they can be observed. Also add a very small test-case for this.
Using template parameter dependent name lookup it is
now possible to create to_nasal_helper overloads
for custom types and having them used for automatic
type conversion with binding methods/member on
nasal::Ghost objects.
It is now possible to register all types of member function
and free functions as methods for nasal::Ghost objects.
The return value and arguments are converte automatically
to the required types.
Also usage is simplified by removing replacing the old
method and method_func with a single method function
which only needs a name for the method and something
callable.
Check for the 3rdparty dir in the parent of build dir, not the parent of the source dir. For the recommended build layout, this is the same location, but for super-builds using fgmeta it's not (and the source tree should not be touched).
If this causes anyone issues, please let me know, since it's possible more flexibility is needed to set the path explicitly.
- Improved Nasal/C++ bindings will follow. For now just test if
all compilers are happy with intended approach.
- Add to_nasal overload for std::map<std::string, T>.
A user_data pointer and another pointer to an optional
deleter function is stored in unused parts of the naPtr
union. The previous behavior of extension functions does
not change. Only one additional boolean comparison is
required upon each function call to check whether user
data is available.
The levels at which page nodes are built is exposed by an
osg database pager option SimGear::SPT_PAGE_LEVELS which could
contain a blank separated list of levels where paging occurs.
Also the database pagers paths are searched for static lower
level of detail tiles in case they are available.
This defers loading the models into a paged lod node
that is evaluated at a later point in time. That should
help for memory problems with higher visibilities.
Basic library infrastructure, catalog download/refresh, and package install,
uninstall and update. Disabled at cmake time by default, and not yet hooked
into FlightGear.
Will be used to support native Nasal commands, which was tricky with pure function pointers before. Can also be used to avoid some trampoline functions in the code, but this can happen gradually.
Don't reduce width of bounding box below character width
even if outline of rendered character is smaller. This
prevents trailing spaces from being ignored and also
fixes continuously chaging alignment (especially with
monospace fonts).
Support multiple backends, and make it thread-safe. Use an internal thread to push log entries to backends, to avoid blocking the submitting thread for any time.
- Fix overwriting of parent node if PropertyObject::node() is
called for a non-existing node.
- Prevent implicit conversion from const char* and
SGPropertyNode*
Currently this fires on button release, but also after any mouse-wheel movement (since they are sent as buttons). This feels slightly wrong, but can't decide how a spring-loaded know would work, when interacting via the mouse-wheel. Comments welcome.
As part of this, pass the osgGA GUIEventAdapter down into the pick callbacks, which seems reasonable to me. If anyone can foresee issues with this, please let me know and I can adjust the API.
- Add nasal::String for wrapping Nasal string data and accessing
string methods (which eg. could be exposed to Nasal)
- Allow adding functions from C/C++ which are callable on
Nasal strings.
Change the bucket tiling at the poles not to cross the
0deg longitude and not to cross the 180deg longitude line.
This lets some special cases disappear for the buckets as well
as for the hierarchical level of detail spt loader.
Also change the last degree tiles from spanning 360 degrees to
12 degrees. Before we had 8 nested rings which neither helps
scenery paging nor culling. With that change the chunks are
about the same order of size than any other tile. Also the
tile shapes are much more friendly for culling and paging.
Also in presence of the current scenery, this polar tiles contain
as of today just totally broken geometry which tells me that
also the scenery generation process did not like these rings
for the tile shapes.
The impact on the current scenery is low. With this change the
polar regions do no longer load the tiles that are available
in the current scenery builds. The last degree tiles are broken
in this scenery version anyway. The next degree that is changed
will really loose some tiles that were sensible as of today.
All these areas are replaced with sea tiles by the old paging
structure. So, you will have at least ground below you when you
fly there. A hopefully comming soon scenery rebuild will
use this new tiling structure and thus will be the first one
providing closed polar caps.
This removes support for exposing and managing classes by just
raw pointers as this made lifetime management of instances
from C++ to Nasal and especially the other way round nearly
impossible. Always using smart pointers saves us from a lot
of headaches.
Since there's no active request during a name lookup failure, explicitly fail all sent and queued requests, so the Request subclasses can take regular failure action.
Work-around a crash on certain Mac builds (I can't tell why other work fine) where the called parameters to apr_pool_create_ex are problematic. Explicitly pass the default values for the function.
As doesnt seem to work to just resize the texture, if changing
the size of the Canvas render target a new FBO is created and
placed on all active placements.
ENABLE_SOUND=0 now works when configuring SimGear, and libSimGearScene can be linked without OpenAL. However, more testing of FlightGear in this mode is needed before it's officially supported!
- Implement click event creation like specified in
DOM Level 3:
* Check for max move distance between mousedown/up
and clicks
* Check for click timeout
* Count clicks and report double clicks
- Now it is possible to attach listeners to canvas
elements and also the canvas itself, which get
called upon different mouse events (Currently
only basic mouse events supported. click/dblclick
etc. are missing)
Ubuntu/Debian introduced "multiarch" library directories, which is
unsupported by CMake <= 2.8.10. Add manual search paths as a workaround.
Currently it is only needed for libsvn, but it is needed for any lib
which is converted to the new directory standard.
Since there's no external lock, it was impossible to check the queue was non-empty before a pop, without a race condition. To avoid this, tolerate an empty queue and return a default constructed value.
Remove duplicate members shared by SGSoundSample and SGSampleQueue (which inherits from it). Change SGSoundSample to expose some members as protected data for access by the sample-queue, and hence share nearly all the methods. Also remove 'inline' keyword from virtual methods.
Tolerate slightly malformed request URLs (no slash following the host specified), and use a better check when POST-ing to decide the request-body data source.
Packs arbitrary data (strings, property trees, binary blobs, ...) into a
single file.
Use this for storing/loading user-data only, not for distribution files
(scenery, aircraft etc).
It's possible (and happens!) to have less than 2^16 vertices or tex-coords, but more than 2^15 objects (tris) with the same materials. This was breaking our version 7 vs version 10 detection logic. Pete found the issue, I'm simply committing a version of his fix.
parseColor is used to parse a CSS color string into an osg::Vec4
which is only available in SimGearScene. If someone needs the
function also in SimGear headless mode we have to think about
where to better place this function.
- Refactor Canvas from FlightGear and fix lazy rendering with
recursive canvases.
- New classes PropertyBasedElement and PropertyBasedManager for
creating subsystems controlled by the property tree.
- New method parseColor to parse CSS 3 conformant color strings
(only basic color schemes supported)
- New Rect class representing a rectangle.
- Subsystem which manages a list of elements which
are controlled through the property tree.
- Fix a ShivaVG compiler warning.
- Add some helper functions to trigger property removed/add
events for a whole property tree.
Order of files in file system order is random (maybe different for every
user). Determinsm is good, i.e. when loading Nasal scripts in a fixed,
known sequence, or config files, where the later may overrule settings of
the earlier.
Flatten the leaf nodes in the paged bounding volume tree
as good as possible. The implementation still assumes a
whole world database which actually holds for our usual
scenery.
This kind of work is done two times for different
flavours of bounding volume generation. Factor
out and use this in BVHPageNodeOSG.cxx and
BoundingVolumeBuildVisitor.hxx.
It's common to use SGTime to calculate the the Julian Date, without providing time-zone information. Don't warn in these cases, since the behaviour is fine.
Allow subsystem init to be incremental, i.e requiring repeated init calls until a 'done' code is returned. Use this to support incremental init in groups and the manager. (It would also be possible to support it in an individual subsystem).
Note that if you use the existing init() calls, behaviour is unchanged.
At least one Linux distribution packager of FG has complained that we're bundling expat in our binaries. To keep them happy, add the option (-DSYSTEM_EXPAT=1 at cmake time) to use the system expat instead.
For the moment (and simplicity), this requires building SIMGEAR_SHARED (which is fired to on by selecting the option).
Clang was complaining that SGSky has virtual methods, but no virtual destructor. It turns out we're never subclassing SGSky - it's used directly. Hence, remove all the 'virtual' attributes from its methods.
CMake has never supported the MIPS compatibility headers, or indeed building using MIPSpro. If someone wishes to re-add MIPS/IRIX support, I'm hoping they will be using a compiler with functional standard library headers!
Imitate Q_UNSUED from Qt, and provide a Simgear 'unused var' warning suppression macro. Fix up one place where the previous warning suppression attempt (assigning to self) was still producing a warning under clang.
Always create only two SimGear libraries: SimGearCore and SimGearStatic, regardless of whether we're building static or shared. This requires an updated to FindSimGear.cmake module, for the static configuration.
This eliminates the black borders on runways between threshold and
designation textures and also between two designation numbers.
Thanks to Emilian for tracking this down!
Distros like Debian/Ubuntu use architecture-specific directory structures
(like /usr/lib/x86_64-linux-gnu) which we cannot hardcode/guess, so we
really need to search the default paths.
The new callback has a default implementation of the callback
methods that do call back into the registrys callback before
calling the registrys implementation directly.
This is meant to be used together with ReaderWriterOptions that
still want to call back into the normal callback chain of the
registry.
The flags are meant to be used for fgelev and for an ai
module that will probably only need ground elevation queries
in those reagions where the aircraft simulated there will roll
that is on airports.
The basic boundignvolume implementation does only need math and
geometry. As such it is agnostic to the scenegraph being used.
Only the parts building this query structure from terrain
depend on the implementation of the terrain.
So, move this into the simgear core component.
Adapt the freealut code into a WAV-file reader. As a side-effect, it would now be possible to deploy WAV files compressed with gzip, since we use ZLib's gzread functions to read from disk.
Previously, any effect attribute that was set via effect parameters i.e., was
not a constant value, was marked with data variance DYNAMIC. Now, only
attributes that get their values from the property tree are so marked.
# Oops. ENABLE_LIBSVN is ON, but svn is still missing.
# Provide clearly visible warning/hint, so builders know what else they should install (or disable).
message(WARNING"Failed to enable subversion client support. Unable to find required subversion client library. Some features may not be available (scenery download).")
message(WARNING"Install 'libsvn' library/DLL (libsvn-devel/libsvnclient/...). Otherwise disable subversion support (set 'ENABLE_LIBSVN' to 'OFF').")
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.