Compare commits

...

781 Commits

Author SHA1 Message Date
Automatic Release Builder
af8b27032f new version: 2020.1.2 2020-05-18 11:54:22 +01:00
James Turner
f76b72e2f3 Adjust RelWithDebInfo optimisation for Clang
This should give a bit of speed boost to macOS official builds.
2020-05-14 13:50:58 +01:00
James Turner
59512aea1f Windows: ensure RelWithDebInfo is fast
Default CMake RelWithDebInfo pessimizes inlining
2020-05-10 19:46:27 +01:00
James Turner
96618a2e26 Enable old-style texture compression
Thanks to Dany for tracking this down!
2020-05-10 19:46:27 +01:00
James Turner
635f460dd5 Nasal: improve message for non-object member access
Based on some discussion on this ticket:

https://sourceforge.net/p/flightgear/codetickets/2186/

Make this message slightly clearer.
2020-05-03 12:22:23 +01:00
James Turner
36316e8859 Add Canvas::Image.dirtyPixels() 2020-05-03 12:22:11 +01:00
James Turner
81bdae283a new version: 2020.1.1 2020-04-27 09:29:54 +01:00
James Turner
00e25404c7 Add simgear::optional
This is a poor-man’s proxy for std::optional until we have it.
2020-04-25 18:05:59 +01:00
gallaert
6a157e1c08 Replace boost::tuple by std::tuple 2020-04-22 14:04:21 +01:00
gallaert
7a6f9151a6 General boost cleanup 2020-04-22 14:04:21 +01:00
gallaert
567293c14d Replace boost::function by std::function 2020-04-22 14:04:21 +01:00
gallaert
2ff6a4966a Replace boost::bind by std::bind and lambda function 2020-04-22 14:04:21 +01:00
gallaert
b13d7f9392 Replace boost::lexical_cast by std::ostringstream and std:stof/stoi/stod 2020-04-22 14:04:21 +01:00
gallaert
d21137739d Replace boost::enable_if/disable_if/enable_if_c/disable_if_c by std::enable_if 2020-04-22 14:03:47 +01:00
gallaert
1e13cf6fec Replace boost::shared_ptr/weak_ptr by std::shared_ptr/weak_ptr 2020-04-22 14:03:47 +01:00
James Turner
5c52cdc255 Fix for crash on reset:
https://sourceforge.net/p/flightgear/codetickets/2217/

Ensure that subsystem lookup during its own removal, returns nullptr.
Otherwise we cache an about-to-be dead pointer, which is Bad (TM)
2020-04-22 10:55:41 +01:00
James Turner
17d7808200 Remove a log message 2020-04-22 10:54:44 +01:00
James Turner
f144bd5a89 CanvasImage: fix updating after fillRect / setPixel 2020-04-18 21:31:16 +01:00
James Turner
b72553f6f0 Nasal: add isscalar() for Henning 2020-04-18 18:06:35 +01:00
James Turner
c82a14c252 Nasal: fix build on non-C99 mode
It seems GCC at least is strict about C99 mode.
2020-04-16 16:44:20 +01:00
James Turner
faa559e9af Nasal: add vecindex() built-in 2020-04-16 13:40:41 +01:00
James Turner
c51c0c43ed Nasal: add more isTYPE helpers from Henning 2020-04-16 11:42:41 +01:00
gallaert
2ab0122124 Replace boost::to_lower and boost::to_upper by strutils::lowercase and strutils::uppercase 2020-04-14 13:24:59 +01:00
James Turner
8626e0482d Nasal: add some type-check helpers.
These avoid building a string for the result, as typeof() does
2020-04-14 13:24:06 +01:00
gallaert
c9a4c0dac1 Replace BOOST_FOREACH by C++ 11 for range loop. 2020-04-12 14:39:12 +01:00
gallaert
825d93423d Statements following return, break, continue, goto or throw will never be executed. 2020-04-12 14:39:12 +01:00
Erik Hofman
ad24ce02e7 Remove some debugging statements 2020-04-12 14:53:16 +02:00
Erik Hofman
695616a8f2 Switch from doing the calculations ourselves in case of a bad_doppler implementation to using alDopplerFactor 2020-04-12 14:50:12 +02:00
Erik Hofman
b3bdf8636a Limit the velocity to the sound velocity after multiplying it by a foctor of 100 to compensate for bad Doppler calculations. Also add the option to set the sound velocity for the sound manager from within FlightGear (not yet used). 2020-04-11 09:48:49 +02:00
James Turner
c62c080a4b Logging: enable the WinDebug callback using an env var.
Instead of hard-coding, add an env-var SG_WINDEBUG to enable the
logging to the Windows debug stream.
2020-04-10 19:50:58 +01:00
James Turner
c90ab3df5b Packages: consider checksum failures for retry.
This means an out-of-sync mirror causes a retry on a different
mirror server.
2020-04-10 15:03:17 +01:00
James Turner
21e21a1fa8 Allow TiedPropertyList to fire valueChanged 2020-04-10 10:41:00 +01:00
James Turner
92ebdbfacc Expose compare-version helper publicly.
This helper was added for Catalog version checking, but will be used in
FlightGear now, so move it to strutils.
2020-04-09 14:39:12 +01:00
James Turner
8dbabc8b43 Texture-compression fixes
Rename a highly confusing method, and disable the older texture-
compression code since it interacts badly with the new texture-cache.
2020-04-07 12:12:52 +01:00
James Turner
c83dc79357 Revert to C++11 for now, found an alternative solution. 2020-04-06 10:44:23 +01:00
James Turner
a53c1bfe8b CMake logic to export debug symbols 2020-04-05 14:04:19 +01:00
James Turner
6185b8fd0d Fix crash with Touch animation mouse-up 2020-04-05 14:04:19 +01:00
Richard Harrison
ef002f6dfa Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/73/
2020-04-04 20:43:04 +00:00
James Turner
9cdec99fa4 Quiet some warnings 2020-04-03 10:00:22 +01:00
Fernando García Liñán
9393f84972 Compositor: Fix crash when using clustered shading with OSG 3.6 2020-04-02 21:21:55 +02:00
Stuart Buchanan
ceba006c60 Only sync scenery-path-suffix with valid name
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.
2020-04-01 21:47:53 +01:00
James Turner
e9e2053c64 Strutils: add hex-decoding helper
This will be used to allow entering hex bytes in XML files, for HID
descriptor support on Windows.
2020-03-31 10:09:47 +01:00
Fernando García Liñán
bf013aea54 Compositor: Improve custom depth range handling in scene passes. 2020-03-30 19:23:03 +02:00
Stuart Buchanan
454df4872a Reduce shader attribute usage by packing floats
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.
2020-03-26 22:09:04 +00:00
James Turner
ec315bf26d Fix thumbnail cache retrieval
Use direct reading of thumbnail-cache files, instead of using libCurl
2020-03-26 16:51:00 +00:00
James Turner
74c304097d Fix for older libCurl versions 2020-03-26 16:51:00 +00:00
Erik Hofman
ad1833a4d5 Move more modern C++ idioms and use std::unique_ptr for moving daat ownership around 2020-03-26 09:54:28 +01:00
James Turner
d65bb58317 HTTP: increase the Curl download buffer size
This improves download performance with large files, i.e,
most of them.
2020-03-24 20:34:49 +00:00
James Turner
8cf11f9208 Packages: fix handling of unsafe paths in zips
This was breaking the P-51D which contains a mis-named PNG file which
tripped the unsafe path detection.
2020-03-24 13:51:57 +00:00
Fernando García Liñán
73f00bd842 Compositor: Added support for logarithmic depth buffer. 2020-03-22 17:24:48 +01:00
Fernando García Liñán
1b6545fc05 Compositor: No longer append 'Compositor/' to Effects when the Compositor is
enabled. Do not remove transparent bins in shadow passes.
2020-03-22 17:24:48 +01:00
James Turner
40725a76ab Packages: randomise mirror URL selection
Also add retry on mirrors when a download fails.
2020-03-21 18:31:53 +00:00
Erik Hofman
75f40fad95 Use more modern C++ 2020-03-20 10:40:09 +01:00
Erik Hofman
b458300c02 'lin' is a valid value for the type parameter so do not show a warning. Add a 'random' tag for pitch offset 2020-03-20 09:56:21 +01:00
Erik Hofman
6c6e74e8d1 Change logging levels to developer mode and be more descriptive 2020-03-19 13:33:30 +01:00
gallaert
4bab064ad6 - When HLA is enabled in Simgear, HLA is also enabled in Flightgear
making the build between Simgear and Flightgear consistent.
- Fix an issue with lib/lib64 path between CentOS/RedHat distributions
  and Debian derived distributions.
2020-03-15 22:29:43 +00:00
gallaert
3da2880aae Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2020-03-15 21:32:42 +00:00
James Turner
c8d802bc1d More SGPath / UTF-8 fixes
Use SGPath in more public APIs, so FlightGear doesn’t have to convert
and guess the conversion itself.
2020-03-15 14:26:42 +00:00
James Turner
c3a169319c Fix UTF-8 shader path support
Work around osg::Shader::loadShaderFromSourceFile ’s lack of UTF-8
support by loading using our own istream, and then setting the text
directly.
2020-03-15 14:26:42 +00:00
Erik Hofman
72af950573 Fix an error 2020-03-15 14:57:24 +01:00
Erik Hofman
edae7a2b75 Make warnings and alerts a single message for DEV_WARN and DEV_ALERT since they will result in a popu-dialog message 2020-03-15 14:33:05 +01:00
Erik Hofman
1fa48e7edb File readind is not of the SG_INPUT class s change it to SG_IO and make all warinigs and alerts developer-warings and developer-alerts 2020-03-15 14:24:02 +01:00
Erik Hofman
d76992efe6 Show the affected file when displaying an animation error or warning 2020-03-15 10:44:29 +01:00
James Turner
87da4680c7 Tweaks to Windows string conversion
Avoid use of code-cvt, and tolerate differences in compiler handling of
string literals (tested Clanged and MSVC, hopefully GCC is kind)
2020-03-14 20:10:20 +00:00
Richard Harrison
9cc7508b07 fixes #2123 Relocation splash distorted.
Allow splash screen as an origin and do not allow splash screens to be cached and thus the poweroftwo rules don't apply.
2020-03-13 20:07:31 +01:00
James Turner
b258bc598e Load time-zones from UTF-8 paths correctly
Use _wfopen on Windows, after converting UTF-8 paths to wchar
2020-03-13 16:48:12 +00:00
James Turner
f25c0c60a8 Use UTF8 paths in nearly all places, for OSG
We already request OSG to use UTF8 paths, so ensure whenever we pass
an SGPath to OSG, we use the correct conversion function.
2020-03-13 09:50:43 +00:00
James Turner
f350bd31bd CanvasImage: fillRect / setPixel tweaks
Fix image dirtying and allocation without an underlying fike
2020-03-11 17:12:42 +00:00
gallaert
06f1699223 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2020-03-09 22:13:16 +00:00
James Turner
3e4d528859 Additional install / download failure test
Ensure we can install again on a previously failed URL.
2020-03-09 15:00:23 +00:00
Erik Hofman
b847f57382 Fix a threads header 2020-03-09 14:56:08 +01:00
gallaert
2d7ad25031 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2020-03-01 16:14:13 +00:00
James Turner
d670cc13ac testHTTP mods to investigate macOS failure.
Disabled one test for now, since it’s blocking macOS release process
2020-02-25 16:12:12 +00:00
James Turner
43699d039f Track package install status persistently. 2020-02-25 14:27:48 +00:00
James Turner
9192b009e1 Catalog enable/disable feature 2020-02-24 11:35:04 +00:00
Stuart Buchanan
3fe85809b2 Add support for tarballs in Terrasync 2020-02-16 20:26:20 +00:00
Stuart Buchanan
a4b79d6882 Merge /u/tbmoore/simgear/ branch tmoore/canvas-mipmap into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/52/
2020-02-12 21:02:43 +00:00
gallaert
fc21e6eafa Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2020-01-31 22:51:14 +00:00
Erik Hofman
11e243a216 Clean up the threading code: remove the private classes. 2020-01-29 11:33:54 +01:00
Stuart Buchanan
9f862dcc0e Fix directional lights for AMD
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.
2020-01-27 09:28:25 +00:00
Erik Hofman
faf43d2c4b Comment out Windows debugging code, for now 2020-01-24 19:30:32 +01:00
Erik Hofman
b0580b2df5 Re-order the mutex locking of the condition-mutex and the caller-mutex, add noxecept. Also add some debugging code to detect multiple locks of the same mutex. 2020-01-24 15:46:36 +01:00
Erik Hofman
308903dc91 Revert to c3ae704610 until the condition_variable problem is solved 2020-01-24 13:52:37 +01:00
Erik Hofman
1c7fd67c39 Convert condition variables to C++11 too. 2020-01-24 10:48:53 +01:00
Erik Hofman
c3ae704610 Move SGThread::current to after the system dependent code which includes the proper header files 2020-01-23 13:47:04 +01:00
Erik Hofman
9f8e6c0634 Make backwards compatible stubs so only a recompile without any modification is required. 2020-01-23 10:38:52 +01:00
Erik Hofman
aab88b411e Switch to C++11 threads, mutexes and lock_guards. Switching to C++11 condition_variables requires some more thought. 2020-01-22 13:44:47 +01:00
James Turner
867cf6b60a test_Http: Better completion checking 2020-01-19 06:30:10 -08:00
gallaert
ed87114c5e Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2020-01-11 18:52:36 +00:00
Julian Smith
213adb5f0d simgear/debug/logstream.cxx: ensure fgfs.log always includes file:line.
This is a bit of a hack - we set line = -line if m_fileLine is false, so that
the +ve value can be recovered by FileLogCallback::operator().
2019-12-31 16:50:46 +00:00
Scott Giese
c5c10a003a Rollback error until stability issues are resolved. 2019-12-31 10:29:25 -06:00
Julian Smith
e78205f071 simgear/debug/logstream.cxx: Fixed FileLogCallback to not output <filename>:-1.
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.
2019-12-29 19:04:47 +00:00
Richard Harrison
ba7134c2a2 Use isfinite to determine if an FP number is valid.
ref: https://forum.flightgear.org/viewtopic.php?f=30&t=36600&sid=4bdfcb69abb4a6440cd8965aa03815d5#p357164
2019-12-29 13:50:21 +01:00
Richard Harrison
1eadaa4cda Protect against null reference when effect not found 2019-12-29 13:48:40 +01:00
Richard Harrison
d93ce29b20 Exclusive thread possible fix for Linux
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)
2019-12-29 13:48:09 +01:00
Richard Harrison
0cddb9e843 Revert "Disable NasalMainLoopRecipient"
This reverts commit 67e2860cc3.
2019-12-29 13:45:42 +01:00
Scott Giese
67e2860cc3 Disable NasalMainLoopRecipient
This is preventing FGFS shutdown on Linux OS.
Does not appear that this thread is properly joined and terminated.
2019-12-27 20:48:02 -06:00
James Turner
0cf9dd165e Add NetBeans .gitignore 2019-12-24 20:58:48 +00:00
James Turner
3aa567b672 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/70/
2019-12-24 19:47:25 +00:00
Fernando García Liñán
fa1e3cb183 Support in Effects for reading 3D textures from disk as an array of 2D textures 2019-12-24 03:37:14 +01:00
Fernando García Liñán
14845bf3f2 Compositor: Provide previous frame transformation matrices and the sunlight direction as uniforms 2019-12-24 03:34:37 +01:00
Fernando García Liñán
120328eb2b Removed 'using namespace' from header 2019-12-24 03:31:28 +01:00
gallaert
e222c0888c Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2019-12-19 11:48:09 +00:00
James Turner
ec19dfc2f2 Fix Windows build
__PRETTY_FUNCTION__ is not portable, alas.
2019-12-18 23:43:40 +00:00
James Turner
da45c26e7d Adding pixel manipulators to canvas::Image 2019-12-17 22:32:25 +00:00
James Turner
c39a5fd8c0 Fix some Clang warnings 2019-12-17 22:32:25 +00:00
Scott Giese
fb57fe9da7 Catching an exception by value 2019-12-15 03:12:54 -06:00
Scott Giese
02496da4d2 Logic error 2019-12-15 03:08:06 -06:00
Scott Giese
eb1afec22b Remove unused object creation 2019-12-15 02:39:43 -06:00
Scott Giese
1619df97f8 Potential unterminated string 2019-12-15 02:19:13 -06:00
Scott Giese
c653a82619 Eliminate unitialized warning 2019-12-15 02:00:16 -06:00
Scott Giese
2289618cea Fix conditional compile logic 2019-12-15 00:18:39 -06:00
Scott Giese
dc886118ba [CanvasText] Fix conditional compiles 2019-12-15 00:13:46 -06:00
Scott Giese
879b01004b [CanvasText] Fix conditional compiles 2019-12-14 23:31:13 -06:00
Stuart Buchanan
86f3169e4b Shader Buildings - fix roof orientation
Correct transformation to make roof ridges match orientation
in documentation.
2019-12-08 17:36:23 +00:00
Stuart Buchanan
d5957b8c5f Random Buildings - improved texture mapping
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.
2019-11-23 17:05:20 +00:00
James.Hester
595eb3efea Change order of test for is_plantation as per feedback. 2019-11-21 20:36:56 +11:00
James.Hester
81e93448e3 Merge branch 'plantation' into next 2019-11-17 09:05:47 +11:00
James.Hester
0f9fe8adef Add generation of plantation vegetation to TileDetailsCallback.
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.
2019-11-16 11:16:09 +11:00
James.Hester
56933067c0 Add "is_plantation" property to materials definitions. 2019-11-16 11:02:35 +11:00
James.Hester
0919f5bf9c Improve comments on previous commit. 2019-11-12 08:00:04 +11:00
James.Hester
b91d4411b5 Added point_in_triangle function. 2019-11-12 07:55:09 +11:00
Erik Hofman
15c6131f0e Use a better way to set the listener position and orientation 2019-11-08 10:51:56 +01:00
James Turner
c2f2f25046 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/68/
2019-11-07 17:38:31 +00:00
Fernando García Liñán
94ced66f87 Compositor: Enable more culling for shadow passes 2019-11-07 15:46:05 +01:00
Erik Hofman
ece2f913a1 Get AeonWave up to par again by removing a number of errors, and fixing a unit type for the audio cone inner and outer angle. 2019-11-07 15:15:02 +01:00
Fernando García Liñán
2b2ada2037 Compositor: Added support for spotlights in clustered shading 2019-11-07 15:09:26 +01:00
Julian Smith
1a4568175c simgear/environment/metar.*: getDescription() can now also use single spaces.
If <tabstop> param is -1, all sequences of tabs are replaced by a single space.
2019-11-06 19:56:03 +00:00
Julian Smith
0c8949e723 simgear/environment/metar.cxx:SGMetar::getDescription(): minor improvements to returned text.
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.
2019-11-06 19:56:03 +00:00
James Turner
012966f6a2 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/67/
2019-11-05 09:32:28 +00:00
Erik Hofman
82b1cca247 Also add pressure to the mix 2019-11-04 15:18:59 +01:00
Erik Hofman
2976dc29d5 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2019-11-04 14:54:30 +01:00
Erik Hofman
99d5b0dc8a Switch to in-place declarations and to the ISO9613 distance attenuation model for AeonWave which also calcualtes the proper sound velocity based on atmospheric properties 2019-11-04 14:54:06 +01:00
Fernando García Liñán
d1eb768de6 Disabled CASTSHADOW_BIT on most of the scene graph geometry to optimize performance 2019-11-03 20:53:55 +01:00
Julian Smith
5db8e42c69 simgear/environment/metar.*: added getDescription().
Returns human-readable descrition of metar. Uses code from
flightgear:src/Main/metar_main.cxx.
2019-11-01 22:55:20 +00:00
Fernando García Liñán
c7efa81efe Only use effect schemes when the Compositor is enabled 2019-10-30 17:14:38 +01:00
James Turner
7d92698644 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/64/
2019-10-29 08:40:00 +00:00
Stuart Buchanan
4b280a00db Shader Buildings - fix roofs, set small tex to 5m
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.
2019-10-26 16:29:37 +01:00
Fernando García Liñán
02b61b145a Compositor: Shaders are looked for in $FG_ROOT/Compositor/Shaders when the compositor is enabled.
Fixed Compositor/ always being added to the effect filename. Now it is only added when the base folder is Effects/.
2019-10-26 01:53:30 +02:00
James Turner
0a7514c47b Add new ‘listener-safe’ SGProperty attribute
Used in FG to make certain tied properties as safe to use with
listeners, and hence suppress the warning.
2019-10-20 13:03:15 +01:00
James Turner
4b1a53367f Runway lights improvements from Sascha Reißner
(Sascha Reißner <reiszner@novaplan.at>)
2019-10-20 13:02:30 +01:00
James Turner
de3625d992 Fix linkage of OpenAL tests
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.
2019-10-19 07:42:28 -07:00
Mykola Orliuk
65331599ec BoostTestTargets.cmake: support CMake 3.15
Signed-off-by: James Turner <zakalawe@mac.com>
2019-10-17 09:41:35 +01:00
Stuart Buchanan
74cd8cf75c Shader building roof types
Shader buildings now support multiple roof types:
- flat
- gabled
- hipped
- pyramidal
2019-10-08 21:38:48 +01:00
Stuart Buchanan
07586e84ce Rotate orientation of pitched roofs by 90 degrees
Also add some additional checking of parameters.
2019-10-06 12:52:12 +01:00
James Turner
ca97b4371b Use alternative name for internal expat_config.h
Avoid clashes when system has expat installed.
2019-10-05 17:19:09 +01:00
Scott Giese
b742607c76 [ReaderWriteSTG] fix for missing header. 2019-10-03 11:50:07 -05:00
ThomasS
1399cc9482 Additional interface to ReaderWriterSTG for adding callbacks for unknown STG token handler 2019-10-03 08:03:37 +02:00
Stuart Buchanan
7464e17e22 Swap width and depth for shader defined buildings
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.
2019-10-01 14:56:18 +01:00
Stuart Buchanan
053bda26a4 Shader buildings - split wall and roof tex index
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.
2019-09-25 21:53:19 +01:00
James Turner
93995cd742 Nasal GC : Fix crash running FG unit-tests
When freeing a context, clear its stack so that anything dangling in
them (especially the opStack) is GCed.
2019-09-19 08:05:55 +01:00
Scott Giese
202dfc9ebe Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2019-09-17 12:51:47 -05:00
Scott Giese
23f378cd93 Support VS 2019 - courtesy of Lars Toenning 2019-09-17 12:51:05 -05:00
Scott Giese
70c564dd2c Fix compile issue on Win10 VS2019 2019-09-16 23:30:59 -05:00
Julian Smith
9bea6afb80 Revert "simgear/scene/model/ModelRegistry.cxx: avoid noisy diagnostic from OSG."
This reverts commit 7762bc2cad.

This broke Windows and Mac builds.
2019-09-05 15:00:22 +01:00
Julian Smith
20fb7a9ce0 simgear/debug/logstream.cxx: Allow runtime control of file:line in diagnostics.
New fn logstream::setFileLine() allows other code to control whether log output
includes file:line information.
2019-09-02 16:10:38 +01:00
Julian Smith
7762bc2cad simgear/scene/model/ModelRegistry.cxx: avoid noisy diagnostic from OSG. 2019-09-02 16:10:10 +01:00
Julian Smith
f407785f10 Fixes for building on OpenBSD. 2019-08-22 17:35:13 +01:00
Stuart Buchanan
138e28fcbe Instance-based 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.
2019-08-20 17:00:17 +01:00
Richard Harrison
38f6a5a40a Remove fairly irrelevant startup log message from NasalMainLoopRecipient
This is probably the reason why the tests are failing.
2019-08-14 16:47:25 +02:00
Scott Giese
b28f030874 [CanvasText] Restore support for OSG 3.4 2019-08-04 10:43:00 -05:00
Scott Giese
d883ab278d [osgText.getActiveFont] Breaking change within OSG 2019-08-04 02:27:57 -05:00
gallaert
40ce45c8e9 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2019-07-13 18:12:22 +01:00
Edward d'Auvergne
fa754ecaf8 SGSubsystem classes: Registration of all subsystems. 2019-07-01 14:37:49 +02:00
Edward d'Auvergne
c11557316d SGSubsystemMgr: Changed the Registrant class argument order.
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.
2019-07-01 14:37:49 +02:00
Edward d'Auvergne
5bf28d3f90 SGSubsystemMgr: Expanded the dependency list types.
All the dependency types are now documented.
2019-07-01 14:37:49 +02:00
Edward d'Auvergne
c8625ce599 SGSubsystem classes: Addition of staticSubsystemClassId() to all subsystems. 2019-07-01 14:37:48 +02:00
Edward d'Auvergne
991fafb839 SGSubsystemGroup: Removal of the subsystem group naming.
This is a partial reversion of c1dd8faa29 and a
complete reversion of caea68007e and
846f024e91.  These changes are incompatible with
the subsystem class IDs.
2019-07-01 11:07:03 +02:00
Edward d'Auvergne
d7323f5f19 SGSubsystem classes: Renaming of the subsystem ID variables and functions. 2019-07-01 10:51:41 +02:00
Edward d'Auvergne
10662e4ca5 SGSubsystem classes: Subsystem and subsystem group API declaration standardisation.
This is a cleanup commit.
2019-06-16 14:12:38 +02:00
Edward d'Auvergne
b73dfb08ae SGSubsystem classes: Whitespace standardisation of the declarations.
This is a clean up commit prior to the subsystem API standardisation to simplify
the diffs.  It includes all SGSubsystem and SGSubsystemGroup derived classes.
2019-06-16 14:12:38 +02:00
Scott Giese
d8a46cffa5 [emesary] Fix naming conflict with some compilers 2019-06-15 17:22:53 -05:00
Scott Giese
3b3093c72e [nasal] remediate segfault in lib.c
state of vaCopy is altered during each usage, so it needs to be discarded and not reused by multiple calls.
2019-06-15 11:54:35 -05:00
Scott Giese
3d841a214c Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2019-06-14 22:12:02 -05:00
Scott Giese
2cbbb29eb5 [Emesary] Fix compile on Linux. 2019-06-14 22:11:31 -05:00
Scott Giese
c0677ad8c5 [Emesary] Fix compile on Linux. 2019-06-14 21:43:47 -05:00
James Turner
098c5b0924 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/62/
2019-06-11 21:56:28 +00:00
Richard Harrison
01ac9a71b7 Fix case sensitive filename for emesary.cxx 2019-06-11 23:40:21 +02:00
Fernando García Liñán
ab8b1d39bd Fixed undetected compiler error due to gcc accepting variable-length arrays 2019-06-11 23:05:09 +02:00
James Turner
b22a8debf2 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/61/
2019-06-11 14:59:05 +00:00
Richard Harrison
92a3c8bbd8 Added Nasal garbage collection background thread
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.
2019-06-11 13:44:52 +02:00
Richard Harrison
c71f287498 SG Threading added new class for an exclusive thread
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.
2019-06-11 13:30:29 +02:00
Richard Harrison
b7f8fbe7a0 Nasal lib: dosprintf
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.
2019-06-11 12:38:49 +02:00
Fernando García Liñán
1ca3f60f80 Compositor: Significant rework of the clustered shading feature
- 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.
2019-06-10 16:02:32 +02:00
Richard Harrison
7a903361e6 Added Emesary
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
2019-06-09 13:07:50 +02:00
Richard Harrison
4f6e72de55 UDNS Windows compatibility changes
For some reason the config file doesn't generate with WINDOWS defined on my system.
2019-06-08 15:49:15 +02:00
Richard Harrison
a68c4e9434 DDS Texture cache improvements
- 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.
2019-06-08 15:38:22 +02:00
Richard Harrison
798b90e0a5 Added Emesary 2019-06-08 10:12:22 +02:00
Richard Harrison
cba902f22b Nasal GC background threaded merge.
Merge branch 'nasal-background-thredead-gc'
2019-06-08 10:07:48 +02:00
Richard Harrison
8eb51e813f Added Emesary to SimGear Core 2019-06-03 23:32:49 +02:00
Richard Harrison
9ac3c1a394 Revert GC instrumentation committed by mistake as part of "SGTimeStamp elapsedUSec"
This reverts commit 0b114ac5cd, reversing
changes made to 39eb9837e9.
2019-05-27 18:49:33 +02:00
Tim Moore
5486ca3b4a Protect logstream startup entries with a mutex 2019-05-24 10:15:06 +01:00
Tim Moore
90845974ea nasal/lib.c: Make copy of va_list for each traversal
It's not portable to traverse a va_list more than once.
2019-05-24 10:14:50 +01:00
James Turner
57fd817486 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/58/
2019-05-22 12:57:13 +00:00
Fernando García Liñán
b322fa8f32 Use $FG_ROOT/Compositor/Effects instead of $FG_ROOT/Effects when the compositor is enabled
This allows coexistence of new compositor-compatible effects and current effects.
2019-05-20 23:40:12 +02:00
Fernando García Liñán
81d1e16d7b Compositor: Removed intersection checking
This is now responsibility of the CameraGroup.
2019-05-20 22:51:40 +02:00
Erik Hofman
4c52d77aa5 Add missing cassert incldues 2019-05-20 11:00:51 +02:00
James Turner
523d5166ef Merge /u/dancliff/simgear/ branch fix_sound_on_model_reload into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/57/
2019-05-14 20:33:12 +00:00
Dan Wickstrom
cde95864b4 Aircraft model reinit deletes sound effect samples, but leaves them defined in the sample group, so a reload doesn't re-add them. 2019-05-14 12:51:35 -04:00
Richard Harrison
7354201b5d Added background (threaded) garbage collector 2019-05-13 15:21:08 +02:00
Scott Giese
14971f88ee [soundmgr_openal] Pause/Resume Sound.
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.
2019-05-09 20:52:20 -05:00
Richard Harrison
0b114ac5cd SGTimeStamp elapsedUSec 2019-05-07 05:17:28 +02:00
Richard Harrison
c06eabff24 Instrumented Nasal GC 2019-05-07 05:17:27 +02:00
Richard Harrison
b3ef2478f5 Instrumented Nasal GC 2019-05-07 05:13:55 +02:00
Richard Harrison
39eb9837e9 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/55/
2019-05-05 13:50:27 +00:00
Scott Giese
1a429b63c5 [SGImageUtils] eliminate unused variable. 2019-05-04 15:45:53 -05:00
Scott Giese
ae6ad20940 [SGDemSession] fix uninitialized members. 2019-05-04 15:26:25 -05:00
Fernando García Liñán
3e57b50066 Added support for Effect schemes
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.
2019-05-04 19:15:22 +02:00
Florent Rougon
dd38e399ca Add readwav.hxx to HEADERS and readwav.cxx to SOURCES in all cases
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.
2019-04-27 11:23:14 +02:00
Florent Rougon
319b59500c Convert obsolete uses of get_filename_component(<var> <FileName> PATH)
In the context of get_filename_component(), PATH is a legacy alias for
DIRECTORY. Replace it with DIRECTORY, which is recommended[1] for
CMake versions > 2.8.11.

[1] https://cmake.org/cmake/help/latest/command/get_filename_component.html
2019-04-25 19:19:19 +02:00
Fernando García Liñán
3a79b71e80 Compositor: Effects used by a compositor now receive a proper SGReaderWriterOptions and other misc fixes 2019-04-23 03:35:10 +02:00
gallaert
0c0eab9247 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2019-04-22 19:08:39 +01:00
James Turner
114ddcff52 Tweak code for older GCC 2019-04-11 21:39:41 +01:00
James Turner
57339486d9 Flip the default meaning of alternate-mouse-wheel-dir 2019-04-11 20:37:47 +01:00
Richard Harrison
5f9b17d55b Terrasync fixes;
- 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)
2019-04-08 14:08:58 +02:00
Tim Moore
325b89e023 Fix automatic mipmap generation for Canvas textures
When using glTexStorage2D, OSG doesn't allocate storage for the levels
of the mipmap above the base unless an image is assigned to the
texture.
2019-04-04 12:07:34 +00:00
Tim Moore
9ebc823975 Optimize parsing of property node names
Add hand-coded versions of isalpha() and isdigit(), which were a
hotspot in profiling.
2019-04-04 12:00:18 +00:00
James Turner
5fdf6ef4f3 Simgear parts of queued command execution
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.
2019-03-24 14:13:42 +00:00
Richard Harrison
0792962591 add simgear::strutils::replace 2019-03-17 18:20:27 +01:00
Torsten Dreyer
f964374027 new version: 2019.2.0 2019-03-13 21:20:49 +01:00
Torsten Dreyer
4352c0a737 new version: 2019.1.1 2019-03-13 21:20:49 +01:00
Stuart Buchanan
a0bdcb30fd Correct log messages. 2019-03-12 21:53:22 +00:00
Stuart Buchanan
7e0a10c016 Set radius for PagedLOD
Speculative fix to address scenery chunks being unloaded
unexpectedly under high load.
2019-03-12 21:45:34 +00:00
Richard Harrison
7fb6f82ab1 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/49/
2019-03-07 15:21:35 +00:00
Scott Giese
fdcc9c9e0e Fix compile issue with OSG versions below 3.4 2019-03-05 23:56:47 -06:00
Richard Harrison
846f024e91 SGSubsytem name compatibility for other compilers;
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.
2019-03-01 19:00:43 +01:00
James Turner
7e969f4e28 Updated star rendering phases/parameters
As part of this, adjust the normalisation so the active cutoff value
corresponds to 0.0 normalised intensity.
2019-02-25 16:12:41 +00:00
James Turner
10a701308d Make star cutoff controllable at runtime.
When a new property /environment/star-magnitude-cutoff is defined,
use this to set an upper bound on the magnitude of stars displayed.
2019-02-25 16:12:41 +00:00
Fernando García Liñán
e2bed86bfc Compositor: Enable small feature and view frustum culling by default for every pass. Added option to inherit the view master camera cull mask. 2019-02-23 23:26:27 +01:00
Richard Harrison
487cdc85cd DDS-TC; retain original filename and fix previous commit
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.
2019-02-21 19:07:37 +01:00
Richard Harrison
052bbecc3b OSG 3.4.0 compilation fixes and anisotropy
Set anisotropy on model textures after loading.
2019-02-20 19:10:58 +01:00
Richard Harrison
c860b12b3d OSG 3.4.0 compilation fixes 2019-02-20 19:10:58 +01:00
Richard Harrison
e227008331 DDS-TC handle sgio_exceptions during hash creation.
ref: https://sourceforge.net/p/flightgear/codetickets/2113/
2019-02-20 19:10:58 +01:00
Fernando García Liñán
72f3a784de Compositor: Added support for static branching and <property> tags to be able to configure the Compositor at startup. 2019-02-20 03:05:55 +01:00
Richard Harrison
31c9df665d Fix compile error related to missing osg version include (< 3.6)
For some reason this compiles on 3.6.
2019-02-19 15:11:04 +01:00
Richard Harrison
dd240116b1 Compositor compilation fixes for OSG 3.6 and Win32 2019-02-19 08:59:54 +01:00
Richard Harrison
92ec139175 Merge /u/fgarlin/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/47/
2019-02-19 07:28:58 +00:00
Stuart Buchanan
f076c43b90 Improve parsing of state machines
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.
2019-02-14 22:15:38 +00:00
Stuart Buchanan
98215e3dbd Improve error messages for Nasal prop references. 2019-02-14 22:13:54 +00:00
James Turner
6197098541 Guard against a potential race init-ing libCurl 2019-02-13 12:49:21 +00:00
James Turner
34b3c52a28 Improve HTTP redirect handling, and add test.
Ensure we get the final status code for the request after redirecting.
2019-02-13 12:34:17 +00:00
Richard Harrison
caea68007e Fix subsystem tests 2019-02-11 08:49:40 +01:00
Richard Harrison
c1dd8faa29 Improved subsystem performance monitoring and overrun detection
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
2019-02-10 17:48:21 +01:00
James Turner
95d065b3d7 Add strutils::iequals helper
Replaces another boost method
2019-02-06 12:35:08 +00:00
Scott Giese
2303da846b Fix missing header for OSG macros.
Patch provided by Stewart Andreason.
2019-02-05 21:46:02 -06:00
Scott Giese
7246edcb4b [boost::enable_if] Support Boost versions < 1.56 2019-02-05 12:20:06 -06:00
Fernando García Liñán
dc2f24dbed Compositor framework initial commit. 2019-02-04 18:02:44 +01:00
Scott Giese
4b793d5344 Remove deprecated boost/utility.
This is enable compatibility with boost 1.69.
2019-02-02 19:46:04 -06:00
gallaert
72dd45388f Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2019-02-01 12:34:40 +00:00
Richard Harrison
b76f78c6da OSG < 3.4.x fixes
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.
2019-01-26 17:48:31 +01:00
Richard Harrison
30482a3599 Fix errant spaces in DDS cache log file 2019-01-26 17:48:31 +01:00
Erik Hofman
b3f9571b2d Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2019-01-26 09:13:17 +01:00
Richard Harrison
0d5afe83a2 No need to set precipitation (rain/snow) each frame when it is turned off. 2019-01-24 18:07:05 +01:00
Richard Harrison
8b35c9a4b1 Improvements to the DDS texture cache
- 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..
2019-01-24 18:07:05 +01:00
Richard Harrison
a5d8eec25f Fix for deleting referenced object from model registry
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.
2019-01-24 18:07:05 +01:00
James Turner
df6ec4f94c Property alias loop protection
Patch by Henning Stahlke
2019-01-22 17:24:21 +01:00
James Turner
61ebee12ad Set curl VERBOSE based on current SG log settings 2019-01-22 17:24:21 +01:00
Scott Giese
105d63a697 Simgear: LARGE_INTEGER is defined in Windows.h
Fixes build issues on Linux.
2019-01-20 20:35:08 -06:00
Richard Harrison
07036ac48f Add load origin hint to options
This is to allow the DDS cache to handle the image load differently depending on the origin.
2019-01-20 18:28:37 +01:00
Richard Harrison
4f6c8f7784 Better error handling on load failure 2019-01-20 18:28:37 +01:00
Richard Harrison
8e57a61aed Fix null ref during load.
This happened a few times
2019-01-20 18:28:37 +01:00
Richard Harrison
8707005a97 Fix particles active even when disabled during load.
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.
2019-01-20 18:28:37 +01:00
Richard Harrison
cb024dd82d Fix for deleting still referenced object
ref https://sourceforge.net/p/flightgear/codetickets/2105/

Use the thread safe versions (getRef) of the objectcache methods
2019-01-20 18:28:37 +01:00
Richard Harrison
84046a6717 Add missing method 2019-01-20 18:28:37 +01:00
Richard Harrison
8bcaa50ba6 OSG3.7 changes 2019-01-20 18:28:37 +01:00
Richard Harrison
c433d29171 Win32: use high resolution timers (QueryPerformanceCounter) if available 2019-01-20 18:28:36 +01:00
Richard Harrison
64d51b5290 sg_file: Add compute hash method 2019-01-20 18:28:36 +01:00
Erik Hofman
6393b7704e Do not attempt to deregister the same emitter more than once 2019-01-16 14:55:37 +01:00
Erik Hofman
0a2071b2f1 Use AAX_PROCESSED since AAX_STOPPED is only a request to stop but the library decides when it is actually stopped. And AeonWave has become more picky about destroying emitters which aren't completely processed yet since MIDI support was added. 2019-01-15 11:38:38 +01:00
Erik Hofman
7981809f36 Split up SIMD support in ENABLE_SIMD which enables sse2 support for the compiler and ENABLE_SIMD_CODE which enables the hand crafted SIMD math functions which defaults to OFF now since compilers have catched up on generating optimized vectorized SIMD code. 2019-01-15 10:36:23 +01:00
Scott Giese
ed87a0b032 Eliminate compiler warnings 2018-12-23 22:16:05 -06:00
James Turner
fc2630e66d Revert "Logging API changes"
This is causing perf impact, so reverting until we figure out
a lower-impact solution.

This reverts commit 1be3e5771a.
2018-12-23 09:17:15 +00:00
Stuart Buchanan
ec14050890 General tiles with only BUILDING_LIST
Bug found during code-read.  If tile just contained BUILDING_LIST
entries (i.e. no OBJECT_STATIC or OBJECT_SIGN entries), then it would
not generate.
2018-12-22 16:52:05 +00:00
James Turner
4b17ea95fc Random buildings: reduce log output in a common case 2018-12-20 16:10:36 +00:00
James Turner
1be3e5771a Logging API changes
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>)
2018-12-20 16:10:36 +00:00
Stuart Buchanan
232cbbac5e DEBUG logging of model animation counts. 2018-12-19 20:05:06 +00:00
gallaert
dee204d2b2 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-12-13 21:59:16 +00:00
Stuart Buchanan
b71e9eac51 Fix 2092 DDS cache: segmentation fault when reloading scenery.
https://sourceforge.net/p/flightgear/codetickets/2092/

DDS cache: segmentation fault when reloading scenery.
2018-12-10 21:21:44 +00:00
gallaert
f88636f47c Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-12-06 12:35:21 +00:00
Edward d'Auvergne
8a301efe8b PropertyObject: create() function support for SGPropertyNode_ptr. 2018-12-04 12:38:14 +01:00
Edward d'Auvergne
5bd393135f PropertyObject: Unit test for declaration followed by definition. 2018-12-04 12:38:14 +01:00
Edward d'Auvergne
d550eac525 PropertyObject<std::string>: Added a default ctor. 2018-12-04 12:38:14 +01:00
Edward d'Auvergne
fea59adbbe PropertyObject: Unit test for declarations.
This shows a failure for the declaration of std::string type PropertyObjects.
2018-12-04 12:38:14 +01:00
Richard Harrison
dae0d0ff8b Logging changes.
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
2018-11-29 19:29:14 +01:00
Richard Harrison
86d739cc85 DDS TextureCache: remove unused code to support non-persistent images
- this didn't compile for Stuart on OSG3.2 and it's not used.
2018-11-25 23:48:58 +01:00
Richard Harrison
9d99f4ce30 Added DDS Texture Cache.
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.
2018-11-24 20:02:33 +01:00
Stuart Buchanan
460a666234 STG-defined buildings using Random Building shader
Support BUILDING_LIST STG verb which references a file
containing the cartesian coordinates of individual buildings,
to be generated using the random-building shader approach.

BUILDING_LIST buildings.txt OSM_Building -2.72943543 56.00080606 36.1 0

buildings.txt:

0 0 0 0 0
0 100 0 0 0
0 200 0 0 0
0 300 0 0 1
0 400 0 0 1
0 500 0 0 2
100 0 0 0 2
200 0 0 0 2
300 0 0 0 2
400 0 0 15 2
2018-11-18 21:08:06 +00:00
Stuart Buchanan
ba9342cd4b Fix effects for MP models - ticket 2076
https://sourceforge.net/p/flightgear/codetickets/2076/

Effects were being instantiated by the loader for
all models, rather than just simple .ac/.obj models.
2018-11-06 17:01:01 +00:00
gallaert
c37eae3b56 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-11-04 15:52:05 +00:00
Richard Harrison
61cc8d6c50 Fix exception when number of primitive sets not what assumed.
This was something that happened when random vegetation was off, but tree shadows was on.

Adding random vegetation would then reliably cause an exception.
2018-10-30 20:13:32 +01:00
Richard Harrison
758ab5e581 LOD ranges
The scenery ranges for bare and rough are now deltas, to avoid overlapping values by user error.
2018-10-30 20:12:12 +01:00
James Turner
f05ff37560 Fix for assert with empty systems
Empty subsystem groups didn’t set their init state correctly, leading
to an assert on post-init. Fix this and add a test for it.

https://sourceforge.net/p/flightgear/codetickets/2043/
2018-10-23 15:29:56 +01:00
Stuart Buchanan
14354090f9 Don't check for cloud movement every frame
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.
2018-10-18 22:28:39 +01:00
James Turner
0185884ca8 Catalogs: allow migration to alternate IDs 2018-10-16 09:56:56 +01:00
gallaert
5665403d66 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-10-15 22:29:01 +01:00
James Turner
46b271d75c Packages: improve localised string support 2018-10-12 10:49:14 +01:00
James Turner
854b958797 Packages: check for existing update when scheduling
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.
2018-10-05 10:40:35 +01:00
James Turner
ff52b55a25 Mac: Set CMake OS-X deployment target correctly
Also raises the OS-X min version to 10.9 for libc++ compat
2018-10-01 22:28:56 +01:00
gallaert
e755735ac2 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-09-30 16:25:33 +01:00
Scott Giese
69e20a3931 Bug Fix #1922 Wrong retun type 2018-09-29 18:41:00 -05:00
James Turner
05da3db2ed Fix a debug message left in the terrasync code 2018-09-24 14:54:20 +01:00
Torsten Dreyer
6d89cc6c1d new version: 2018.4.0 2018-09-21 17:18:46 +02:00
Torsten Dreyer
0494af48a3 new version: 2018.3.1 2018-09-21 17:18:46 +02:00
James Turner
f4cad42958 Lat-lon parsing: catch exceptions from std::stod
The standard library throws exceptions in some cases, catch those
and return false. Extend the test coverage for some of the problematic
cases.
2018-09-13 23:47:24 +02:00
James Turner
32189b7239 Event-manager: add dump() method for debugging 2018-09-01 18:08:32 +01:00
James Turner
c192071f03 TerraSync: improve copy-installed-files logic 2018-08-31 16:05:48 +01:00
James Turner
8c9fda9137 Fix Utf-8 literal on MSVC 2018-08-31 16:05:48 +01:00
gallaert
35d1bb1149 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-08-29 21:01:36 +01:00
James Turner
8dd0833993 Fix setting OPENAL_DIR on Windows
We need to set this in all cases, since AeonWave is requested by
default, but may not be available.
2018-08-23 19:11:50 +01:00
James Turner
306eaeaba9 Fix subsystem-remove bug 2018-08-19 12:32:30 +01:00
James Turner
7853a5329d Extend propsfwd.hxx so it can be used in more places 2018-08-11 18:41:29 +02:00
James Turner
1fa77078fc Subsystems: bind/init/unbind on add/remove
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.
2018-08-11 18:41:04 +02:00
James Turner
8e8ce04e18 Subsystems: default name to group name when adding 2018-08-11 18:16:33 +02:00
James Turner
264779e1d3 Packages: fix download progress
(Broke it when improving zip/tar support)
2018-08-08 11:12:53 +02:00
James Turner
6f505f3a76 formatGeodAsString: add ICAO route format 2018-07-30 10:08:34 +02:00
Edward d'Auvergne
3817bdd602 NotifyLogger: Shifted the class from flightgear to simgear.
This is to allow the code to be reused in the flightgear test suite.
2018-07-26 20:48:12 +02:00
Edward d'Auvergne
2c9420d9bc Logstream: Added a logging class for outputting messages in headless mode. 2018-07-26 20:48:12 +02:00
James Turner
2e3cace7f9 Canvas::path: early return for descendant changes
The ‘rect’ attributes of Path were before the early-return when the
change is for a descendant node.
2018-07-24 13:13:08 +01:00
James Turner
9553a604ac Cache parsed lat/lon values in Canvas::Map
This avoids re-parsing each lat/lon in the map from a string, each
time the project changes
2018-07-24 13:13:08 +01:00
James Turner
f1e1bf11b6 Cache x/y nodes in Canvas::Map::GeoPair
This removes a bad CPU hit when Canvas map is used continuously,
since this is two named property lookups per map coord per frame
2018-07-24 13:13:08 +01:00
James Turner
f77724a646 Fix terrasync hash persistence 2018-07-19 07:40:23 +01:00
gallaert
5921fd19fb Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-07-18 20:48:01 +01:00
James Turner
a0c4913f84 Fix .dirindex preservation on Windows
Ensure we don't treat the special files as regular children
when updating.
2018-07-18 16:30:44 +01:00
James Turner
3dfce43de2 Fixes to HTTP repo tests on Windows.
Large alloca fails, and SGFIle dtor doesn't close the handle,
which breaks _wunlink on Windows :(
2018-07-18 07:20:18 +01:00
Erik Hofman
0e9e5f77cc It turns out the 16-bit version was not introduced until gcc-4.8 2018-07-05 10:29:03 +02:00
James Turner
f2f465960b Tar code: handle symlink and PAX extensions
This now accepts the GitLab .tgz archives without problems, eg
the Tu-144.
2018-07-04 23:47:14 +01:00
James Turner
05d8ab3000 Fix Windows build
Clean out legacy crap from stdint.h while we're here
2018-07-04 14:08:57 +01:00
James Turner
126f69434b Refactor untar/unzip code
This is to enable reuse in more places, especially scenery extraction and TerraSync
2018-07-04 10:32:09 +01:00
Erik Hofman
3e081ae869 Use CPU optimized versions of endian swap functions when available 2018-07-04 09:35:45 +02:00
Erik Hofman
4e8df9dcc8 Remove a bunch og gcc-8 warnings 2018-07-04 09:33:32 +02:00
James Turner
d7a413d5e7 Lat-lon parsing: allow lon,lat order, and detect order
Flightplan/route-manager defaults to lon,lat order. Allow the parser
to detect the correct order when NSEW suffixes are provided and 
consistent.
2018-06-29 13:28:02 +01:00
James Turner
609ac93c10 Lat-lon parsing: accept lower case NSEW, fix precision
Thanks to Wkitty for catching both problems.
2018-06-28 22:43:30 +01:00
James Turner
b1d6a41c65 Fix a bug in lat-lon parsing - accept ‘*’
Previously, trailing * symbols confused the parser.
2018-06-27 14:29:45 +01:00
James Turner
a4e2fdfad2 Merge /u/scttgs0/simgear/ branch to-be-merged into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/46/
2018-06-24 20:07:40 +00:00
James Turner
22c2971c3c Lat-lon formatting: support nice degree symbols
Allow Latin-1 (for PUI fnt) and UTF-8 (for Qt, osgText and everybody
else) degree symbols as well as the use of *
2018-06-24 10:30:50 +01:00
Scott Giese
123c597e01 msvc has no support plans beyond OpenMP 2.0
We must use a signed integral data type
2018-06-23 14:44:48 -05:00
Scott Giese
05e3c29ee4 Support Visual Studio 2017 2018-06-22 22:19:49 -05:00
James Turner
9b1444deb5 Strutils to format and parse SGGeod/lat/lon
Format portion is taken from code in fg_props, parsing code is my
own horrible concoction.
2018-06-20 22:00:58 +01:00
James Turner
99d30d5bb7 CMake tweak: include headers in targets
This improves navigation in XCode (any maybe some other tools)
2018-06-20 22:00:03 +01:00
James Turner
100bb3a571 Fix flags passed to SHGetKnownFolderPath
Custom folder locations were not being picked up.
Fixes: https://sourceforge.net/p/flightgear/codetickets/2019/
2018-06-15 11:08:53 +01:00
Stuart Buchanan
7fb89e4d45 Multiple LoD levels of MP Aircraft
Support loading multiple models into PagedLOD.
2018-06-05 21:56:36 +01:00
Stuart Buchanan
1d7c3984ca Fix minor warning for no return value. 2018-06-05 21:55:23 +01:00
Erik Hofman
03156a6d94 Better AeoNWave detection 2018-06-05 09:39:51 +02:00
Erik Hofman
08258ee4b3 Detect AeonWave and if it is installed use it, otherwise fall back to OpenAL. Also let get_available_devices() use C++ strings instead of const char* 2018-06-02 14:06:15 +02:00
Erik Hofman
3dceaf7a0b Update to the latest version 2018-06-02 10:53:03 +02:00
Erik Hofman
856473ca43 Add missing headers 2018-05-29 09:44:37 +02:00
James Turner
7dfe705717 Resource manager clean-up code 2018-05-28 21:57:31 +02:00
ThomasS
dc2f142480 Feature for requesting canvas images per HTTP as described in http://wiki.flightgear.org/Read_canvas_image_by_HTTP 2018-05-28 14:23:12 +01:00
gallaert
fce06105f9 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-05-26 19:05:11 +01:00
Torsten Dreyer
94a1156a6b new version: 2018.3.0 2018-05-19 21:02:35 +02:00
Torsten Dreyer
5ed4fbd4a3 new version: 2018.2.1 2018-05-19 21:02:35 +02:00
xDraconian
d92a289c25 Bug fix: svg dirty flag 2018-05-17 09:11:07 +01:00
Edward d'Auvergne
2ba5676eb0 SGTime: Stripped trailing '\n' from some debugging messages. 2018-05-14 21:36:54 +02:00
Edward d'Auvergne
66cfa800be SGEventMgr: Reset the shutdown flag on init as a reset does not call the ctor.
This fixes the reset process that was broken by
dfed2184f1.
2018-05-14 14:05:04 +02:00
James Turner
9755110ec7 Packages: Remove deprecation warnings for now
Probably a bit over-zealous for these.
2018-05-09 10:15:07 +01:00
James Turner
f5ff969cd4 Warning improvements when requesting bad URLs
Found while debugging some issues with add-default-catalog flow in
the launcher.
2018-05-08 06:50:15 +01:00
Edward d'Auvergne
a232565b3e SGSubsystemMgr: Bug fix for the global_registrations vector.
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.
2018-05-04 09:09:15 +02:00
Edward d'Auvergne
fd4ca1c811 Revert "Speculative fix for global symbol issues for Edward"
This reverts commit b6f5b40557.

The changes did not solve the static init vector allocation issue.
2018-05-04 09:02:08 +02:00
James Turner
b6f5b40557 Speculative fix for global symbol issues for Edward
Let’s see if an explicit static at file scope is better or different
to an anonymous namespace scope
2018-05-03 14:29:07 +01:00
James Turner
5710d33dbf Subsystem commands in the manager
Migrate and update these commands from FlightGear’s subsystem factory.
Currently disabled until subsystem-factory is removed, to avoid
duplicate registration.
2018-05-02 23:27:34 +01:00
James Turner
831369f653 Packages: add archive-path XML support
Allow the in-archive file path to differ from the after-install path.
Requested to allow easier operation with GitHub/Labs zip generation.
2018-04-27 15:25:13 +01:00
James Turner
6db59c64aa Subsystems: change naming scheme, add accessors
Add some hopefully clearer accessors for the subsystem naming, and some
comments documenting what is stored where.
2018-04-27 13:59:11 +01:00
James Turner
888d7fb262 Packages: archive-type support in catalogs
Allow URLs which don’t encode the file extension to work
2018-04-27 12:07:10 +01:00
James Turner
8b4ace6fb8 Subsystems: stub code for smart add+remove
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.
2018-04-25 22:20:12 +01:00
James Turner
368120c479 Track a root property on subsystem-manager 2018-04-25 21:34:17 +01:00
gallaert
b01718aae7 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-04-25 21:08:46 +01:00
James Turner
48b228f68f Packages: additional test for updating invalid
This is part of trying to trace a crash reported on the devel list,
unfortunately the test passes but it’s sill good to have it
2018-04-25 17:04:07 +01:00
James Turner
bf21c0e099 MSVC build fixes, ooops 2018-04-25 11:41:40 +01:00
James Turner
d85d85e7dc Subsystem improvements for testing
- 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
2018-04-25 08:58:58 +01:00
Florent Rougon
99c1dd8124 Add compiler options for GCC and Clang when CMAKE_BUILD_TYPE is Debug
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/
2018-04-18 08:25:10 +02:00
gallaert
9ce026e22e Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-04-12 18:56:37 +01:00
James Turner
2797970837 Catalogs: better invalid data handling 2018-04-08 23:57:24 +01:00
gallaert
4796c8b7f9 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-04-07 20:15:42 +01:00
James Turner
cf03307b70 More verbose error logging from Repository code 2018-03-30 17:24:58 +01:00
Edward d'Auvergne
dfed2184f1 SGEventMgr: Protection from timer insertion after shutdown.
This actually happens, Nasal timers are added after the event manager shutdown()
subsystem API call.
2018-03-25 22:45:04 +02:00
gallaert
2ee5127748 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-03-25 18:27:57 +01:00
Edward d'Auvergne
340a469153 LogStream: Added a testing mode to the simgear logstreams.
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().
2018-03-22 14:45:32 +00:00
gallaert
934e769513 Merge branch 'next' of https://git.code.sf.net/p/flightgear/simgear into next 2018-03-04 19:47:48 +00:00
Thomas Geymayer
62ae6ca35e Mostly canvas doxygen improvements and C++11 refactoring. 2018-03-02 09:07:01 +01:00
Thomas Geymayer
711a4fe0c8 canvas::Map: Preserve default values without new values
Ensure default values are used (instead of 0) if no values are
specified.
2018-03-01 09:10:24 +01:00
James Turner
cba07157d5 Packages: better version handling & migration
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.
2018-02-28 17:26:15 +00:00
Thomas Geymayer
a653d67aae canvas: Event improvements and new events (dragstart, dragend) 2018-02-25 14:50:49 +01:00
gallaert
249e6130fd Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2018-02-22 22:33:47 +00:00
Erik Hofman
6a142bc264 Merge branch 'release/2018.1' into next 2018-02-20 10:11:38 +01:00
Erik Hofman
8bcdd89796 Properly initialize _bad_doppler 2018-02-20 10:11:04 +01:00
Torsten Dreyer
489573329e new version: 2018.2.0 2018-02-18 21:22:54 +01:00
Torsten Dreyer
843df4b334 new version: 2018.1.1 2018-02-18 21:22:54 +01:00
Erik Hofman
ef1821c025 Switch to C++11 2018-02-16 16:09:26 +01:00
James Turner
ed5372f439 Add new PROTECTED property attribute 2018-02-04 17:10:41 +00:00
James Turner
bc63381fb0 Packages: tweaks to thumbnail cache
Don’t discard the existing data when expiring from the cache, in case
the refresh request fails.
2018-01-31 15:00:58 +00:00
James Turner
c59f2a0749 Fix Windows _wutime compilation 2018-01-31 13:10:34 +00:00
James Turner
5c30ca5dc6 Add SGPath::touch() helper 2018-01-31 11:04:10 +00:00
Thomas Geymayer
37bc43c7aa canvas::Path: support for stroke-opacity and fill-opacity 2018-01-29 09:07:04 +01:00
Thomas Geymayer
4edd3f45b7 canvas: Refactor and protect against expired pointers 2018-01-28 15:57:14 +01:00
Thomas Geymayer
087ea4c5f3 canvas: Refactor with C++11 2018-01-28 00:49:05 +01:00
Florent Rougon
40534d6316 Remove overzealous, invasive behavior from SGBinding's destructor
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
2018-01-27 11:03:06 +01:00
James Turner
8621925e75 Floating-point comparison helpers for SGMath<T>
Implemented using numeric_limits::epsilon and std::abs, fingers
crossed this is sufficiently portable!
2018-01-26 11:29:18 +00:00
Thomas Geymayer
5cb2360985 cppbind: Use separet Context::to_nasal_vec instead of overload 2018-01-23 16:15:56 +01:00
Thomas Geymayer
b831d2b64a cppbind: Fix for old g++ 2018-01-23 14:02:18 +01:00
Thomas Geymayer
e81597a176 cppbind: Opimize convert fixed size arrays and more type_traits 2018-01-23 09:30:00 +01:00
James Turner
7df4f32de6 Merge /u/janodesbois/simgear-jano/ branch mp-merge into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/42/
2018-01-22 09:48:01 +00:00
gallaert
8d265a8123 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2018-01-21 20:06:46 +00:00
Thomas Geymayer
db3725880e cppbind: simplify with 'auto' 2018-01-21 14:39:24 +01:00
Thomas Geymayer
af5833cbc5 cppbind: Refactor to use C++11+ type_traits 2018-01-21 13:21:55 +01:00
James Turner
9078a085c3 Kill exception if removeDelegate fails
This simplifies logic when changing the package::Root
2018-01-20 16:19:13 +00:00
jean pellotier
396a7d7f09 a system clock from simgear, using std::chrono libs
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.
2018-01-20 09:15:56 +01:00
Thomas Geymayer
8a128a57cd cppbind: forward declarations 2018-01-19 10:34:37 +01:00
Thomas Geymayer
3dca9b8a68 cppbind: Make Mac and Windows happy and add forward declaration 2018-01-19 10:24:33 +01:00
Thomas Geymayer
5f8f5a1c33 cppbind: More refactoring and finally getting rid of boost.preprocessor 2018-01-19 09:12:11 +01:00
Thomas Geymayer
5a72a7d9f4 canvas: Refactor Path::addSegment with std::initializer_list 2018-01-16 09:01:55 +01:00
James Turner
51a91bfa8a Ignore CmakeList.txt.user files 2018-01-12 22:19:54 +00:00
Thomas Geymayer
4cedd0a346 cppbind: refactor Ghost::method to use variadic templates 2018-01-12 08:32:57 +01:00
Thomas Geymayer
b989f4085d Various doxygen improvements/fixes. 2018-01-12 08:32:04 +01:00
Thomas Geymayer
19cc797c41 cppbind: fix exporting integer_sequence and small codingstyle fixes 2018-01-12 07:57:17 +01:00
Thomas Geymayer
99ee3d9dec cppbind: nasal::Context refactoring and doxygen improvements. 2018-01-09 22:50:29 +01:00
Florent Rougon
455753c774 Simplify code in NetChannelPoller::removeChannel()
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/
2018-01-08 10:26:18 +01:00
James Turner
da099d4312 Correct use of remove_if in the test-server
Should fix erratic crashes of some tests.
2018-01-07 16:10:50 +00:00
xDraconian
a88b9181b6 Enable the test 'test_precipitation' 2018-01-04 08:18:43 +01:00
xDraconian
7f7c632914 Simgear::test_precipitation test coverage
Lines:     0.0% >> 92.3%
Functions: 0.0% >> 97.1%

Memory leaks resolved - reclaiming 169kb in 126 blocks
No memory leaks remain
2018-01-03 12:40:49 +00:00
Alessandro Menti
e7356223bb CMakeLists.txt: explicitly enable the CMP0067 (C/C++ standard flags) policy
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).
2018-01-03 11:54:04 +01:00
Florent Rougon
7547ad0391 Improve formatting of the HAVE_WORKING_STD_REGEX test
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".
2018-01-03 00:34:52 +01:00
Thomas Geymayer
ca30d6bb3d Add missing simgear_config.h include
Required for HAVE_STD_INDEX_SEQUENCE to be properly set.
2018-01-02 11:37:46 +01:00
Thomas Geymayer
ebd2cdb7a7 SGPickAnimation: fix member initialization order 2018-01-02 09:13:14 +01:00
Thomas Geymayer
52b8f60953 Add std::index_sequence for C++11
Will be required for nasal::Ghost
2018-01-02 08:00:49 +01:00
Florent Rougon
ab1e2d49ab Add a CMake check for a working <regex> implementation
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/
2017-12-29 13:46:42 +01:00
xDraconian
401bd1c643 Simgear::test_bucket code coverage
Lines:     82.1% >>  98.7%
Functions: 83.0% >> 100.0%

No memory leaks
2017-12-23 08:52:23 +00:00
gallaert
e6a540660d Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2017-12-18 19:14:12 +00:00
xDraconian
53e6bec425 Tests: resolve several memory leaks 2017-12-17 10:06:20 +01:00
James Turner
f6ded69fa3 Untar failure path fixes
By xDraconian, ensure we call inflateEnd in failure cases, otherwise
the inflate context is leaked.
2017-12-11 18:14:40 +00:00
Thomas Geymayer
68053d64b5 function_list<>: Simplify with C++11 2017-12-04 08:47:51 +01:00
Richard Harrison
1f12966628 Add condition to knob animation.
This will prevent both input from being received and the position being updated by property change.
2017-12-04 07:53:39 +01:00
Richard Harrison
8d3723c91f Prevent nullptr exception in treenodes.
Happened to me once or twice mainly during reposition probably as scenery changed whilst still loading.
2017-12-04 07:33:45 +01:00
Richard Harrison
7dcc359110 add condition to pick animations 2017-12-04 07:31:59 +01:00
Richard Harrison
854881bba2 Prevent nullptr exception. Had this happen once. 2017-12-04 07:30:48 +01:00
Alessandro Menti
ddb7958f40 Remove old .spec files
Remove old SuSE/Red Hat packaging files (in line with what was done
in commit ef66ba in FlightGear).
2017-12-02 17:47:05 +01:00
Alessandro Menti
fe0d3fd448 Remove the dependency on the UTF-8 external library
Remove the dependency on the UTF-8 external library by writing the
UTF-8/code point conversion routines in KeyboardEvent.cxx.
2017-12-02 16:32:27 +01:00
Thomas Geymayer
15d5c878f3 canvas::NasalWidget: don't call unsafe method in destructor
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.
2017-12-01 08:14:44 +01:00
Thomas Geymayer
4f63c3f8a8 nasal::Object: Simplify with C++11
C++11 variadic templates finally allow us to get rid of the
ugly boost preprocessor workaround.
2017-12-01 07:32:49 +01:00
James Turner
b766ce76ff Package thumbnail caching tweaks
Resolves some issue with expired thumbnails not being reloaded
correctly.
2017-11-27 23:37:56 +00:00
ThorstenB
0b4b09958f Merge /u/thbr/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/41/
2017-11-24 21:58:52 +00:00
Florent Rougon
e12fc5a89d Use common definition of simgear::enumValue() from <simgear/sg_inlines.h>
This avoids code duplication.
2017-11-19 08:15:44 +01:00
Florent Rougon
bd3c351f1f Add function template simgear::enumValue() to simgear/sg_inlines.h
This function template is useful to get the value of a member of a
scoped enumeration, without having to hardcode its type while casting
it.
2017-11-19 00:45:47 +01:00
Florent Rougon
6064be33e5 SGPath: add comparison operators (<, >, <=, >=) and an std::hash specialization
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.
2017-11-19 00:45:47 +01:00
Florent Rougon
1540d6f472 SGPath: mark the str() and utf8Str() methods as 'noexcept'
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
2017-11-18 16:04:32 +01:00
Florent Rougon
1310092c0c SGPath: enable move operations
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
}
2017-11-18 14:54:33 +01:00
gallaert
12bed8e8ad Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2017-11-17 18:46:21 +00:00
ThorstenB
e485fac8ed Provide polar earth radius as a simgear constant. 2017-11-16 21:38:50 +01:00
Florent Rougon
55d75f18de Add missing include <algorithm> for std::max() and std::min()
This include was missing in several files from the simgear/hla
directory.
2017-11-16 16:00:14 +01:00
Florent Rougon
e8648a3f71 Add missing include <algorithm> for std::max() 2017-11-16 00:42:22 +01:00
Florent Rougon
0c7cabe46f SGSharedPtr: optimized version of the free function swap()
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()!
2017-11-14 01:31:03 +01:00
Florent Rougon
a9ec3be2fd SGSharedPtr: the move constructor and move assignment operator are now 'noexcept'
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.
2017-11-13 23:43:43 +01:00
Florent Rougon
abaaee1af2 Add simgear::noexceptSwap() to simgear/sg_inlines.h
This is a function template that is guaranteed to be 'noexcept' as long
as compilation succeeds. Idea and implementation from
<https://akrzemi1.wordpress.com/2011/06/10/using-noexcept/>.
2017-11-13 11:59:11 +01:00
Florent Rougon
6283a515b9 Fix missing headers in simgear/io/DNSClient.cxx and simgear/props/props_test.cxx
<algorithm> is needed for std::sort() and std::find().
2017-11-13 10:04:34 +01:00
Thomas Geymayer
ce7d463710 Fix wrong argument
One more catch by Florent Rougon.
2017-11-13 08:22:14 +01:00
Florent Rougon
bc3404fcbe SGSharedPtr: more efficient copy and move assignment operators
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
2017-11-13 07:34:48 +01:00
Thomas Geymayer
bd87d3963a Fix leak in NasalObjectHolder
Thanks to Florent Rougon for spotting it.
2017-11-12 22:41:14 +01:00
Richard Harrison
fed449a801 Fix error message in axis object animation 2017-11-12 17:07:29 +01:00
Florent Rougon
19dd92d3e0 Remove or replace obsolete uses of throw()
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_spec
  https://akrzemi1.wordpress.com/2013/08/20/noexcept-destructors/
2017-11-12 09:56:26 +01:00
Florent Rougon
f22b9ba9f1 SGSharedPtr: add unit tests
Add unit tests for move ctor and move assignment operator, as well for a
few other SGSharedPtr methods.
2017-11-11 17:55:54 +01:00
Florent Rougon
fedafb9352 SGSharedPtr: add move constructor and move assignment operator 2017-11-11 16:18:36 +01:00
Florent Rougon
18f0484249 Convert structure/shared_ptr_test.cpp to use the SG test macros (no more boost) 2017-11-11 01:29:49 +01:00
James Turner
10956056b3 Own code for UTF-32 <-> UTF-8 conversion
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.
2017-11-01 17:04:56 +00:00
Erik Hofman
e482f04123 int16_t needs cstdint 2017-10-31 11:22:39 +01:00
Erik Hofman
db89f0d4d1 Oops, use the proper project name 2017-10-31 10:49:04 +01:00
Erik Hofman
2ac97a9f1f std::wstring_convert requires locale 2017-10-31 10:47:12 +01:00
Erik Hofman
c03359a189 Update to the (now GPL) AeonWave version 3.0+ 2017-10-31 10:42:44 +01:00
Erik Hofman
84b636debc Add a frequency filter and a bitcrusher filetr 2017-10-31 10:42:16 +01:00
James Turner
2642299d77 We require C++11 now, simplify this code.
This ensures wstring to std::string conversion is always available,
needed for some HID work I’m doing on a branch,.
2017-10-29 13:20:39 +00:00
Richard Harrison
2a60e5e338 Added touch animation.
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>
2017-10-29 01:04:36 +02:00
Florent Rougon
880c063d04 Remove useless readdir() calls in Dir::isEmpty()
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.
2017-10-27 20:49:17 +02:00
Florent Rougon
7a374c43dc Fix CMake test for std::isnan()
It used the wrong header; std::isnan() is defined in <cmath>.
2017-10-23 19:29:07 +02:00
Richard Harrison
7be1fcc32e Add method to copy entire properry subtree 2017-10-15 16:54:36 +02:00
Stuart Buchanan
b57dca66be Handle case where no tranform matrix exists. 2017-10-13 17:35:21 +01:00
Florent Rougon
d455f5f445 props_io.cxx: use SG_ORIGIN when throwing exceptions
This will provide more accurate info than the fixed string "SimGear
Property Reader".
2017-10-10 20:15:54 +02:00
gallaert
5305095832 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2017-10-09 22:04:36 +01:00
Florent Rougon
2200fad30e Rename the ResourceProxy class to EmbeddedResourceProxy
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.
2017-10-07 16:36:49 +02:00
gallaert
e4b9cbcb80 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2017-10-01 21:25:16 +01:00
Florent Rougon
e5e112c3c2 Add a ResourceProxy class
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)
2017-10-01 07:54:17 +02:00
James Turner
dd3cdf63e6 Terrasync: Fix exception deleting orphaned directories. 2017-09-29 12:47:42 +01:00
Stuart Buchanan
a800189c25 Add support for Slippy Map Canvas layers.
- Add so-called Web Mercator projection and ability to choose
  projection for a Canvas Map.
- Add supporting functions for Slippy Maps (i.e. OSM)
2017-09-28 15:36:48 +01:00
James Turner
b342245619 Fix lib64 mode on Ubuntu 17.04 / CMake 3.7 2017-09-28 15:11:09 +01:00
James Turner
6cd5ac2d0d Move readTime (parse_time) from options.cxx 2017-09-27 15:06:37 +01:00
James Turner
872a48dacb Extend the state-machine parsing test slightly 2017-09-27 14:33:57 +01:00
James Turner
721aa544c9 Use C++11 in the state-machine code 2017-09-26 16:39:04 +02:00
Richard Harrison
7bfbda7188 Fix for AMD / Radeon rendering of lights as point sprites.
Tested against R9-290 and GTX 550 Ti (thanks Nikolai V. Chr.)
2017-09-24 22:10:44 +02:00
James Turner
602244979b Tar extractor can filter file paths. 2017-09-21 17:47:28 +01:00
Torsten Dreyer
8e29cae309 new version: 2017.4.0 2017-09-17 12:14:00 +02:00
Torsten Dreyer
2a73e6c0d5 new version: 2017.3.1 2017-09-17 12:14:00 +02:00
gallaert
d4198659b7 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2017-08-31 22:38:56 +01:00
Richard Harrison
16b5dd5e78 Remove message "Could not find at least one of the following objects for axis animation" when not relevant.
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.
2017-08-31 00:30:18 +02:00
gallaert
ef1edc7ee8 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2017-08-25 20:47:36 +01:00
gallaert
3ccfb74028 Fix candidate for 'lib' vs 'lib64'. 2017-08-21 23:07:05 +01:00
James Turner
1aba20d642 Merge /u/gallaert/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/38/
2017-08-18 22:25:48 +00:00
Florent Rougon
27786d709d EmbeddedResourceManager: better API with respect to rehashing
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.
2017-08-16 23:49:19 +02:00
gallaert
e0e6a29150 CMake fails to detect OpenRTI include files. 2017-08-16 21:15:20 +01:00
Torsten Dreyer
dfd6076e19 Fix a warning 2017-08-12 22:34:52 +02:00
Alessandro Menti
e589ef8627 Remove the .spec file
Remove the .spec file as it is unused and we leave the packaging to
upstream (as it has been done with FlightGear).
2017-08-06 15:08:11 +02:00
Stuart Buchanan
e8c1baa396 Clear Uniform cache on reset. 2017-08-01 21:23:35 +01:00
James Turner
69ba2617d2 Fix thumbnail loading on Windows 2017-07-28 12:05:35 +01:00
James Turner
34c215ad83 Persistent thumbnail cache for aircraft packages
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.
2017-07-28 11:38:59 +01:00
James Turner
2a3bb62001 Add efficient hasTag check to Package.
Avoids copying the tags set each time to check for presence / absence
of a particular tag.
2017-07-27 23:26:06 +01:00
James Turner
fe46ae09ef Fix MSVC build.
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.
2017-07-19 13:00:33 +01:00
Ganael Laplanche
46f67fce7a Remove dependency to TR1.
TR1 will be deprecated in Boost 1.65, see:
https://github.com/boostorg/admin/issues/123
2017-07-17 14:49:51 +02:00
Torsten Dreyer
629e68428f Fix SimGear test target for change in commandmgr api 2017-07-07 08:56:13 +02:00
Richard Harrison
100439aadd Model relative property tree root binding.
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.
2017-07-05 12:05:01 +02:00
Stuart Buchanan
f6a348ba94 Enable display lists for random trees. 2017-07-04 21:45:56 +01:00
James Turner
a54b3ffcee Extend Package delegate callbacks.
This makes it easier to report the status in the launcher, at least.
2017-06-28 22:27:40 +01:00
James Turner
47842c9ea7 Work-around older Curl on macOS 10.8n and earlier 2017-06-28 10:18:35 +01:00
Richard Harrison
834e25521b Axis based animation use ObjectName-axis as default if nothing specified. 2017-06-25 09:25:06 +02:00
James Turner
f78597f010 Merge /u/reavertm/simgear/ branch next into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/35/
2017-06-21 10:52:24 +00:00
James Turner
c06e433e74 Templated lookup of subsystem-group members. 2017-06-15 18:30:27 +01:00
Maciej Mrozowski
9971d517fd Link shared SimGearScene with libgdal when enabled 2017-06-15 04:58:03 +02:00
Florent Rougon
f8548029a2 EmbeddedResourceManager.hxx: refine the previous MSVC workaround
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).
2017-06-11 17:30:58 +02:00
Florent Rougon
3e337e3e97 Fix build errors related to template instantiations on Windows
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.
2017-06-11 10:29:43 +02:00
Florent Rougon
e59f8eda74 Embedded resources system: SimGear part
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).
2017-06-10 23:38:59 +02:00
Florent Rougon
31e70b205c CharArrayStream_test: fix failing test (logic error in the test code) 2017-06-10 20:59:15 +02:00
Florent Rougon
5d02f1db5f CharArrayStream_test.cxx: attempt to fix build errors on Windows 2017-06-10 16:58:16 +02:00
Florent Rougon
b01bd93a20 Add CharArrayStreambuf and related IOStreams classes for working with char arrays
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.
2017-06-10 09:45:15 +02:00
Alessandro Menti
05bbba5074 Remove the last traces of enhanced lighting support
Remove some traces of the enhanced lighting support which were left
there from a refactoring several years ago.

See discussion at <https://sourceforge.net/p/flightgear/mailman/message/35875305/>
2017-06-04 16:51:27 +02:00
Automatic Release Builder
679d4e1dcd new version: 2017.3.0 2017-05-18 15:15:48 +02:00
Automatic Release Builder
aaa6231f89 new version: 2017.2.1 2017-05-18 15:15:48 +02:00
Erik Hofman
446c8cd70c Fix a bug when using properties instead of a fixed position 2017-05-17 08:28:01 +02:00
Richard Harrison
11ff1d256c Fix mesh visibility on pick animations.
(caused by incorrectly overloaded methods)
2017-05-11 19:17:24 +02:00
Richard Harrison
4acd047982 Fix animation axis text for new calling conventions.
NOTE: the transient model data as initialized contains nullptrs for mostly everything - except the required data for this test.
2017-05-11 13:02:40 +02:00
Erik Hofman
ee4b6621e7 Fit the property definied positions to the axis definition by negating them 2017-05-11 10:29:08 +02:00
Richard Harrison
77517b15fd Allow animations to take an object as the centre and axis.
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>
2017-05-11 06:32:27 +02:00
Florent Rougon
19a86a6f0d Change license from GPL2+ to LGPL2.0+ for the SimGear files I wrote
Change as per the FlightGear Policy Document:

  http://www.flightgear.org/flightgear-policy-document/
2017-05-10 17:03:50 +02:00
Stuart Buchanan
a7dee1164d materials.xml support for osm2city Buildings etc. 2017-05-09 14:30:57 +01:00
Erik Hofman
7512bc0fb2 Make position properties work for relative positions too 2017-05-09 10:57:31 +02:00
Florent Rougon
d6b57d0937 Fix MSVC warning: redefinition of default template parameter
The default values for template parameters don't have to be repeated in
the .cxx file, apparently.
2017-05-03 19:11:30 +02:00
Florent Rougon
1e99c4b2ec Add function template simgear::strutils::readNonNegativeInt()
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.
2017-05-03 16:33:53 +02:00
Torsten Dreyer
04ca3ad8f4 Fix bug "dns timeout, no terrasync servers found"
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)
2017-05-03 10:41:11 +02:00
Florent Rougon
2b8915e35f zlibstream.cxx: explicitly mark as virtual the inherited virtual methods
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.
2017-04-30 16:19:50 +02:00
Florent Rougon
2a0801da6b zlibstream*: use C++11 scoped enumerations instead of C-style enums
These enumerations are those declared with 'enum class' instead of just
'enum' (cf. §7.2 of the C++11 standard).

+ add missing include (<zlib.h>)
2017-04-30 15:45:52 +02:00
Florent Rougon
2935d78490 Fix build failure in strutils_test.cxx
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.
2017-04-28 23:16:15 +02:00
Florent Rougon
2404924bcb Add function strutils::escape()
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)
2017-04-28 22:24:21 +02:00
Florent Rougon
e4c4db5cf9 strutils::unescape(): minor change
Use static_cast<char> for clarity when adding an int to an std::string
with std::string::operator+=().
2017-04-28 22:14:52 +02:00
Florent Rougon
e1c655c570 strutils::unescape(): fix handling of hexadecimal escape sequences
Hexadecimal escape sequences have no length limit and terminate at the
first character that is not a valid hexadecimal digit.
2017-04-28 22:14:52 +02:00
Florent Rougon
2788da9c51 strutils::unescape(): fix off-by-one error
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.
2017-04-28 22:14:35 +02:00
Erik Hofman
4860a70443 Fix (hopefully) sim4_t class initialization problems 2017-04-27 14:54:21 +02:00
Florent Rougon
22d1433ab0 argparse.cxx: allow arguments consisting of a single '-'
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!).
2017-04-21 22:30:45 +02:00
Florent Rougon
ef9eedf35a Fix misleading indentation in sg_path.cxx (g++ warning) 2017-04-15 09:33:27 +02:00
Florent Rougon
a962c90b30 Change SGPath::pathListSep into a const char array of size 2
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.
2017-04-15 09:29:59 +02:00
Florent Rougon
36275f5cce Add classes to ease writing command line parsers with GNU-style options handling
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/>.
2017-04-13 11:04:01 +02:00
James Turner
60d1c87cef New string helper function: property path matching
Match property path strings against template strings containing wild
card characters.
2017-04-13 07:29:05 +01:00
Stuart Buchanan
9223f30f08 Improve warning of object in wrong bucket.
Reduce level to DEV_WARN from DEV_ALERT as it's
largely benign.
2017-04-07 21:20:42 +01:00
James Turner
fe87e7f60d Define SG_DEPRECATED, remove unused DEPRECATED.
Use this to mark two Package APIs as deprecated.
2017-04-05 22:09:52 +09:00
James Turner
f3e83cf020 Package APIs to support multiple primary aircraft.
This (with some catalog and front-end changes) will allow packages to
supply multiple primary aircraft.
2017-04-04 07:04:43 +02:00
Richard Harrison
9eee41d74a Add logging support for hexdumps 2017-04-02 17:56:31 +02:00
Florent Rougon
991d76b69e Fix build failure due to missing <osg/Version> include
Failure observed on Debian jessie with openscenegraph 3.2.1-6.
2017-04-01 15:58:07 +02:00
Richard Harrison
6f0c7da6ad OSG 3.5.x support 2017-03-30 03:58:27 +02:00
James Turner
c170f576b6 Ensure <simgear_config.h> is always included.
This is going to become important soon - prep for enabling SIMGEAR_SHARED on Windows.
2017-03-28 09:36:53 +01:00
Erik Hofman
1446f559cc Add -fPIC to make FlightGear's shared library linking for fgtestlib happy 2017-03-26 10:17:10 +02:00
James Turner
4467e68db1 Make test macros public. 2017-03-24 16:52:02 +00:00
James Turner
cc1118b330 And make Windows happier again. 2017-03-19 12:16:10 +00:00
James Turner
a1126bd42c Make the LogStreamPrivate a d-ptr. 2017-03-19 10:28:57 +00:00
James Turner
370523d5bf Remove sgGMTime, no longer used.
(And the implementation was wrong on Windows)
2017-03-17 23:25:25 +00:00
James Turner
96b4d2c03d Make debugClassToString a public static.
This helps with implementing log-callbacks in other places, which
the unit-testing framework does.
2017-03-17 23:22:59 +00:00
James Turner
c4898502bf Use std::unique_ptr to avoid leaking logging
This makes calling shutdownLogging unnecessary on exit.
2017-03-17 23:22:59 +00:00
Florent Rougon
f7a511d1b3 Fix includes in zlibstream.hxx
Forward declarations of std::streambuf and std::istream are not enough,
since this file declares classes derived from them.
2017-03-14 20:24:32 +01:00
Florent Rougon
b66c51a6f8 Fix handling of SG_LOG()'s second argument
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.
2017-03-09 10:25:40 +01:00
Torsten Dreyer
a4cf38925b move TS dns lookup into the worker thread 2017-03-07 11:32:39 +01:00
Torsten Dreyer
41059a24a7 Fix indention, no functional change 2017-03-07 09:22:05 +01:00
Erik Hofman
ee4f5a5190 Disable SIMD for now as a test. 2017-02-28 12:42:48 +01:00
James Turner
141e98564c Generic string -> bool parser. 2017-02-27 23:11:05 +00:00
James Turner
72341a6de4 Adjust some messages to be developer-mode.
Still deciding how far to go with this, comments welcome.
2017-02-27 00:13:39 +00:00
Bertrand Coconnier
55ee59ac99 Flags ENABLE_GDAL and ENABLE_OPENMP are now carried over to FlightGear. 2017-02-26 16:39:48 +01:00
Peter Sadrozinski
61525c555e Disable GDAL, and compiling new terrain engine by default 2017-02-26 09:46:29 -05:00
Peter Sadrozinski
dad30b0cc2 alternative terrain engine - SGMesh utilizing pagedLOD 2017-02-25 19:17:55 -05:00
James Turner
9c9e4e86e7 Packages allows thumbnails per variant.
Change API for thumbnail access, so each variant can have a unique thumbnail alongside other data. Map existing catalog XML format to
this system.
2017-02-25 20:52:35 +00:00
James Turner
b88aa46e1c Merge /u/accek/simgear/ branch prop-strings into next
https://sourceforge.net/p/flightgear/simgear/merge-requests/32/
2017-02-25 16:36:49 +00:00
Bertrand Coconnier
10fa8a471a SGPath::set is called by SGPath::operator=(const char*p) so it needs to be unconditionnally compiled. 2017-02-25 16:02:36 +01:00
Szymon Acedański
4e875be0dd Added SGStringValueMethods property implementation
This is to be used in places where SGRawValueMethods returning .c_str()
from local strings were used, causing use-after-free later.
2017-02-25 15:02:37 +01:00
Bertrand Coconnier
23cc940743 gcc fails to catch std::ios_base::failure due to an inconsistent C++11 ABI between headers and libraries. See bug#66145 for more details (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145). 2017-02-25 14:38:38 +01:00
Florent Rougon
4b010cc416 Minor change to simgear/io/iostreams/zlibstream_test.cxx 2017-02-25 11:30:16 +01:00
Florent Rougon
46f39d5fbd zlibstream classes: add constructors with sink semantic based on std::unique_ptr
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.
2017-02-24 22:51:21 +01:00
Florent Rougon
03515151f0 Add new test trying to read max amount with ZlibDecompressorIStreambuf::xsgetn()
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).
2017-02-24 22:51:21 +01:00
Florent Rougon
8cd723d91b Fix build errors in zlibstream*.cxx, re-enable their compilation
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!
2017-02-24 22:51:21 +01:00
Torsten Dreyer
6f2943ed9a disable service test for now 2017-02-23 18:34:48 +01:00
Torsten Dreyer
e509fc3f5d Prepare for terrasync/https 2017-02-23 16:35:29 +01:00
James Turner
707d9e12cf Fix issues with package upgrades on Windows. 2017-02-23 13:26:02 +00:00
Automatic Release Builder
9840302931 new version: 2017.2.0 2017-02-20 18:52:12 +01:00
Automatic Release Builder
983047982f new version: 2017.1.1 2017-02-20 18:52:12 +01:00
James Turner
f977be5fe4 Concept for developer log messages. 2017-02-14 18:27:40 -08:00
Florent Rougon
e21ad4b5c1 Disable building of zlibstream.cxx for now
It is unclear to me how to correctly fix some of the remaining build
errors obtained on jenkins, therefore I am disabling it from the build
for now.
2017-02-12 23:55:03 +01:00
Florent Rougon
619055f544 Attempt at fixing build errors for simgear/io/iostreams/zlibstream.cxx
Apparently (on Jenkins), std::unordered_map doesn't like enums as keys.
Too bad, this made the code more compact...
2017-02-12 22:22:08 +01:00
Florent Rougon
c9611fc45b Add stream buffers and std::istream subclasses to deal with zlib compression
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.
2017-02-12 21:18:52 +01:00
Florent Rougon
79f869a7f3 Move IOStreams-related files to simgear/io/iostreams; rename zfstream.[ch]xx to gzfstream.[ch]xx
- 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).
2017-02-12 21:18:52 +01:00
Torsten Dreyer
1b8dfb2bef Accept time token for .dirindex files
print the timestamp on log-level "info"
2017-02-12 17:39:12 +01:00
Richard Harrison
143a47482b Change the log level of the "failed to load sound buffer" as it shouldn't be a popup because within my interpreation it is not within the definition of what POPUP should be used for. 2017-02-11 13:34:01 +01:00
James Turner
a28cf0f860 Additional SGPath test for remove + rename.
Trying to track down failure to update aircraft on Windows.
2017-02-09 18:48:05 +00:00
James Turner
d9f4d7373f SGFile uses wide-string APIs on Windows. 2017-02-07 16:15:14 +00:00
James Turner
c3f48c7261 Use sg_ofstream in one more place. 2017-02-07 16:05:06 +00:00
James Turner
48b7b70e23 BinObj code uses wide-strings on Windows. 2017-02-07 16:05:06 +00:00
James Turner
b93b362e2f Fix wide-string support for wav-file reader. 2017-02-07 16:05:06 +00:00
Bertrand Coconnier
2082b18e2e Export the symbol ENABLE_SIMD for FG to build with the same setting. 2017-02-07 00:02:39 +01:00
Erik Hofman
7f65e7f905 We need to copy the matrix before altering it's contents: Fix a SGMathTest failure 2017-02-03 15:07:35 +01:00
Erik Hofman
3417ca7e49 Add a linear-interpolation function 2017-02-02 11:35:11 +01:00
Richard Senior
6334c30eb6 Allow empty reason string in validation of HTTP response.
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
2017-02-01 10:23:10 +00:00
Erik Hofman
c87dff7e8f More code cleanups ans fix a Clang problem. And disable AVX for good, I don't have time for this crap anymore: it looks like a hardware or compielr bug 2017-01-31 00:04:01 +01:00
Erik Hofman
332f76f34d Last code cleanups and more explicit constructors 2017-01-30 18:25:42 +01:00
Erik Hofman
3387f3d084 Switch to c++11 alignas instead of our own hacks 2017-01-30 16:00:29 +01:00
Erik Hofman
bd421c381c Also make AVX available for simd4x4 2017-01-30 12:53:52 +01:00
Erik Hofman
0cce949837 Fix the last bug that prevented AVX from working properly. Hopefully this fixes all other SIMD related problems too 2017-01-30 12:25:51 +01:00
James Turner
ed3ba67925 Logging system buffers startup messages.
This allows adding log callbacks easier during startup, without 
missing the initial messages, which might be very important.
2017-01-30 07:43:35 +01:00
Erik Hofman
866f85064a Fix a mistake 2017-01-30 00:18:36 +01:00
Erik Hofman
9215c530b3 Explicit declaration of more constructors to make sure the laste lane of simd4_t<T,3> and the last two lanes of simd4_t<T,2> remain zero 2017-01-29 15:26:34 +01:00
James Turner
a6437f4e96 More SGPropertyNode::getPositions tests. 2017-01-28 15:37:41 +00:00
James Turner
5bd7be6ed1 Check for file permissions via SGPath. 2017-01-28 15:37:41 +00:00
Florent Rougon
d9cc3738b9 Improve sgstream_test.cxx
- 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).
2017-01-26 16:58:20 +01:00
Erik Hofman
edec5bbc01 There is still a segmenttion fault issue with the AVX code, disable it until this is sorted out 2017-01-26 14:46:36 +01:00
Florent Rougon
6a2d86c526 Small improvements for simgear::Dir
- 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().
2017-01-26 12:41:59 +01:00
Stuart Buchanan
6c64e9b36c Add scenery-path-suffix support to terrasync
Remove /sim/rendering/building-mesh as it is
redundant.

Add check that objects are in the correct bounding
box of the containing STG file.
2017-01-21 22:19:38 +00:00
Erik Hofman
bcecee0f76 Small optimization to my own cross product implementation 2017-01-21 10:28:24 +01:00
Richard Harrison
c5cdfa1a1d Prevent null pointer deference when load has failed.
This was triggered by the TU154B; probably related to the console error

* "Image loading failed:Warning: reading "fgdata\AI\Aircraft\tu154b\Model" not supported.
2017-01-21 00:54:30 +01:00
Erik Hofman
f9f2b4cbdb Bring the ARM NEON code in line with the SSE code 2017-01-20 15:32:28 +01:00
Erik Hofman
33feb9a416 Move SIMD flags to CMAKE_CXX_FLAGS_RELEASE and fix a typo in the process 2017-01-20 14:56:15 +01:00
Erik Hofman
9e1aaa8b56 Make a distinction between a null-pointer and the value of 0 2017-01-19 23:14:39 +01:00
Erik Hofman
ef2eb635af Fix a header path 2017-01-19 16:41:01 +01:00
Erik Hofman
2db412a923 Specialize class constructors in the hope to ged rid of wrong compiler assignment of an unaligned float array to an SSE register 2017-01-19 16:39:30 +01:00
Erik Hofman
061fea48c8 Add an ARM NEON readu simd4x4_neon.hxx and small fixes for simd_neon.hxx 2017-01-19 13:20:52 +01:00
Erik Hofman
c4ea62a899 Add a version of simd.hxx for ARM NEON 2017-01-18 15:41:12 +01:00
Erik Hofman
789c09a402 I forgot the linux variant of ALIGN 2017-01-12 14:19:09 +01:00
Erik Hofman
de9b329115 reorganize the code a bit 2017-01-12 11:43:46 +01:00
Erik Hofman
1b793a127c Be more explicit about alignment 2017-01-12 10:18:39 +01:00
James Turner
3cb3084725 Rename ‘new’ thumbnails to ‘previews’
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.
2017-01-10 18:05:40 +00:00
Erik Hofman
637f67888a Reinstate AVX support again 2017-01-07 13:55:09 +01:00
Erik Hofman
fbc0986fd8 Do not rely on SSE3, this is just a slight drawback 2017-01-06 15:10:52 +01:00
Erik Hofman
14ebe0b618 Disable AVX support until someone figures out why it is not working properly 2017-01-06 00:11:05 +01:00
James Turner
fd34cc30b8 compare_versions: limit how many parts are checked.
This can be used to only check the first one or two parts of a version,
to ensure only the major, or major+minor parts match.
2017-01-05 10:55:14 +00:00
Erik Hofman
7b0faed03a Fix an AVX error 2017-01-04 16:30:19 +01:00
Erik Hofman
8d1dc30b07 Try to fix a possible AVX core dump 2017-01-04 12:55:28 +01:00
Erik Hofman
03cff6abca Fix Never use <avxintrin.h> directly; include <immintrin.h> instead. 2017-01-01 13:26:36 +01:00
Erik Hofman
d7821324b8 Fix a wrong enclosing bracket 2017-01-01 11:40:59 +01:00
Ron Haertel
f3e066cce0 Bug fix for bug 1920
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
2016-12-30 18:49:19 -05:00
James Turner
45ac758cc9 Expose position on SGPropertyNode. 2016-12-27 11:09:07 +00:00
Erik Hofman
f0e6402fff One more, and hopefully the last, MSVC fix 2016-12-23 15:31:40 +01:00
Erik Hofman
41bf142e31 Try to fix an MSVC compile error 2016-12-23 14:50:14 +01:00
Erik Hofman
2e9efa98d7 Add accelearated cross product 2016-12-22 13:43:04 +01:00
Erik Hofman
2c2a57f368 Addd support for AVX, 4 double precision operations in one go 2016-12-21 09:04:46 +01:00
Erik Hofman
4ea1326126 A better MSVC fix and code speedups 2016-12-20 09:54:19 +01:00
Erik Hofman
09b44ac68a MSVC compiler fix (hopefully) 2016-12-19 18:37:52 +01:00
Erik Hofman
a48ab434ab Convert more code to SIMD 2016-12-19 15:58:57 +01:00
Florent Rougon
d39a56d4fb Add missing include: <cctype> for unary std::islower()
Thanks to Ron H. for the report.
2016-12-18 11:02:01 +01:00
Erik Hofman
892579456d add SSE support for the C compiler (gcc and clang) 2016-12-18 09:40:38 +01:00
Erik Hofman
4dde1d365c MSVC 2013+ for 64-bit automatically sets /arch:SSE2 and doesn't recognise te option 2016-12-17 10:50:19 +01:00
James Turner
2f21b582cd Canvas image fill and source rect setters.
C++ code can set the fill and source rect directly.
2016-12-16 19:14:44 +00:00
James Turner
b29536f8b7 Set Canvas element transforms from C++
Also allow transforms to be disabled.
2016-12-16 19:14:44 +00:00
James Turner
039f9920db Direct rect support. 2016-12-16 19:14:44 +00:00
James Turner
7c254e9c04 Native SVG path-data parsing in the Canvas.
This substantially cuts down the amount of properties needed when
importing SVG elements into Canvas paths.
2016-12-16 19:14:44 +00:00
Erik Hofman
35a115bfd4 Fix a stupid mistake and move hsum_ps_sse to shVector.c 2016-12-16 16:01:59 +01:00
Erik Hofman
70dd9d35b1 Also accelerate SHVector3 using SIMD 2016-12-16 15:12:53 +01:00
Erik Hofman
31e3cf06fb Accelerate SHVector4 and SHMatrix3x3 operations using SIMD 2016-12-16 14:54:24 +01:00
Erik Hofman
175eddd1fa Add the proper SSE options to Clang too 2016-12-16 11:05:03 +01:00
Erik Hofman
fe73247b82 Really use _mm_setzero_ps9) instead 2016-12-16 11:04:49 +01:00
Erik Hofman
203db3d095 Enable SSE and SSE2 by default 2016-12-16 10:49:44 +01:00
James Turner
8c4695b991 Fix duplicate variants in packages. 2016-12-15 17:37:32 +00:00
James Turner
a2b111bb09 Bugfix: reject dubious paths in HTTP repos.
This avoids a malicious repository writing to files outside the local
storage root.
2016-12-15 17:37:28 +00:00
James Turner
2a1542d544 Helper for parsing CSS/SVG strings. 2016-12-15 17:37:25 +00:00
Erik Hofman
e5b51677c5 MacOS fix 2016-12-15 13:11:31 +01:00
Erik Hofman
f9450d136d Minor speedups in small tweaks 2016-12-15 09:57:10 +01:00
Erik Hofman
0586cb62c3 Fix the pink-sky bug, don't initilize the vector with (z,y,z,w) but use the proper (x,y,z,w) instead 2016-12-15 09:56:52 +01:00
Erik Hofman
8fee04b32b Generalize the code to be able to test integers too 2016-12-14 11:05:56 +01:00
Erik Hofman
04e16c95e2 Consolidate some code, exlicitly use intrinsics (instead of the usual math operators): this fixes a compiler bug for integers and add some SSE4.1 accelerations for integers 2016-12-14 11:05:31 +01:00
Erik Hofman
e257dbe6ed accelerate float rotation_matrix and fix a bug for double rotation_matrix 2016-12-14 11:03:32 +01:00
Erik Hofman
abf78f8e31 Make absolutely sure the unions are 16-bytes aligned, move more setters and min() and max() to the simd implementation and add horizontal SIMD add functions for magnitude2 and dot 2016-12-12 20:27:07 +01:00
Stuart Buchanan
da13bd9f04 Fix minor compiler warnings 2016-12-10 16:00:28 +00:00
Alessandro Menti
86fb1ed00f BoostTestTargets.cmake: fix a wrong include test
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
2016-12-08 11:47:18 +01:00
Erik Hofman
56fb81dc03 Hopefuly the last MSVC fix 2016-12-08 09:39:45 +01:00
Erik Hofman
343ce57468 Tupe conversion is evil, don't allow it 2016-12-08 01:02:44 +01:00
Erik Hofman
3e52e37181 remove explicit, it looks like SMVC chokes on it 2016-12-07 13:22:17 +01:00
Erik Hofman
e768553a4a Replace auto_ptr with unique_ptr 2016-12-07 11:03:49 +01:00
Erik Hofman
b74d1a8351 Add some more accelerated functions (dot, magnitude, matrix transpose), allow simd_t4 with non mathcing elements to be assigned and a bunch of fixes. Make sure the code compiles when SSE is not available. 2016-12-07 10:00:02 +01:00
James Turner
801d8c4af5 Revert recursive listeners for the moment.
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'.
2016-12-05 12:57:29 +00:00
Florent Rougon
3a4693803b strutils: new functions stripTrailingNewlines() and stripTrailingNewlines_inplace() 2016-12-04 22:41:12 +01:00
Florent Rougon
79f0d3356e Convert strutils_test.cxx to use the SG test macros instead of BOOST 2016-12-04 22:41:12 +01:00
Florent Rougon
6a1bf02ddb Use appropriate test macros in parse_color_test.cxx and state_machine_test.cxx
- 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().
2016-12-04 22:41:12 +01:00
Florent Rougon
6662800deb Expand the test macros framework
- 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.
2016-12-04 22:41:04 +01:00
Florent Rougon
c9bb6102c0 Test macros: add parentheses around arguments 2016-12-04 21:22:43 +01:00
Florent Rougon
90479419cc Add test macros: SG_CHECK_NE, SG_CHECK_LT, SG_CHECK_LE, SG_CHECK_GT, SG_CHECK_GE 2016-12-04 21:09:39 +01:00
Florent Rougon
b4178ae888 Test macros: be more rigorous and consistent
- 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'.
2016-12-04 21:09:39 +01:00
Florent Rougon
ab4814c916 simgear/misc/test_macros.hxx: add missing <iostream> header + minor changes
- 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.
2016-12-04 21:09:39 +01:00
Florent Rougon
6b16f96c8a Test macros: use defensive parentheses and std::fabs() for SG_CHECK_EQUAL_EP*
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.
2016-12-04 21:09:39 +01:00
Florent Rougon
e655d41817 Rename the COMPARE, COMPARE_EP, COMPARE_EP2 and VERIFY test macros
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.
2016-12-04 21:04:40 +01:00
James Turner
b5c1902a2d Tweaks to recursive listener behaviour 2016-12-03 14:09:56 +00:00
James Turner
d088259739 Add aliased listener test, disabled for now. 2016-12-02 17:15:11 +00:00
James Turner
d8acf44a3a Revert unintended change in listener refactoring. 2016-12-02 17:14:27 +00:00
Torsten Dreyer
4664af12fa Fix lockup on Windows when polling DNS, add test 2016-12-02 14:44:38 +01:00
James Turner
7a909d0c0b Improved Package search function.
Handle or/and groups, and search variant descriptions and names.
2016-11-30 21:32:31 +00:00
James Turner
919c25769c Quiet a canvas message. 2016-11-30 12:18:44 +00:00
James Turner
5a0908d5bb Package::indexOfvariant works on fully-qualified IDs.
Should fix issues restoring variants in the launcher.
2016-11-29 15:36:00 +00:00
Erik Hofman
1c39daec07 Fix an error 2016-11-27 10:19:17 +01:00
James Turner
835ae941ce Unit-tests for localised-variant strings. 2016-11-26 14:28:22 +00:00
James Turner
63edff078f Fix warnings in sgvec4 test.
Use C++ type-overloaded fabs call.
2016-11-26 14:20:17 +00:00
Erik Hofman
0ea9786601 Add SIMD matrix operations 2016-11-26 11:40:01 +01:00
Florent Rougon
9e0bb33d58 Fix missing include in simgear/props/props_test.cxx 2016-11-26 01:12:34 +01:00
James Turner
64531c85e3 Generalise per-variant localised string lookup.
Will be used for per-variant long-descriptions.
2016-11-25 22:44:24 +00:00
James Turner
14cdae5102 Unit-test for copy-installed children. 2016-11-25 22:19:55 +00:00
James Turner
2aaad212e8 Revert partial-update mode for TerraSync repos.
Going to implement this a different, simpler way now,
2016-11-25 22:19:51 +00:00
James Turner
bd88bf1126 Explicit handling of recursive listeners.
Use a different strategy for recursive listeners, and make them opt-in.
2016-11-25 16:07:18 +00:00
James Turner
ea9da65b7c Expanded property unit-tests. 2016-11-25 16:07:18 +00:00
Erik Hofman
e7f80cf5f3 Finish SIMD Vector code, do not change matrix operations yet since it seems to have a problem 2016-11-25 13:31:54 +01:00
Erik Hofman
16d62f93c8 Fix a clang reported error 2016-11-22 15:18:16 +01:00
Erik Hofman
e96834fcc6 Fix an error 2016-11-22 14:36:28 +01:00
Erik Hofman
22a74c63b4 First changes for SIMD matrix operations 2016-11-22 14:27:42 +01:00
James Turner
5681fcbdc5 Unit-tests for property listener. 2016-11-22 00:19:18 +00:00
James Turner
7755f8e094 Override changes for atomic listener. 2016-11-22 00:15:14 +00:00
James Turner
e266e44f63 Extended scenery/STG suffix handling 2016-11-22 00:09:51 +00:00
Erik Hofman
4dc66a385e Include SGMathFwd.hxx to add unknown math types 2016-11-21 09:22:09 +01:00
Erik Hofman
aec29a3a37 Fix clang errors 2016-11-20 23:54:15 +01:00
Erik Hofman
0d213a1990 Fix a typo 2016-11-20 16:16:28 +01:00
Erik Hofman
8162a49f6c Give vector math a (potential) boost. Next stoP; matrices 2016-11-20 16:15:40 +01:00
Torsten Dreyer
d2e2603400 initialize udns_library on first use 2016-11-20 16:12:01 +01:00
Erik Hofman
43a8277bdb Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2016-11-20 15:01:10 +01:00
Erik Hofman
61a8bd5cd3 _m128d ony holds two doubles instead of 4 (obviously). 2016-11-20 15:00:24 +01:00
Erik Hofman
ad6f3d2db2 Small updates 2016-11-20 14:59:43 +01:00
Torsten Dreyer
9088f41352 Use private udns context for each DNSClient 2016-11-20 12:35:43 +01:00
Erik Hofman
73f57bbbd8 Add a test utility 2016-11-19 15:57:05 +01:00
Erik Hofman
a8673356a2 Be more specific about the exact type 2016-11-19 15:56:06 +01:00
James Turner
5ecc1ab6f2 Simplify timing code.
Assumes we have timegm on Unix, and use _mkgmtime on Windows.
This means we never need to use ftime() / timeb.h
2016-11-17 21:23:56 +01:00
Automatic Release Builder
0702f85540 new version: 2017.1.0 2016-11-17 13:43:29 +01:00
Automatic Release Builder
277dab0d55 new version: 2016.4.1 2016-11-17 13:43:29 +01:00
Erik Hofman
321a3fdaba Fix a typo 2016-11-17 13:05:08 +01:00
Erik Hofman
2eb17d0083 Revetr previous paatch for SGVec4 so close to the release 2016-11-17 11:50:15 +01:00
Erik Hofman
ff7e4597e7 Maximize simd optimization 2016-11-17 11:48:16 +01:00
Erik Hofman
4a4baf1b42 Merge branch 'next' of ssh://git.code.sf.net/p/flightgear/simgear into next 2016-11-17 09:15:02 +01:00
Erik Hofman
2672d5cd11 include simd.hxx 2016-11-17 09:14:51 +01:00
Erik Hofman
1bf3d7c9b1 Add a copyright header 2016-11-16 15:34:25 +01:00
Erik Hofman
f7c0a7f933 Add a simd_t<int> class and more inlining 2016-11-16 14:00:25 +01:00
Erik Hofman
6bf864babb Add class assingment functions 2016-11-16 13:33:51 +01:00
Erik Hofman
43bd1b15ee Add a SIMD accelerator class for float[4] and double[4] types 2016-11-16 12:45:14 +01:00
Rebecca N. Palmer
14c79d9ffb Nasal: disable NASAL_NAN64 on non-x86
Not every architecture has <=48-bit virtual address spaces:
http://meetings-archive.debian.net/pub/debian-meetings/2016/miniconf_cambridge16/Thanks_for_the_Memory.webm
2016-11-15 22:50:41 +00:00
James Turner
3009aadaa6 Simplify Boost auto-detection on MSVC. 2016-11-14 23:05:10 +01:00
James Turner
fca64343ae Attempting to fix Windows include issues.
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.
2016-11-14 07:52:15 +01:00
James Turner
042a2659f6 Disable Codecvt for now, libstdc++ is problematic.
Need to research which libstdc++ versions implement codecvt.
2016-11-14 07:45:23 +01:00
James Turner
fe54af405c Zlib is a public, not private include in Simgear.
Should fix Windows compilation as reported by Alan Teeder on the list.
2016-11-14 07:31:54 +01:00
James Turner
ab70090a0a Finally fix bogus terrasync download numbers.
(Staying a hotel with sufficiently slow wi-fi to debug this!)
2016-11-13 22:18:32 +01:00
James Turner
ee02750e95 Enforce VS2013/2015 requirement on Windows. 2016-11-13 14:57:39 +00:00
James Turner
f55007394e Make more includes target-specific. 2016-11-13 14:57:21 +00:00
James Turner
60a9e8fb7e Implement UTF-8 conversion using codecvt 2016-11-13 14:56:52 +00:00
James Turner
7f8455f731 Multi-thumbnail support in packages.
Allow multiple thumbnails per variant / package, including
tagging with types so we can require certain thumbnails in the future.
2016-11-13 14:56:31 +00:00
James Turner
6ae86fc4ca Fix a warning. 2016-11-13 12:02:12 +00:00
Torsten Dreyer
e1fb13bed8 Allow passing of service and protocol for DNS SRV requests 2016-11-09 13:30:58 +01:00
Torsten Dreyer
27fff3b72a Sort DNS TXT entries and provide an attribute map 2016-11-09 12:03:37 +01:00
Torsten Dreyer
6a9235223e Set correct class for DNS TXT queries 2016-11-09 09:44:10 +01:00
Stuart Buchanan
c1e50e9a9c Correct mesh size correction for building LOD ranges 2016-11-08 20:06:34 +00:00
Stuart Buchanan
dcbf5b7c11 Fix for OBJECT_BUILDING_MESH_DETAILED 2016-11-08 19:56:08 +00:00
Torsten Dreyer
4b571f2a24 Implement SRV and TXT DNS records 2016-11-08 17:09:37 +01:00
Erik Hofman
679b7b845c Always define the class destructor 2016-11-08 13:17:15 +01:00
Edward d'Auvergne
50d7127c51 Calculation of the illuminance factor for the moon.
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 .
2016-11-08 09:49:57 +01:00
Edward d'Auvergne
0e09ee4bce Calculation of the log of the illuminance of the moon outside the atmosphere.
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).
2016-11-08 09:49:57 +01:00
Edward d'Auvergne
76ebd569d5 Calculation and exposure of the moon's age and phase.
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.
2016-11-08 09:49:57 +01:00
Edward d'Auvergne
edcd42bc2d Optimisation of the celestialBody ephemeris code.
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().
2016-11-08 09:49:57 +01:00
Edward d'Auvergne
f04e501472 Exposure of the moon position.
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).
2016-11-08 09:49:57 +01:00
Edward d'Auvergne
32d152ba38 A few spelling fixes for the moon position ephemeris code. 2016-11-08 09:49:57 +01:00
Edward d'Auvergne
94c4c44d92 Optimisation of the moon position ephemeris code.
By storing repetitive intermediate calculations, the number of mathematical
operations for a single call to MoonPos::updatePosition() has decreased by 32.
2016-11-08 09:49:57 +01:00
James Turner
ab1d4e651e Bugfix: avoid bogus download size on start
Missed a default init of the HTTP repo download content size, so until
the request response header was received, this could report a very
large value.
2016-11-07 15:49:07 +01:00
James Turner
5cd250e452 Packages: notify delegate of uninstalls. 2016-11-06 21:58:01 +01:00
James Turner
2dcff4bb8e Ensure build include location is used first.
Otherwise PREFIX_PATH headers might be found first, but these could be
from an older SimGear version.
2016-11-06 21:57:30 +01:00
James Turner
604a9ff614 Hopefully fix Win32 linkage. 2016-11-02 22:57:39 +00:00
James Turner
a09630bcca Cmake export fixes.
Should hopefully fix importing in FlightGear
2016-11-02 13:59:43 +00:00
James Turner
b44c70b3f4 Simplify isnan detection with C++11 library. 2016-10-30 22:49:38 +00:00
James Turner
e4cddb100e Drastically simplify compiler.h 2016-10-30 22:49:11 +00:00
Erik Hofman
e3a4144e6c Switch to SGMisc::isNaN 2016-10-28 11:18:40 +02:00
James Turner
51e7d95bf2 Require CMake 3.0, enable C++11
Let’s see what this breaks.
2016-10-24 22:52:51 +02:00
James Turner
202571386b Exported package fix.
https://sourceforge.net/p/flightgear/codetickets/1892/
2016-10-20 20:26:51 +01:00
Florent Rougon
7837bd0e11 Add parameter 'use_exact_name' to sg_gzifstream's constructor and open() method
This allows one to be sure about which file is opened.
2016-10-20 14:07:08 +02:00
Florent Rougon
11c6e5bf04 Require zlib 1.2.4 or compatible
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.
2016-10-19 21:17:54 +02:00
Florent Rougon
8277857827 Add gzfilebuf::approxOffset() and sg_gzifstream::approxOffset()
gzfilebuf::approxOffset() is a wrapper for zlib's offset() function.
It can be useful to implement progress indicators and such.
2016-10-19 00:30:55 +02:00
Florent Rougon
412111ba5a Change sgSearchPathSep into a public static member: SGPath::pathListSep
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).
2016-10-12 09:05:21 +02:00
James Turner
dd52b6af50 Remove some archaic code. 2016-10-09 11:08:17 +02:00
Erik Hofman
a97c145f56 Always return a value 2016-10-04 09:08:43 +02:00
Erik Hofman
b9deebb59d It's perfectly valid to call is_sample_stopped() even if the sample was already stopped. So remove the assert and replace it with an if-test 2016-10-03 09:55:31 +02:00
Richard Harrison
906813c90b Console handling: VS2015 seems to only work with redirection when both stdout and stderr are redirected; so show a message box error when redirecting only one stream. 2016-10-02 02:29:22 +02:00
Florent Rougon
1711592e64 A few more tests for simgear::strutils::split() 2016-10-01 10:44:33 +02:00
James Turner
7b2507cb19 Config changes to warn on older tools.
Warn on to-be-deprecated versions of Cmake, Visual Studio and GCC
2016-09-28 17:20:51 -05:00
James Turner
2e19aaaff9 Remove multi-arch workaround in CMake
Since we now require 2.8.11, we can rely on this bug being fixed.
2016-09-27 20:43:03 -05:00
James Turner
6854598b79 Initial pieces for full OBJ support.
Needs testing by aircraft developers, this is just the first piece.
2016-09-27 20:41:31 -05:00
Stuart Buchanan
809ddb21c9 Add STG verbs for building mesh integration.
Add OBJECT_BUILDING_MESH_ROUGH and OBJECT_BUILDING_MESH_DETAILED

Intended for use by OSM buildings.
2016-09-22 20:38:58 +01:00
Richard Harrison
38bab59c1a Revised Windows console handling
- 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.
2016-09-21 00:50:13 +02:00
James Turner
87590cafb2 Fix terrasync behaviour when net is down. 2016-09-07 22:49:03 +01:00
511 changed files with 44774 additions and 13393 deletions

3
.gitignore vendored
View File

@@ -14,3 +14,6 @@ CTestTestfile.cmake
install_manifest.txt
build*
Build
CMakeLists.txt.user
3rdparty/expat_2.2.6/
nbproject

View File

@@ -2,8 +2,6 @@ if (NOT SYSTEM_EXPAT)
add_subdirectory(expat)
endif()
add_subdirectory(utf8)
if (ENABLE_DNS AND NOT SYSTEM_UDNS)
add_subdirectory(udns)
endif()

View File

@@ -1,7 +1,7 @@
configure_file (
"${PROJECT_SOURCE_DIR}/3rdparty/expat/expat_config_cmake.in"
"${PROJECT_BINARY_DIR}/3rdparty/expat/expat_config.h"
"${PROJECT_BINARY_DIR}/3rdparty/expat/simgear_expat_config.h"
)
set(expat_sources

View File

@@ -18,6 +18,8 @@
#include "amigaconfig.h"
#elif defined(__WATCOMC__)
#include "watcomconfig.h"
#elif defined(HAVE_SIMGEAR_EXPAT_CONFIG_H)
#include "simgear_expat_config.h"
#elif defined(HAVE_EXPAT_CONFIG_H)
#include "expat_config.h"
#endif /* ndef COMPILED_FROM_DSP */

View File

@@ -12,6 +12,8 @@
#include "amigaconfig.h"
#elif defined(__WATCOMC__)
#include "watcomconfig.h"
#elif defined(HAVE_SIMGEAR_EXPAT_CONFIG_H)
#include "simgear_expat_config.h"
#else
#ifdef HAVE_EXPAT_CONFIG_H
#include "expat_config.h"

View File

@@ -12,6 +12,8 @@
#include "amigaconfig.h"
#elif defined(__WATCOMC__)
#include "watcomconfig.h"
#elif defined(HAVE_SIMGEAR_EXPAT_CONFIG_H)
#include "simgear_expat_config.h"
#else
#ifdef HAVE_EXPAT_CONFIG_H
#include "expat_config.h"

View File

@@ -24,7 +24,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
# include <winsock2.h> /* includes <windows.h> */
# include <iphlpapi.h> /* for dns server addresses etc */
#else
@@ -53,7 +53,7 @@ static void dns_set_srch_internal(struct dns_ctx *ctx, char *srch) {
dns_add_srch(ctx, srch);
}
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
#ifndef NO_IPHLPAPI
/* Apparently, some systems does not have proper headers for IPHLPAIP to work.
@@ -217,7 +217,7 @@ int dns_init(struct dns_ctx *ctx, int do_open) {
ctx = &dns_defctx;
dns_reset(ctx);
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
if (dns_initns_iphlpapi(ctx) != 0)
dns_initns_registry(ctx);
/*XXX WINDOWS: probably good to get default domain and search list too...

View File

@@ -24,7 +24,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
# include <winsock2.h> /* includes <windows.h> */
# include <ws2tcpip.h> /* needed for struct in6_addr */
#else
@@ -392,7 +392,7 @@ dns_set_tmcbck(struct dns_ctx *ctx, dns_utm_fn *fn, void *data) {
}
static unsigned dns_nonrandom_32(void) {
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return ft.dwLowDateTime;
@@ -551,7 +551,7 @@ int dns_open(struct dns_ctx *ctx) {
ctx->dnsc_qstatus = DNS_E_TEMPFAIL;
return -1;
}
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
{ unsigned long on = 1;
if (ioctlsocket(sock, FIONBIO, &on) == SOCKET_ERROR) {
closesocket(sock);
@@ -991,7 +991,7 @@ again: /* receive the reply */
* or remote. On local errors, we should stop, while
* remote errors should be ignored (for now anyway).
*/
#ifdef WINDOWS
#if defined(_WINDOWS) || defined(WINDOWS)
if (WSAGetLastError() == WSAEWOULDBLOCK)
#else
if (errno == EAGAIN)

View File

@@ -27,7 +27,7 @@
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#ifndef WINDOWS
#if !defined(_WINDOWS) && !defined(WINDOWS)
# include <sys/types.h>
# include <netinet/in.h>
#endif

View File

@@ -1,17 +0,0 @@
include (SimGearComponent)
set(HEADERS
source/utf8.h
)
set(HEADERS_utf8
source/utf8/checked.h
source/utf8/core.h
source/utf8/unchecked.h
)
set(SOURCES
)
simgear_component(utf8 3rdparty/utf8 "${SOURCES}" "${HEADERS}")
simgear_component(utf8-internal 3rdparty/utf8/utf8 "" "${HEADERS_utf8}")

View File

@@ -1,12 +0,0 @@
utf8 cpp library
Release 2.3.4
A minor bug fix release. Thanks to all who reported bugs.
Note: Version 2.3.3 contained a regression, and therefore was removed.
Changes from version 2.3.2
- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';'
- Bug fix [36]: replace_invalid() only works with back_inserter
Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "utf8/checked.h"
#include "utf8/unchecked.h"
#endif // header guard

View File

@@ -1,327 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
#include <stdexcept>
namespace utf8
{
// Base for the exceptions that may be thrown from the library
class exception : public ::std::exception {
};
// Exceptions that may be thrown from the library functions.
class invalid_code_point : public exception {
uint32_t cp;
public:
invalid_code_point(uint32_t cp) : cp(cp) {}
virtual const char* what() const throw() { return "Invalid code point"; }
uint32_t code_point() const {return cp;}
};
class invalid_utf8 : public exception {
uint8_t u8;
public:
invalid_utf8 (uint8_t u) : u8(u) {}
virtual const char* what() const throw() { return "Invalid UTF-8"; }
uint8_t utf8_octet() const {return u8;}
};
class invalid_utf16 : public exception {
uint16_t u16;
public:
invalid_utf16 (uint16_t u) : u16(u) {}
virtual const char* what() const throw() { return "Invalid UTF-16"; }
uint16_t utf16_word() const {return u16;}
};
class not_enough_room : public exception {
public:
virtual const char* what() const throw() { return "Not enough space"; }
};
/// The library API - functions intended to be called by the users
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (!utf8::internal::is_code_point_valid(cp))
throw invalid_code_point(cp);
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
template <typename octet_iterator, typename output_iterator>
output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
{
while (start != end) {
octet_iterator sequence_start = start;
internal::utf_error err_code = utf8::internal::validate_next(start, end);
switch (err_code) {
case internal::UTF8_OK :
for (octet_iterator it = sequence_start; it != start; ++it)
*out++ = *it;
break;
case internal::NOT_ENOUGH_ROOM:
throw not_enough_room();
case internal::INVALID_LEAD:
out = utf8::append (replacement, out);
++start;
break;
case internal::INCOMPLETE_SEQUENCE:
case internal::OVERLONG_SEQUENCE:
case internal::INVALID_CODE_POINT:
out = utf8::append (replacement, out);
++start;
// just one replacement mark for the sequence
while (start != end && utf8::internal::is_trail(*start))
++start;
break;
}
}
return out;
}
template <typename octet_iterator, typename output_iterator>
inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
{
static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
return utf8::replace_invalid(start, end, out, replacement_marker);
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it, octet_iterator end)
{
uint32_t cp = 0;
internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
switch (err_code) {
case internal::UTF8_OK :
break;
case internal::NOT_ENOUGH_ROOM :
throw not_enough_room();
case internal::INVALID_LEAD :
case internal::INCOMPLETE_SEQUENCE :
case internal::OVERLONG_SEQUENCE :
throw invalid_utf8(*it);
case internal::INVALID_CODE_POINT :
throw invalid_code_point(cp);
}
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it, octet_iterator end)
{
return utf8::next(it, end);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it, octet_iterator start)
{
// can't do much if it == start
if (it == start)
throw not_enough_room();
octet_iterator end = it;
// Go back until we hit either a lead octet or start
while (utf8::internal::is_trail(*(--it)))
if (it == start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
return utf8::peek_next(it, end);
}
/// Deprecated in versions that include "prior"
template <typename octet_iterator>
uint32_t previous(octet_iterator& it, octet_iterator pass_start)
{
octet_iterator end = it;
while (utf8::internal::is_trail(*(--it)))
if (it == pass_start)
throw invalid_utf8(*it); // error - no lead byte in the sequence
octet_iterator temp = it;
return utf8::next(temp, end);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n, octet_iterator end)
{
for (distance_type i = 0; i < n; ++i)
utf8::next(it, end);
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
utf8::next(first, last);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = utf8::internal::mask16(*start++);
// Take care of surrogate pairs first
if (utf8::internal::is_lead_surrogate(cp)) {
if (start != end) {
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
if (utf8::internal::is_trail_surrogate(trail_surrogate))
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
else
throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
}
else
throw invalid_utf16(static_cast<uint16_t>(cp));
}
// Lone trail surrogate
else if (utf8::internal::is_trail_surrogate(cp))
throw invalid_utf16(static_cast<uint16_t>(cp));
result = utf8::append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start != end) {
uint32_t cp = utf8::next(start, end);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = utf8::append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start != end)
(*result++) = utf8::next(start, end);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
octet_iterator it;
octet_iterator range_start;
octet_iterator range_end;
public:
iterator () {}
explicit iterator (const octet_iterator& octet_it,
const octet_iterator& range_start,
const octet_iterator& range_end) :
it(octet_it), range_start(range_start), range_end(range_end)
{
if (it < range_start || it > range_end)
throw std::out_of_range("Invalid utf-8 iterator position");
}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return utf8::next(temp, range_end);
}
bool operator == (const iterator& rhs) const
{
if (range_start != rhs.range_start || range_end != rhs.range_end)
throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
utf8::next(it, range_end);
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
utf8::next(it, range_end);
return temp;
}
iterator& operator -- ()
{
utf8::prior(it, range_start);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
utf8::prior(it, range_start);
return temp;
}
}; // class iterator
} // namespace utf8
#endif //header guard

View File

@@ -1,329 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include <iterator>
namespace utf8
{
// The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
// You may need to change them to match your system.
// These typedefs have the same names as ones from cstdint, or boost/cstdint
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Helper code - not intended to be directly called by the library users. May be changed at any time
namespace internal
{
// Unicode constants
// Leading (high) surrogates: 0xd800 - 0xdbff
// Trailing (low) surrogates: 0xdc00 - 0xdfff
const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10);
const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN;
// Maximum valid value for a Unicode code point
const uint32_t CODE_POINT_MAX = 0x0010ffffu;
template<typename octet_type>
inline uint8_t mask8(octet_type oc)
{
return static_cast<uint8_t>(0xff & oc);
}
template<typename u16_type>
inline uint16_t mask16(u16_type oc)
{
return static_cast<uint16_t>(0xffff & oc);
}
template<typename octet_type>
inline bool is_trail(octet_type oc)
{
return ((utf8::internal::mask8(oc) >> 6) == 0x2);
}
template <typename u16>
inline bool is_lead_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
}
template <typename u16>
inline bool is_trail_surrogate(u16 cp)
{
return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u16>
inline bool is_surrogate(u16 cp)
{
return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
}
template <typename u32>
inline bool is_code_point_valid(u32 cp)
{
return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
}
template <typename octet_iterator>
inline typename std::iterator_traits<octet_iterator>::difference_type
sequence_length(octet_iterator lead_it)
{
uint8_t lead = utf8::internal::mask8(*lead_it);
if (lead < 0x80)
return 1;
else if ((lead >> 5) == 0x6)
return 2;
else if ((lead >> 4) == 0xe)
return 3;
else if ((lead >> 3) == 0x1e)
return 4;
else
return 0;
}
template <typename octet_difference_type>
inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
{
if (cp < 0x80) {
if (length != 1)
return true;
}
else if (cp < 0x800) {
if (length != 2)
return true;
}
else if (cp < 0x10000) {
if (length != 3)
return true;
}
return false;
}
enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
/// Helper for get_sequence_x
template <typename octet_iterator>
utf_error increase_safely(octet_iterator& it, octet_iterator end)
{
if (++it == end)
return NOT_ENOUGH_ROOM;
if (!utf8::internal::is_trail(*it))
return INCOMPLETE_SEQUENCE;
return UTF8_OK;
}
#define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
/// get_sequence_x functions decode utf-8 sequences of the length x
template <typename octet_iterator>
utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (*it) & 0x3f;
return UTF8_OK;
}
template <typename octet_iterator>
utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
if (it == end)
return NOT_ENOUGH_ROOM;
code_point = utf8::internal::mask8(*it);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
code_point += (*it) & 0x3f;
return UTF8_OK;
}
#undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
template <typename octet_iterator>
utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
{
// Save the original value of it so we can go back in case of failure
// Of course, it does not make much sense with i.e. stream iterators
octet_iterator original_it = it;
uint32_t cp = 0;
// Determine the sequence length based on the lead octet
typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
const octet_difference_type length = utf8::internal::sequence_length(it);
// Get trail octets and calculate the code point
utf_error err = UTF8_OK;
switch (length) {
case 0:
return INVALID_LEAD;
case 1:
err = utf8::internal::get_sequence_1(it, end, cp);
break;
case 2:
err = utf8::internal::get_sequence_2(it, end, cp);
break;
case 3:
err = utf8::internal::get_sequence_3(it, end, cp);
break;
case 4:
err = utf8::internal::get_sequence_4(it, end, cp);
break;
}
if (err == UTF8_OK) {
// Decoding succeeded. Now, security checks...
if (utf8::internal::is_code_point_valid(cp)) {
if (!utf8::internal::is_overlong_sequence(cp, length)){
// Passed! Return here.
code_point = cp;
++it;
return UTF8_OK;
}
else
err = OVERLONG_SEQUENCE;
}
else
err = INVALID_CODE_POINT;
}
// Failure branch - restore the original value of the iterator
it = original_it;
return err;
}
template <typename octet_iterator>
inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
uint32_t ignored;
return utf8::internal::validate_next(it, end, ignored);
}
} // namespace internal
/// The library API - functions intended to be called by the users
// Byte order mark
const uint8_t bom[] = {0xef, 0xbb, 0xbf};
template <typename octet_iterator>
octet_iterator find_invalid(octet_iterator start, octet_iterator end)
{
octet_iterator result = start;
while (result != end) {
utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
if (err_code != internal::UTF8_OK)
return result;
}
return result;
}
template <typename octet_iterator>
inline bool is_valid(octet_iterator start, octet_iterator end)
{
return (utf8::find_invalid(start, end) == end);
}
template <typename octet_iterator>
inline bool starts_with_bom (octet_iterator it, octet_iterator end)
{
return (
((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
((it != end) && (utf8::internal::mask8(*it)) == bom[2])
);
}
//Deprecated in release 2.3
template <typename octet_iterator>
inline bool is_bom (octet_iterator it)
{
return (
(utf8::internal::mask8(*it++)) == bom[0] &&
(utf8::internal::mask8(*it++)) == bom[1] &&
(utf8::internal::mask8(*it)) == bom[2]
);
}
} // namespace utf8
#endif // header guard

View File

@@ -1,228 +0,0 @@
// Copyright 2006 Nemanja Trifunovic
/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
#include "core.h"
namespace utf8
{
namespace unchecked
{
template <typename octet_iterator>
octet_iterator append(uint32_t cp, octet_iterator result)
{
if (cp < 0x80) // one octet
*(result++) = static_cast<uint8_t>(cp);
else if (cp < 0x800) { // two octets
*(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else if (cp < 0x10000) { // three octets
*(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
else { // four octets
*(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
*(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
*(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
*(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
}
return result;
}
template <typename octet_iterator>
uint32_t next(octet_iterator& it)
{
uint32_t cp = utf8::internal::mask8(*it);
typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
switch (length) {
case 1:
break;
case 2:
it++;
cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
break;
case 3:
++it;
cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
++it;
cp += (*it) & 0x3f;
break;
case 4:
++it;
cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
++it;
cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
++it;
cp += (*it) & 0x3f;
break;
}
++it;
return cp;
}
template <typename octet_iterator>
uint32_t peek_next(octet_iterator it)
{
return utf8::unchecked::next(it);
}
template <typename octet_iterator>
uint32_t prior(octet_iterator& it)
{
while (utf8::internal::is_trail(*(--it))) ;
octet_iterator temp = it;
return utf8::unchecked::next(temp);
}
// Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous)
template <typename octet_iterator>
inline uint32_t previous(octet_iterator& it)
{
return utf8::unchecked::prior(it);
}
template <typename octet_iterator, typename distance_type>
void advance (octet_iterator& it, distance_type n)
{
for (distance_type i = 0; i < n; ++i)
utf8::unchecked::next(it);
}
template <typename octet_iterator>
typename std::iterator_traits<octet_iterator>::difference_type
distance (octet_iterator first, octet_iterator last)
{
typename std::iterator_traits<octet_iterator>::difference_type dist;
for (dist = 0; first < last; ++dist)
utf8::unchecked::next(first);
return dist;
}
template <typename u16bit_iterator, typename octet_iterator>
octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
{
while (start != end) {
uint32_t cp = utf8::internal::mask16(*start++);
// Take care of surrogate pairs first
if (utf8::internal::is_lead_surrogate(cp)) {
uint32_t trail_surrogate = utf8::internal::mask16(*start++);
cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
}
result = utf8::unchecked::append(cp, result);
}
return result;
}
template <typename u16bit_iterator, typename octet_iterator>
u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
{
while (start < end) {
uint32_t cp = utf8::unchecked::next(start);
if (cp > 0xffff) { //make a surrogate pair
*result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
*result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
}
else
*result++ = static_cast<uint16_t>(cp);
}
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
{
while (start != end)
result = utf8::unchecked::append(*(start++), result);
return result;
}
template <typename octet_iterator, typename u32bit_iterator>
u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
{
while (start < end)
(*result++) = utf8::unchecked::next(start);
return result;
}
// The iterator class
template <typename octet_iterator>
class iterator : public std::iterator <std::bidirectional_iterator_tag, uint32_t> {
octet_iterator it;
public:
iterator () {}
explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
// the default "big three" are OK
octet_iterator base () const { return it; }
uint32_t operator * () const
{
octet_iterator temp = it;
return utf8::unchecked::next(temp);
}
bool operator == (const iterator& rhs) const
{
return (it == rhs.it);
}
bool operator != (const iterator& rhs) const
{
return !(operator == (rhs));
}
iterator& operator ++ ()
{
::std::advance(it, utf8::internal::sequence_length(it));
return *this;
}
iterator operator ++ (int)
{
iterator temp = *this;
::std::advance(it, utf8::internal::sequence_length(it));
return temp;
}
iterator& operator -- ()
{
utf8::unchecked::prior(it);
return *this;
}
iterator operator -- (int)
{
iterator temp = *this;
utf8::unchecked::prior(it);
return temp;
}
}; // class iterator
} // namespace utf8::unchecked
} // namespace utf8
#endif // header guard

View File

@@ -1,4 +1,4 @@
cmake_minimum_required (VERSION 2.8.11)
cmake_minimum_required (VERSION 3.0)
if(COMMAND cmake_policy)
if(POLICY CMP0054)
@@ -7,6 +7,23 @@ if(COMMAND cmake_policy)
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
if(POLICY CMP0067)
cmake_policy(SET CMP0067 NEW)
endif()
if(POLICY CMP0093)
cmake_policy(SET CMP0093 NEW)
endif()
endif()
message(STATUS "CMAKE Build type: ${CMAKE_BUILD_TYPE}")
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Debug' as none was specified.")
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
"MinSizeRel" "RelWithDebInfo")
endif()
include (CheckFunctionExists)
@@ -16,32 +33,25 @@ include (CheckCXXSourceCompiles)
include (CheckCXXCompilerFlag)
include (GenerateExportHeader)
# using 10.7 because boost requires libc++ and 10.6 doesn't include it
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
# only relevant for building shared libs but let's set it regardless
set(CMAKE_OSX_RPATH 1)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
# Set the C++ standard to C++98 to avoid compilation errors on GCC 6 (which
# defaults to C++14).
if(CMAKE_VERSION VERSION_LESS "3.1")
if(CMAKE_COMPILER_IS_GNUCXX)
set (CMAKE_CXX_FLAGS "-std=gnu++98 ${CMAKE_CXX_FLAGS}")
endif()
else()
set (CMAKE_CXX_STANDARD 98)
endif()
project(SimGear)
# let's use & require C++11 - note these are only functional with CMake 3.1
# we do manual fallbacks for CMake 3.0 in the compilers section
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
# read 'version' file into a variable (stripping any newlines or spaces)
file(READ version versionFile)
string(STRIP ${versionFile} SIMGEAR_VERSION)
# add a dependency on the versino file
project(SimGear VERSION ${SIMGEAR_VERSION} LANGUAGES C CXX)
# add a dependency on the version file
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS version)
set(FIND_LIBRARY_USE_LIB64_PATHS ON)
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
# use simgear version also as the SO version (if building SOs)
SET(SIMGEAR_SOVERSION ${SIMGEAR_VERSION})
@@ -76,8 +86,6 @@ set(CPACK_SOURCE_PACKAGE_FILE_NAME "simgear-${SIMGEAR_VERSION}" CACHE INTERNAL "
set(CPACK_SOURCE_IGNORE_FILES
"^${PROJECT_SOURCE_DIR}/.git;\\\\.gitignore;Makefile.am;~$;${CPACK_SOURCE_IGNORE_FILES}")
message(STATUS "ignoring: ${CPACK_SOURCE_IGNORE_FILES}")
include (CPack)
# We have some custom .cmake scripts not in the official distribution.
@@ -100,21 +108,6 @@ message(STATUS "Library installation directory: ${CMAKE_INSTALL_LIBDIR}")
# Configure library search paths
#####################################################################################
if(NOT "${CMAKE_LIBRARY_ARCHITECTURE}" STREQUAL "")
# Workaround for Ubuntu/Debian which introduced the "multiarch" library
# directory structure, which is unsupported by CMake < 2.8.10, so we need to
# add paths manually
# see http://www.cmake.org/Bug/view.php?id=12049 and
# http://www.cmake.org/Bug/view.php?id=12037
list(APPEND ADDITIONAL_LIBRARY_PATHS
/usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}
/lib/${CMAKE_LIBRARY_ARCHITECTURE})
message(STATUS "additional library directories: ${ADDITIONAL_LIBRARY_PATHS}")
endif()
#####################################################################################
if (NOT MSVC)
option(SIMGEAR_SHARED "Set to ON to build SimGear as a shared library/framework" OFF)
option(SYSTEM_EXPAT "Set to ON to build SimGear using the system expat library" OFF)
@@ -129,18 +122,39 @@ endif()
option(SIMGEAR_HEADLESS "Set to ON to build SimGear without GUI/graphics support" OFF)
option(ENABLE_RTI "Set to ON to build SimGear with RTI support" OFF)
option(ENABLE_GDAL "Set to ON to build SimGear with GDAL support" OFF)
option(ENABLE_TESTS "Set to OFF to disable building SimGear's test applications" ON)
option(ENABLE_SOUND "Set to OFF to disable building SimGear's sound support" ON)
option(USE_AEONWAVE "Set to ON to use AeonWave instead of OpenAL" OFF)
option(USE_AEONWAVE "Set to ON to use AeonWave instead of OpenAL" ON)
option(ENABLE_PKGUTIL "Set to ON to build the sg_pkgutil application (default)" ON)
option(ENABLE_DNS "Set to ON to use udns library and DNS service resolver" ON)
option(ENABLE_SIMD "Enable SSE/SSE2 support for compilers" ON)
option(ENABLE_SIMD_CODE "Enable SSE/SSE2 support code for compilers" OFF)
option(ENABLE_OPENMP "Enable OpenMP compiler support" OFF)
if (NOT ENABLE_SIMD AND ENABLE_SIMD_CODE)
set(ENABLE_SIMD_CODE OFF)
endif()
include (DetectArch)
include (ExportDebugSymbols)
# until the fstream fix is applied and generally available in OSG,
# keep the compatability link option as the default
option(OSG_FSTREAM_EXPORT_FIXED "Set to ON if the osgDB fstream export patch is applied" OFF)
if (CMAKE_COMPILER_IS_GNUCXX OR CLANG)
if (CMAKE_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++${CMAKE_CXX_STANDARD}")
elseif (CMAKE_VERSION VERSION_LESS 3.8)
# policy CMP0067 (try_compile does not honor CMAKE_CXX_STANDARD)
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++${CMAKE_CXX_STANDARD}")
endif()
endif()
if (MSVC)
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} PATH)
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_BINARY_DIR} DIRECTORY)
if (CMAKE_CL_64)
SET(TEST_3RDPARTY_DIR "${PARENT_DIR}/3rdparty.x64")
else (CMAKE_CL_64)
@@ -151,6 +165,11 @@ if (MSVC)
else (EXISTS ${TEST_3RDPARTY_DIR})
set(MSVC_3RDPARTY_ROOT NOT_FOUND CACHE PATH "Location where the third-party dependencies are extracted")
endif (EXISTS ${TEST_3RDPARTY_DIR})
# override CMake default RelWithDebInfo flags. This is important to ensure
# good performance
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/Zi /O2 /Ob2 /D NDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/Zi /O2 /Ob2 /D NDEBUG")
else (MSVC)
set(MSVC_3RDPARTY_ROOT NOT_FOUND CACHE PATH "Location where the third-party dependencies are extracted")
endif (MSVC)
@@ -158,16 +177,24 @@ endif (MSVC)
if (MSVC AND MSVC_3RDPARTY_ROOT)
message(STATUS "3rdparty files located in ${MSVC_3RDPARTY_ROOT}")
string(SUBSTRING ${MSVC_VERSION} 0 2 MSVC_VERSION_MAJOR)
string(SUBSTRING ${MSVC_VERSION} 2 2 MSVC_VERSION_MINOR)
set( OSG_MSVC "msvc" )
if (${MSVC_VERSION} EQUAL 1900)
if (${MSVC_VERSION_MAJOR} EQUAL "19")
if (${MSVC_VERSION_MINOR} GREATER_EQUAL "20")
set( OSG_MSVC ${OSG_MSVC}142 )
elseif (${MSVC_VERSION_MINOR} GREATER_EQUAL "10")
set( OSG_MSVC ${OSG_MSVC}141 )
else ()
set( OSG_MSVC ${OSG_MSVC}140 )
elseif (${MSVC_VERSION} EQUAL 1800)
set( OSG_MSVC ${OSG_MSVC}120 )
elseif (${MSVC_VERSION} EQUAL 1700)
set( OSG_MSVC ${OSG_MSVC}110 )
elseif (${MSVC_VERSION} EQUAL 1600)
set( OSG_MSVC ${OSG_MSVC}100 )
endif ()
elseif (${MSVC_VERSION_MAJOR} EQUAL "18")
set( OSG_MSVC ${OSG_MSVC}120 )
else ()
message(FATAL_ERROR "Visual Studio 2013 or higher is required")
endif ()
if (CMAKE_CL_64)
set( OSG_MSVC ${OSG_MSVC}-64 )
set( MSVC_3RDPARTY_DIR 3rdParty.x64 )
@@ -178,42 +205,24 @@ if (MSVC AND MSVC_3RDPARTY_ROOT)
set (CMAKE_LIBRARY_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenRTI/lib )
set (CMAKE_INCLUDE_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenRTI/include)
GET_FILENAME_COMPONENT(MSVC_ROOT_PARENT_DIR ${MSVC_3RDPARTY_ROOT} PATH)
find_path(BOOST_ROOT boost/version.hpp
PATHS
${MSVC_ROOT_PARENT_DIR}
${MSVC_3RDPARTY_ROOT}/boost
${MSVC_3RDPARTY_ROOT}/boost_1_52_0
${MSVC_3RDPARTY_ROOT}/boost_1_51_0
${MSVC_3RDPARTY_ROOT}/boost_1_50_0
${MSVC_3RDPARTY_ROOT}/boost_1_49_0
${MSVC_3RDPARTY_ROOT}/boost_1_48_0
${MSVC_3RDPARTY_ROOT}/boost_1_47_0
${MSVC_3RDPARTY_ROOT}/boost_1_46_1
${MSVC_3RDPARTY_ROOT}/boost_1_46_0
${MSVC_3RDPARTY_ROOT}/boost_1_45_0
${MSVC_3RDPARTY_ROOT}/boost_1_44_0
)
# set (BOOST_ROOT ${MSVC_3RDPARTY_ROOT}/boost_1_44_0)
message(STATUS "BOOST_ROOT is ${BOOST_ROOT}")
if (NOT USE_AEONWAVE)
set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include)
set (OPENAL_LIBRARY_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib)
message(STATUS "OPENAL_INCLUDE_DIR is ${OPENAL_INCLUDE_DIR}")
if(NOT BOOST_INCLUDEDIR)
# if this variable was not set by the user, set it to 3rdparty root's
# parent dir, which is the normal location for people using our
# windows-3rd-party repo
get_filename_component(MSVC_ROOT_PARENT_DIR ${MSVC_3RDPARTY_ROOT} DIRECTORY)
set(BOOST_INCLUDEDIR ${MSVC_ROOT_PARENT_DIR})
message(STATUS "BOOST_INCLUDEDIR is ${BOOST_INCLUDEDIR}")
endif()
set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include)
set (OPENAL_LIBRARY_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib)
endif (MSVC AND MSVC_3RDPARTY_ROOT)
if(APPLE)
find_library(COCOA_LIBRARY Cocoa)
# this should be handled by setting CMAKE_OSX_DEPLOYMENT_TARGET
# but it's not working reliably, so forcing it for now
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.7")
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR
${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
find_package(Threads REQUIRED)
endif()
@@ -230,18 +239,22 @@ else()
if (ENABLE_SOUND)
if (USE_AEONWAVE)
find_package(AAX COMPONENTS aax REQUIRED)
include_directories( ${AAX_INCLUDE_DIR} )
else()
find_package(OpenAL REQUIRED)
include_directories( ${OPENAL_INCLUDE_DIR} )
find_package(AAX)
endif()
message(STATUS "Sound support: ENABLED")
if(NOT AAX_FOUND)
set(USE_AEONWAVE FALSE)
find_package(OpenAL REQUIRED)
endif()
if(AAX_FOUND)
message(STATUS "Sound support: AeonWave")
else()
message(STATUS "Sound support: OpenAL")
endif()
endif(ENABLE_SOUND)
find_package(OpenSceneGraph 3.2.0 REQUIRED osgText osgSim osgDB osgParticle osgGA osgViewer osgUtil)
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
if (MSVC)
set(CMAKE_REQUIRED_INCLUDES ${OPENSCENEGRAPH_INCLUDE_DIRS})
@@ -254,12 +267,12 @@ else()
int main() { return 0; }"
SIMGEAR_OSG_USE_UTF8_FILENAME)
if (NOT SIMGEAR_OSG_USE_UTF8_FILENAME)
message(WARNING "Please rebuild OSG with OSG_USE_UTF8_FILENAME set to ON")
message(FATAL_ERROR "Please rebuild OSG with OSG_USE_UTF8_FILENAME set to ON")
endif()
endif()
endif(SIMGEAR_HEADLESS)
find_package(ZLIB REQUIRED)
find_package(ZLIB 1.2.4 REQUIRED)
find_package(CURL REQUIRED)
if (SYSTEM_EXPAT)
@@ -269,19 +282,13 @@ if (SYSTEM_EXPAT)
else()
message(STATUS "Using built-in expat code")
# XML_STATIC is important to avoid sg_expat_external.h
# declaring symbols as declspec(import)
add_definitions(-DHAVE_EXPAT_CONFIG_H -DXML_STATIC)
set(EXPAT_INCLUDE_DIRS
${PROJECT_SOURCE_DIR}/3rdparty/expat
${PROJECT_BINARY_DIR}/3rdparty/expat)
${PROJECT_SOURCE_DIR}/3rdparty/expat
${PROJECT_BINARY_DIR}/3rdparty/expat)
endif(SYSTEM_EXPAT)
include_directories(${EXPAT_INCLUDE_DIRS})
check_include_file(inttypes.h HAVE_INTTYPES_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/timeb.h HAVE_SYS_TIMEB_H)
check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(windows.h HAVE_WINDOWS_H)
@@ -291,21 +298,40 @@ if(HAVE_INTTYPES_H)
endif()
if(ENABLE_RTI)
# See if we have any rti library variant installed
message(STATUS "RTI: ENABLED")
find_package(RTI)
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
SET(ENV{PKG_CONFIG_PATH} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig:$ENV{PKG_CONFIG_PATH}")
pkg_check_modules(RTI hla-rti13)
endif(PKG_CONFIG_FOUND)
if(RTI_FOUND)
message(STATUS "RTI: ENABLED")
else()
message(STATUS "RTI: DISABLED")
endif(RTI_FOUND)
else()
message(STATUS "RTI: DISABLED")
endif(ENABLE_RTI)
if(ENABLE_GDAL)
find_package(GDAL 2.0.0 REQUIRED)
if (GDAL_FOUND)
include_directories(${GDAL_INCLUDE_DIR})
endif(GDAL_FOUND)
endif(ENABLE_GDAL)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_function_exists(ftime HAVE_FTIME)
check_function_exists(timegm HAVE_TIMEGM)
check_function_exists(rint HAVE_RINT)
check_function_exists(mkdtemp HAVE_MKDTEMP)
check_function_exists(bcopy HAVE_BCOPY)
check_function_exists(mmap HAVE_MMAP)
if (NOT MSVC)
check_function_exists(timegm HAVE_TIMEGM)
if (NOT HAVE_TIMEGM)
message(FATAL_ERROR "Non-Windows platforms must support timegm()")
endif()
endif()
if(HAVE_UNISTD_H)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_INCLUDE_PATH})
check_cxx_source_compiles(
@@ -349,19 +375,59 @@ SET(CMAKE_RELWITHDEBINFO_POSTFIX "" CACHE STRING "add a postfix, usually empty o
SET(CMAKE_MINSIZEREL_POSTFIX "" CACHE STRING "add a postfix, usually empty on windows")
# isnan might not be real symbol, so can't check using function_exists
check_cxx_source_compiles(
"#include <cmath>
int main() { return isnan(0.0);} "
HAVE_ISNAN)
check_cxx_source_compiles(
"#include <cmath>
int main() { return std::isnan(0.0);} "
HAVE_STD_ISNAN)
if (NOT ${HAVE_STD_ISNAN})
message(FATAL_ERROR "Your compiler lacks C++11 std::isnan, please update it")
endif()
# Check if the <regex> implementation in the C++ standard library is usable.
# This is necessary because g++ 4.8 lies about its C++11 compliance: its
# <regex> is utterly unusable, cf. [1].
# The big preprocessor test essentially comes from [2], and gcc upstream devs
# appear to back it (see comments following [2], as well as [3]).
#
# [1] https://stackoverflow.com/a/12665408/4756009
# [2] https://stackoverflow.com/a/41186162/4756009
# [3] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78905
check_cxx_source_compiles(
"#include <regex>
int main() {
#if __cplusplus >= 201103L && \
(!defined(__GLIBCXX__) || \
(__cplusplus >= 201402L) || \
defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
defined(_GLIBCXX_REGEX_STATE_LIMIT) || \
(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE > 4))
#else
nullptr = void; // intentionally trigger a compilation error
#endif
}"
HAVE_WORKING_STD_REGEX)
if(CMAKE_COMPILER_IS_GNUCXX)
set(WARNING_FLAGS_CXX "-Wall")
set(WARNING_FLAGS_C "-Wall")
set(WARNING_FLAGS_CXX "-Wall -fPIC")
set(WARNING_FLAGS_C "-Wall -fPIC")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4)
message(WARNING "GCC 4.4 will be required soon, please upgrade")
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -O0 -fno-omit-frame-pointer -fno-inline")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -O0 -fno-omit-frame-pointer -fno-inline")
elseif (ENABLE_SIMD)
if (X86 OR X86_64)
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
endif()
endif()
# certain GCC versions don't provide the atomic builds, and hence
# require is to provide them in SGAtomic.cxx
@@ -371,13 +437,41 @@ if(CMAKE_COMPILER_IS_GNUCXX)
GCC_ATOMIC_BUILTINS_FOUND)
endif(CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if (CLANG)
# Boost redeclares class members
set(WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual -Wno-redeclared-class-member")
set(WARNING_FLAGS_C "-Wall")
set(WARNING_FLAGS_CXX "-Wall -fPIC -Wno-overloaded-virtual -Wno-redeclared-class-member")
set(WARNING_FLAGS_C "-Wall -fPIC")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
# fix Boost compilation :(
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
# override CMake default RelWithDebInfo flags.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g -DNDEBUG")
if (ENABLE_SIMD)
if (X86 OR X86_64)
set(CMAKE_C_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -msse2 -mfpmath=sse -ftree-vectorize -ftree-slp-vectorize")
# propogate to the RelWithDebInfo flags
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -g -DNDEBUG")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE} -g -DNDEBUG")
endif()
endif()
endif()
if (ENABLE_OPENMP)
find_package(OpenMP)
if(OPENMP_FOUND)
message(STATUS "OpenMP: ENABLED")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
else()
message(STATUS "OpenMP: NOT FOUND")
endif()
else()
message(STATUS "OpenMP: DISABLED")
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
@@ -396,8 +490,17 @@ if(WIN32)
if(MSVC)
set(MSVC_FLAGS "-DWIN32 -DNOMINMAX -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -D__CRT_NONSTDC_NO_WARNINGS /MP")
if(ENABLE_SIMD)
if (X86)
SET(CMAKE_C_FLAGS_RELEASE "/O2 /arch:SSE /arch:SSE2")
SET(CMAKE_CXX_FLAGS_RELEASE "/O2 /arch:SSE /arch:SSE2")
else()
SET(CMAKE_C_FLAGS_RELEASE "/O2")
SET(CMAKE_CXX_FLAGS_RELEASE "/O2")
endif()
endif()
if (NOT OSG_FSTREAM_EXPORT_FIXED AND ${MSVC_VERSION} GREATER 1599)
if (NOT OSG_FSTREAM_EXPORT_FIXED)
message(STATUS "For better linking performance, use OSG with patched fstream header")
# needed to avoid link errors on multiply-defined standard C++
# symbols. Suspect this may be an OSG-DB export bug
@@ -422,17 +525,15 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS_C} ${MSVC_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} ${BOOST_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}")
include(CheckCXXFeatures)
# use BEFORE to ensure local directories are used first,
# ahead of system-installed libs
include_directories(BEFORE ${PROJECT_SOURCE_DIR})
include_directories(BEFORE ${PROJECT_SOURCE_DIR}/simgear/canvas/ShivaVG/include)
include_directories(BEFORE ${PROJECT_BINARY_DIR}/simgear)
include_directories(
${Boost_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIR}
${CURL_INCLUDE_DIRS}
)
if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
include_directories("/usr/X11R6/include")
endif()
add_definitions(-DHAVE_CONFIG_H)
@@ -462,7 +563,8 @@ set(TEST_LIBS_INTERNAL_CORE
${RT_LIBRARY}
${DL_LIBRARY}
${COCOA_LIBRARY}
${CURL_LIBRARIES})
${CURL_LIBRARIES}
${GDAL_LIBRARY})
set(TEST_LIBS SimGearCore ${TEST_LIBS_INTERNAL_CORE})
if(NOT SIMGEAR_HEADLESS)
@@ -471,8 +573,6 @@ endif()
install (FILES ${PROJECT_BINARY_DIR}/simgear/simgear_config.h DESTINATION include/simgear/)
include_directories(3rdparty/utf8/source)
if(ENABLE_DNS)
if(SYSTEM_UDNS)
message(STATUS "Requested to use system udns library, forcing SIMGEAR_SHARED to true")
@@ -512,7 +612,7 @@ configure_file(SimGearConfig.cmake.in
@ONLY
)
set(ConfigPackageLocation lib/cmake/SimGear)
set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/SimGear)
install(EXPORT SimGearTargets
DESTINATION ${ConfigPackageLocation}
)

View File

@@ -46,11 +46,17 @@ set(BOOST_TEST_TARGET_PREFIX "test")
if(NOT Boost_FOUND)
find_package(Boost 1.34.0 QUIET)
endif()
if("${Boost_VERSION}0" LESS "1034000")
if (NOT Boost_VERSION_MACRO)
# Compatibility with pre CMP0093 (CMake 3.15)
set(Boost_VERSION_MACRO ${Boost_VERSION})
endif()
if("${Boost_VERSION_MACRO}0" LESS "1034000")
set(_shared_msg
"NOTE: boost::test-based targets and tests cannot "
"be added: boost >= 1.34.0 required but not found. "
"(found: '${Boost_VERSION}'; want >=103400) ")
"(found: '${Boost_VERSION_MACRO}'; want >=103400) ")
if(ENABLE_TESTS)
message(FATAL_ERROR
${_shared_msg}
@@ -66,7 +72,7 @@ endif()
include(GetForceIncludeDefinitions)
include(CopyResourcesToBuildTree)
if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
if(Boost_FOUND AND NOT "${Boost_VERSION_MACRO}0" LESS "1034000")
set(_boosttesttargets_libs)
set(_boostConfig "BoostTestTargetsIncluded.h")
if(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
@@ -80,7 +86,7 @@ if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
set(_boostConfig "BoostTestTargetsDynamic.h")
endif()
endif()
get_filename_component(_moddir ${CMAKE_CURRENT_LIST_FILE} PATH)
get_filename_component(_moddir ${CMAKE_CURRENT_LIST_FILE} DIRECTORY)
configure_file("${_moddir}/${_boostConfig}"
"${CMAKE_CURRENT_BINARY_DIR}/BoostTestTargetConfig.h"
COPYONLY)
@@ -129,7 +135,7 @@ function(add_boost_test _name)
"Syntax error in use of add_boost_test: at least one source file required!")
endif()
if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
if(Boost_FOUND AND NOT "${Boost_VERSION_MACRO}0" LESS "1034000")
include_directories(${Boost_INCLUDE_DIRS})
@@ -157,7 +163,7 @@ function(add_boost_test _name)
endforeach()
if(NOT _boostTestTargetsNagged${_name} STREQUAL "${includeType}")
if("includeType" STREQUAL "CONFIGURED")
if("${includeType}" STREQUAL "CONFIGURED")
message(STATUS
"Test '${_name}' uses the CMake-configurable form of the boost test framework - congrats! (Including File: ${includeFileLoc})")
elseif("${includeType}" STREQUAL "INCLUDED")
@@ -221,7 +227,7 @@ function(add_boost_test _name)
set(_test_command ${_target_name})
endif()
if(TESTS AND ( "${Boost_VERSION}" VERSION_GREATER "103799" ))
if(TESTS AND ( "${Boost_VERSION_MACRO}" VERSION_GREATER "103799" ))
foreach(_test ${TESTS})
add_test(
${_name}-${_test}

View File

@@ -0,0 +1,30 @@
check_cxx_source_compiles("
#include <utility>
#include <type_traits>
std::make_index_sequence<0> t;
int main() {}" HAVE_STD_INDEX_SEQUENCE
)
check_cxx_source_compiles("
#include <type_traits>
std::remove_cv_t<const int> t;
int main() {}" HAVE_STD_REMOVE_CV_T
)
check_cxx_source_compiles("
#include <type_traits>
std::remove_cvref_t<const int&> t;
int main() {}" HAVE_STD_REMOVE_CVREF_T
)
check_cxx_source_compiles("
#include <type_traits>
std::enable_if_t<true, int> t;
int main() {}" HAVE_STD_ENABLE_IF_T
)
check_cxx_source_compiles("
#include <type_traits>
std::bool_constant<true> t;
int main() {}" HAVE_STD_BOOL_CONSTANT
)

View File

@@ -30,12 +30,12 @@ function(copy_resources_to_build_tree _target)
endif()
get_target_property(_path ${_target} LOCATION)
get_filename_component(_path "${_path}" PATH)
get_filename_component(_path "${_path}" DIRECTORY)
if(NOT MSVC AND NOT "${CMAKE_GENERATOR}" MATCHES "Makefiles")
foreach(_config ${CMAKE_CONFIGURATION_TYPES})
get_target_property(_path${_config} ${_target} LOCATION_${_config})
get_filename_component(_path${_config} "${_path${_config}}" PATH)
get_filename_component(_path${_config} "${_path${_config}}" DIRECTORY)
add_custom_command(TARGET ${_target}
POST_BUILD
COMMAND

View File

@@ -0,0 +1,37 @@
IF(CMAKE_SYSTEM_PROCESSOR MATCHES amd64.*|x86_64.* OR CMAKE_GENERATOR MATCHES "Visual Studio.*Win64")
IF(CMAKE_C_FLAGS MATCHES -m32 OR CMAKE_CXX_FLAGS MATCHES -m32)
SET(X86 1)
ELSE(CMAKE_C_FLAGS MATCHES -m32 OR CMAKE_CXX_FLAGS MATCHES -m32)
SET(X86_64 1)
ENDIF(CMAKE_C_FLAGS MATCHES -m32 OR CMAKE_CXX_FLAGS MATCHES -m32)
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES i686.*|i386.*|x86.* OR WIN32)
IF(CMAKE_C_FLAGS MATCHES -m64 OR CMAKE_CXX_FLAGS MATCHES -m64)
SET(X86_64 1)
ELSE(CMAKE_C_FLAGS MATCHES -m64 OR CMAKE_CXX_FLAGS MATCHES -m64)
SET(X86 1)
ENDIF(CMAKE_C_FLAGS MATCHES -m64 OR CMAKE_CXX_FLAGS MATCHES -m64)
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES arm.* AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(ARM 1)
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES mips)
SET(MIPS 1)
ENDIF()
IF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
# using Clang
SET(CLANG 1)
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "TinyCC")
# using TinyCC
SET(TINYCC 1)
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
# using GCC
SET(GCC 1)
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
SET(INTELCC 1)
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
SET(MSVC 1)
ELSEIF ("${CMAKE_C_COMPILER_ID}" STREQUAL "MIPSpro")
# using SGI MIPSpro
SET(MIPSPRO 1)
ENDIF()

View File

@@ -0,0 +1,26 @@
# placehodler target for other ones to depend upon
add_custom_target(
debug_symbols
)
function(export_debug_symbols target)
if (NOT SIMGEAR_SHARED)
return()
endif()
if (APPLE)
add_custom_target(${target}.dSYM
COMMENT "Generating dSYM files for ${target}"
COMMAND dsymutil --out=${target}.dSYM $<TARGET_FILE:${target}>
DEPENDS $<TARGET_FILE:${target}>
)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${target}.dSYM DESTINATION symbols OPTIONAL)
add_dependencies(debug_symbols ${target}.dSYM)
endif()
endfunction()

View File

@@ -1,48 +1,74 @@
# Locate AAX
# Try to find AAX (AeonWave)
# This module defines
# AAX_LIBRARIES
# AAX_FOUND, if false, do not try to link to AAX
# AAX_INCLUDE_DIR, where to find the headers
#
# AAX_FOUND - if false, do not try to link to AAX
# AAX_INCLUDE_DIR - where to find the headers
# AAX_LIBRARIES - Link these to use AAX
#
# Copyright (C) 2016-2018 by Erik Hofman.
# Copyright (C) 2016-2018 by Adalin B.V.
#
# $AAXDIR is an environment variable that would
# correspond to the ./configure --prefix=$AAXDIR
# used in building AAX.
#
# Created by Erik Hofman.
# This file is Public Domain (www.unlicense.org)
# This is free and unencumbered software released into the public domain.
FIND_PATH(AAX_INCLUDE_DIR aax/aeonwave.hpp
HINTS
$ENV{AAXDIR}
$ENV{ProgramFiles}/aax
$ENV{ProgramFiles}/AeonWave
$ENV{ProgramFiles}/Adalin/AeonWave
PATH_SUFFIXES include
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/opt
)
if (AAX_LIBRARY AND AAX_INCLUDE_DIR)
# in cache already
set(AAX_FOUND TRUE)
else()
find_path(AAX_INCLUDE_DIR aax/aax.h
HINTS
$ENV{AAXDIR}
$ENV{ProgramFiles}/aax
$ENV{ProgramFiles}/AeonWave
$ENV{ProgramFiles}/Adalin/AeonWave
${CMAKE_SOURCE_DIR}/aax
PATH_SUFFIXES include
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/opt
)
FIND_LIBRARY(AAX_LIBRARY
NAMES AAX aax AAX32 libAAX32
HINTS
$ENV{AAXDIR}
$ENV{ProgramFiles}/AAX
$ENV{ProgramFiles}/AeonWave
$ENV{ProgramFiles}/Adalin/AeonWave
PATH_SUFFIXES bin lib lib/${CMAKE_LIBRARY_ARCHITECTURE} lib64 libs64 libs libs/Win32 libs/Win64
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr
/opt
/usr/local
)
find_library(AAX_LIBRARY
NAMES AAX aax libAAX
HINTS
$ENV{AAXDIR}
$ENV{ProgramFiles}/AAX
$ENV{ProgramFiles}/AeonWave
$ENV{ProgramFiles}/Adalin/AeonWave
${CMAKE_BUILD_DIR}/aax
PATH_SUFFIXES lib64 lib lib/${CMAKE_LIBRARY_ARCHITECTURE} libs64 libs libs/Win32 libs/Win64 bin
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/opt
)
SET(AAX_FOUND "NO")
IF(AAX_LIBRARY AND AAX_INCLUDE_DIR)
SET(AAX_FOUND "YES")
ENDIF(AAX_LIBRARY AND AAX_INCLUDE_DIR)
set(AAX_DEFINITIONS "")
if (AAX_LIBRARY AND AAX_INCLUDE_DIR)
set(AAX_FOUND TRUE)
endif()
if (AAX_FOUND)
if (NOT Udns_FIND_QUIETLY)
message(STATUS "Found AeonWave: ${AAX_LIBRARIES}")
endif ()
else ()
if (Udns_FIND_REQUIRED)
message(FATAL_ERROR "Could not find AeonWave")
endif ()
endif ()
# show the AAX_INCLUDE_DIRS and AAX_LIBRARIES variables only in the advanced view
mark_as_advanced(AAX_INCLUDE_DIRS AAX_LIBRARIES)
endif()

View File

@@ -12,6 +12,11 @@ macro(simgear_component_common name includePath sourcesList sources headers)
set_property(GLOBAL
APPEND PROPERTY PUBLIC_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/${h}")
set(fh${sourcesList} "${fh${sourcesList}}#${CMAKE_CURRENT_SOURCE_DIR}/${h}")
# also append headers to the sources list, so that IDEs find the files
# correctly (otherwise they are not in the project)
set_property(GLOBAL
APPEND PROPERTY ${sourcesList} "${CMAKE_CURRENT_SOURCE_DIR}/${h}")
endforeach()
set_property(GLOBAL APPEND PROPERTY FG_GROUPS_${sourcesList}_C "${fc${sourcesList}}@")

568
Doxyfile

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,10 @@
documentation. It has a .cxx extension so that emacs will happily
autoindent correctly. */
/**
* \namespace simgear
* \brief \ref index "SimGear" main namespace.
*/
/** \mainpage SimGear
* Simulation, Visualization, and Game development libraries.

View File

@@ -1,20 +0,0 @@
[This file is mirrored in both the FlightGear and SimGear packages.]
You *must* have the development components of OpenAL installed on your system
to build FlightGear!" You can get a copy here:
http://connect.creativelabs.com/openal/default.aspx
Build notes:
You can download a versioned release of the openal library from
http://www.openal.org/downloads.html. Download the openal source,
release 0.0.8 (dated February 11, 2006) and run:
tar xjvf openal-soft-1.5.304.tar.bz2
cd openal-soft-1.5.304/
ccmake .
[ While running ccmake: press 'c' to configure, press 'c' once more, and
then press 'g' to generate and exit ]

39
README.sound Normal file
View File

@@ -0,0 +1,39 @@
[This file is mirrored in both the FlightGear and SimGear packages.]
For Sound support FlightGear requires one of the two following packages:
- OpenAL
- AeonWave
== OpenAL ===
You *must* have the development components of OpenAL installed on your system
to build FlightGear!" You can get a copy here:
http://connect.creativelabs.com/openal/default.aspx
Build notes:
You can download a versioned release of the openal library from
http://www.openal.org/downloads.html. Download the openal source,
release 0.0.8 (dated February 11, 2006) and run:
tar xjvf openal-soft-1.5.304.tar.bz2
cd openal-soft-1.5.304/
ccmake .
[ While running ccmake: press 'c' to configure, press 'c' once more, and
then press 'g' to generate and exit ]
== AeonWave ===
For FlightGear AeonWave has a number of advantages over OpenAL:
* Correct Doppler effect behavior
* Default distance attenuation frequency filtering
* Native support for 29 types of audio formats.
* Native support for wav, mp3, vorbis and raw file formats.
The source code of AeonWave can be found on GitHub:
https://github.com/adalinbv
Optimized binary packages are available at:
http://www.adalin.com/

View File

@@ -1,76 +0,0 @@
%define ver @VERSION@
%define rel 1
%define prefix /usr
Summary: Simulator Construction Gear.
Name: @PACKAGE@
Version: %ver
Release: %rel
Copyright: LGPL
Group: Libraries/Graphics
Source: %{name}-%{version}.tar.gz
#URL:
BuildRoot: /tmp/%{name}-%{version}-%{rel}-root
Packager: Fill In As You Wish
Docdir: %{prefix}/doc
%description
This package contains a tools and libraries useful for constructing
simulation and visualization applications such as FlightGear or TerraGear.
Authors:
N/A
%prep
%setup -n %{name}-%{version}
%build
# Needed for snapshot releases.
if [ ! -f configure ]; then
CFLAGS="$RPM_OPT_FLAGS" ./autogen.sh --prefix=%prefix
else
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=%prefix
fi
if [ "$SMP" != "" ]; then
JSMP = '"MAKE=make -k -j $SMP"'
fi
make ${JSMP};
%install
[ -d ${RPM_BUILD_ROOT} ] && rm -rf ${RPM_BUILD_ROOT}
make prefix=${RPM_BUILD_ROOT}%{prefix} install
#
# Generating file lists and store them in file-lists
# Starting with the directory listings
#
find ${RPM_BUILD_ROOT}%{prefix}/{bin,include,lib} -type d | sed "s#^${RPM_BUILD_ROOT}#\%attr (-\,root\,root) \%dir #" > file-lists
%{?ETCDR:find ${RPM_BUILD_ROOT}%{!?SYSCF:%{prefix}}/etc -type d | sed "s#^${RPM_BUILD_ROOT}#\%attr (-\,root\,root) \%dir #" >> file-lists}
#
# Then, the file listings
#
echo "%defattr (-, root, root)" >> file-lists
%{?ETCDR:find ${RPM_BUILD_ROOT}%{!?SYSCF:%{prefix}}/etc/%{name}.conf -type f | sed -e "s#^${RPM_BUILD_ROOT}#%config #g" >> file-lists}
find ${RPM_BUILD_ROOT}%{prefix} -type f | sed -e "s#^${RPM_BUILD_ROOT}##g" >> file-lists
%clean
(cd ..; rm -rf %{name}-%{version} ${RPM_BUILD_ROOT})
%files -f file-lists
%defattr (-, root, root)
%doc AUTHORS
%doc COPYING
%doc ChangeLog
%doc INSTALL
%doc NEWS
%doc README
%doc %{name}.spec.in

View File

@@ -7,10 +7,30 @@ find_dependency(Threads)
set(SIMGEAR_HEADLESS @SIMGEAR_HEADLESS@)
set(SIMGEAR_SOUND @ENABLE_SOUND@)
set(USE_AEONWAVE @USE_AEONWAVE@)
# OpenAL isn't a public dependency, so maybe not needed
#if (SIMGEAR_SOUND)
# find_dependency(OpenAL)
#endif()
# SSE/SSE2 support
set(ENABLE_SIMD @ENABLE_SIMD@)
# OpenRTI support
set(ENABLE_RTI @ENABLE_RTI@)
if(ENABLE_RTI)
set(RTI_FOUND @RTI_FOUND@)
if(RTI_FOUND)
set(RTI_INCLUDE_DIRS @RTI_INCLUDE_DIRS@)
set(RTI_LDFLAGS @RTI_LDFLAGS@)
endif(RTI_FOUND)
endif(ENABLE_RTI)
# Alternative terrain engine based on pagedLOD
set(ENABLE_GDAL @ENABLE_GDAL@)
set(ENABLE_OPENMP @ENABLE_OPENMP@)
include("${CMAKE_CURRENT_LIST_DIR}/SimGearTargets.cmake")

View File

@@ -1,13 +0,0 @@
Building a SimGear RPM package for Red Hat
Please see the "package/openSUSE" directory for an
example how to build a SimGear RPM package with
shared SimGear libraries.
You may need to adapt the names (exact spelling) of some
of the package dependencies in the openSUSE RPM spec,
since these may slightly differ for Red Hat.
(If you have a working and tested Red Hat RPM spec,
you're welcome to contribute it to this project.)

View File

@@ -1,23 +0,0 @@
Building a SimGear RPM package for openSUSE
(Last tested with openSUSE 11.4+12.1)
This directory contains the files which, along with
the source code tar files, can be used to build
an RPM package targeted at an openSUSE Linux system.
To build SimGear from source do the following:
1. obtain simgear-2.8.0.tar.bz2 (adapt version if
necessary) and copy it into ~/rpmbuild/SOURCES
2. look in the BuildRequires section of SimGear.spec
and check that all the packages referred to are
installed (note, some of these packages may be part
of openSUSE's "games" repository).
3. run 'rpmbuild -ba simgear.spec' and find the RPM
build result in ~/rpmbuild/RPMS
That's all!

View File

@@ -1,63 +0,0 @@
Summary: Simulator Construction Gear
Name: SimGear
Version: 2.8.0
Release: 1
License: LGPL
URL: http://www.flightgear.org
Group: Amusements/Games/3D/Simulation
Source: http://mirrors.ibiblio.org/pub/mirrors/flightgear/ftp/Source/simgear-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: gcc, gcc-c++, cmake
BuildRequires: libopenal1-soft, openal-soft
BuildRequires: libOpenSceneGraph-devel >= 3.0
BuildRequires: zlib, zlib-devel
BuildRequires: libjpeg62, libjpeg62-devel
BuildRequires: boost-devel >= 1.37
BuildRequires: subversion-devel, libapr1-devel
Requires: OpenSceneGraph-plugins >= 3.0
%description
This package contains a tools and libraries useful for constructing
simulation and visualization applications such as FlightGear or TerraGear.
%package devel
Group: Development/Libraries/Other
Summary: Development header files for SimGear
Requires: SimGear = %{version}
%description devel
Development headers and libraries for building applications against SimGear.
%prep
%setup -T -q -n simgear-%{version} -b 0
%build
export CFLAGS="$RPM_OPT_FLAGS"
export CXXFLAGS="$RPM_OPT_FLAGS"
# build SHARED simgear libraries
cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} -DSIMGEAR_SHARED:BOOL=ON -DENABLE_TESTS:BOOL=OFF -DJPEG_FACTORY:BOOL=ON
make %{?_smp_mflags}
%install
make DESTDIR=%{buildroot} install
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr (-, root, root, -)
%doc AUTHORS COPYING ChangeLog NEWS README
%{_libdir}/libSimGear*.so.*
%files devel
%defattr(-,root,root,-)
%dir %{_includedir}/simgear
%{_includedir}/simgear/*
%{_libdir}/libSimGear*.so
%changelog
* Mon Jul 02 2012 thorstenb@flightgear.org
- Initial version

View File

@@ -5,6 +5,8 @@ foreach( mylibfolder
bucket
bvh
debug
embedded_resources
emesary
ephemeris
io
magvar
@@ -14,6 +16,7 @@ foreach( mylibfolder
nasal/cppbind
props
serial
std
structure
threads
timing
@@ -54,24 +57,17 @@ if(SIMGEAR_SHARED)
set_property(TARGET SimGearCore PROPERTY LINKER_LANGUAGE CXX)
set_property(TARGET SimGearCore PROPERTY VERSION ${SIMGEAR_VERSION})
set_property(TARGET SimGearCore PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
install(TARGETS SimGearCore
EXPORT SimGearTargets
LIBRARY DESTINATION
${CMAKE_INSTALL_LIBDIR})
if(NOT SIMGEAR_HEADLESS)
add_library(SimGearScene SHARED ${sceneSources})
set_property(TARGET SimGearScene PROPERTY LINKER_LANGUAGE CXX)
set_property(TARGET SimGearScene PROPERTY VERSION ${SIMGEAR_VERSION})
set_property(TARGET SimGearScene PROPERTY SOVERSION ${SIMGEAR_SOVERSION})
# EXPORT SimGearSceneConfig
install(TARGETS SimGearScene
EXPORT SimGearTargets
LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR} )
endif()
export_debug_symbols(SimGearCore)
export_debug_symbols(SimGearScene)
else()
message(STATUS "Library building mode: STATIC LIBRARIES")
@@ -94,9 +90,6 @@ else()
endforeach()
add_library(SimGearCore STATIC ${coreSources} ${localExpatSources})
install(TARGETS SimGearCore
EXPORT SimGearTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(NOT SIMGEAR_HEADLESS)
get_property(FG_GROUPS_SCENE_SOURCES_C GLOBAL PROPERTY FG_GROUPS_SCENE_SOURCES_C)
@@ -118,38 +111,92 @@ else()
endforeach()
add_library(SimGearScene STATIC ${sceneSources})
install(TARGETS SimGearScene
EXPORT SimGearTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif(NOT SIMGEAR_HEADLESS)
endif(SIMGEAR_SHARED)
target_link_libraries(SimGearCore
${ZLIB_LIBRARY}
target_include_directories(SimGearCore BEFORE PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
# so simgear/simgear_config.h is found
target_include_directories(SimGearCore BEFORE PUBLIC
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>)
target_include_directories(SimGearCore PUBLIC
${Boost_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR})
target_include_directories(SimGearCore PRIVATE
${EXPAT_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS})
if (NOT SYSTEM_EXPAT)
# XML_STATIC is important to avoid sg_expat_external.h
# declaring symbols as declspec(import)
target_compile_definitions(SimGearCore PRIVATE HAVE_SIMGEAR_EXPAT_CONFIG_H XML_STATIC)
endif()
install(TARGETS SimGearCore
EXPORT SimGearTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if (NOT SIMGEAR_HEADLESS)
install(TARGETS SimGearScene
EXPORT SimGearTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
target_include_directories(SimGearScene BEFORE PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
target_include_directories(SimGearScene PUBLIC ${OPENSCENEGRAPH_INCLUDE_DIRS})
if (USE_AEONWAVE)
target_include_directories(SimGearScene PRIVATE ${AAX_INCLUDE_DIR} )
else()
target_include_directories(SimGearScene PRIVATE ${OPENAL_INCLUDE_DIR} )
endif()
endif()
# we expose ZLib in some of our headers
target_link_libraries(SimGearCore PUBLIC ${ZLIB_LIBRARY})
target_link_libraries(SimGearCore PRIVATE
${RT_LIBRARY}
${DL_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${COCOA_LIBRARY}
${CURL_LIBRARIES})
${CURL_LIBRARIES}
${WINSOCK_LIBRARY})
if(SYSTEM_EXPAT)
target_link_libraries(SimGearCore
${EXPAT_LIBRARIES})
target_link_libraries(SimGearCore PRIVATE ${EXPAT_LIBRARIES})
endif()
if(ENABLE_DNS AND SYSTEM_UDNS)
target_link_libraries(SimGearCore
${UDNS_LIBRARIES})
target_link_libraries(SimGearCore PRIVATE ${UDNS_LIBRARIES})
endif()
if(NOT SIMGEAR_HEADLESS)
target_link_libraries(SimGearScene
target_include_directories(SimGearScene PRIVATE ${PROJECT_SOURCE_DIR}/simgear/canvas/ShivaVG/include)
target_link_libraries(SimGearScene PUBLIC
SimGearCore
${ZLIB_LIBRARY}
${OPENSCENEGRAPH_LIBRARIES}
)
target_link_libraries(SimGearScene PRIVATE
${ZLIB_LIBRARY}
${OPENAL_LIBRARY}
${OPENGL_LIBRARY}
${JPEG_LIBRARY})
if(ENABLE_GDAL)
target_link_libraries(SimGearScene PRIVATE ${GDAL_LIBRARIES})
endif()
# only actually needed by canvas/KeyboardEvent.cxx
target_include_directories(SimGearScene PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/utf8/source)
endif()
if(ENABLE_RTI)
@@ -157,5 +204,5 @@ if(ENABLE_RTI)
set_property(SOURCE hla/RTI13InteractionClass.cxx hla/RTI13ObjectClass.cxx
hla/RTI13ObjectInstance.cxx hla/RTI13Federate.cxx
hla/RTI13FederateFactory.cxx
APPEND PROPERTY COMPILE_FLAGS "-I${RTI_INCLUDE_DIR}")
APPEND PROPERTY COMPILE_FLAGS "-I${RTI_INCLUDE_DIRS}")
endif(ENABLE_RTI)

View File

@@ -35,124 +35,152 @@ using std::endl;
void testBucketSpans()
{
COMPARE(sg_bucket_span(0.0), 0.125);
COMPARE(sg_bucket_span(-20), 0.125);
COMPARE(sg_bucket_span(-40), 0.25);
COMPARE(sg_bucket_span(89.9), 12.0);
COMPARE(sg_bucket_span(88.1), 4.0);
COMPARE(sg_bucket_span(-89.9), 12.0);
SG_CHECK_EQUAL(sg_bucket_span(0.0), 0.125);
SG_CHECK_EQUAL(sg_bucket_span(-20), 0.125);
SG_CHECK_EQUAL(sg_bucket_span(-40), 0.25);
SG_CHECK_EQUAL(sg_bucket_span(89.9), 12.0);
SG_CHECK_EQUAL(sg_bucket_span(88.1), 4.0);
SG_CHECK_EQUAL(sg_bucket_span(-89.9), 12.0);
}
void testBasic()
{
SGBucket b1(5.1, 55.05);
COMPARE(b1.get_chunk_lon(), 5);
COMPARE(b1.get_chunk_lat(), 55);
COMPARE(b1.get_x(), 0);
COMPARE(b1.get_y(), 0);
COMPARE(b1.gen_index(), 3040320);
COMPARE(b1.gen_base_path(), "e000n50/e005n55");
VERIFY(b1.isValid());
SG_CHECK_EQUAL(b1.get_chunk_lon(), 5);
SG_CHECK_EQUAL(b1.get_chunk_lat(), 55);
SG_CHECK_EQUAL(b1.get_x(), 0);
SG_CHECK_EQUAL(b1.get_y(), 0);
SG_CHECK_EQUAL(b1.gen_index(), 3040320);
SG_CHECK_EQUAL(b1.gen_base_path(), "e000n50/e005n55");
SG_VERIFY(b1.isValid());
SGBucket b2(-10.1, -43.8);
COMPARE(b2.get_chunk_lon(), -11);
COMPARE(b2.get_chunk_lat(), -44);
COMPARE(b2.get_x(), 3);
COMPARE(b2.get_y(), 1); // latitude chunks numbered bottom to top, it seems
COMPARE(b2.gen_base_path(), "w020s50/w011s44");
VERIFY(b2.isValid());
SG_CHECK_EQUAL(b2.get_chunk_lon(), -11);
SG_CHECK_EQUAL(b2.get_chunk_lat(), -44);
SG_CHECK_EQUAL(b2.get_x(), 3);
// Latitude chunks numbered bottom to top, it seems
SG_CHECK_EQUAL(b2.get_y(), 1);
SG_CHECK_EQUAL(b2.gen_base_path(), "w020s50/w011s44");
SG_VERIFY(b2.isValid());
SGBucket b3(123.48, 9.01);
COMPARE(b3.get_chunk_lon(), 123);
COMPARE(b3.get_chunk_lat(), 9);
COMPARE(b3.get_x(), 3);
COMPARE(b3.get_y(), 0);
COMPARE(b3.gen_base_path(), "e120n00/e123n09");
VERIFY(b3.isValid());
SG_CHECK_EQUAL(b3.get_chunk_lon(), 123);
SG_CHECK_EQUAL(b3.get_chunk_lat(), 9);
SG_CHECK_EQUAL(b3.get_x(), 3);
SG_CHECK_EQUAL(b3.get_y(), 0);
SG_CHECK_EQUAL(b3.gen_base_path(), "e120n00/e123n09");
SG_VERIFY(b3.isValid());
SGBucket defBuck;
VERIFY(!defBuck.isValid());
SG_VERIFY(!defBuck.isValid());
b3.make_bad();
VERIFY(!b3.isValid());
SG_VERIFY(!b3.isValid());
SGBucket atAntiMeridian(180.0, 12.3);
VERIFY(atAntiMeridian.isValid());
COMPARE(atAntiMeridian.get_chunk_lon(), -180);
COMPARE(atAntiMeridian.get_x(), 0);
SG_VERIFY(atAntiMeridian.isValid());
SG_CHECK_EQUAL(atAntiMeridian.get_chunk_lon(), -180);
SG_CHECK_EQUAL(atAntiMeridian.get_x(), 0);
SGBucket atAntiMeridian2(-180.0, -78.1);
VERIFY(atAntiMeridian2.isValid());
COMPARE(atAntiMeridian2.get_chunk_lon(), -180);
COMPARE(atAntiMeridian2.get_x(), 0);
// check comparisom operator overload
SG_VERIFY(atAntiMeridian2.isValid());
SG_CHECK_EQUAL(atAntiMeridian2.get_chunk_lon(), -180);
SG_CHECK_EQUAL(atAntiMeridian2.get_x(), 0);
// check comparison operator overload
SGBucket b4(5.11, 55.1);
VERIFY(b1 == b4); // should be equal
VERIFY(b1 == b1);
VERIFY(b1 != defBuck);
VERIFY(b1 != b2);
// check wrapping/clipping of inputs
SG_VERIFY(b1 == b4); // should be equal
SG_VERIFY(b1 == b1);
SG_VERIFY(b1 != defBuck);
SG_VERIFY(b1 != b2);
// check wrapping/clipping of inputs
SGBucket wrapMeridian(-200.0, 45.0);
COMPARE(wrapMeridian.get_chunk_lon(), 160);
SG_CHECK_EQUAL(wrapMeridian.get_chunk_lon(), 160);
SGBucket clipPole(48.9, 91);
COMPARE(clipPole.get_chunk_lat(), 89);
SG_CHECK_EQUAL(clipPole.get_chunk_lat(), 89);
// test override of a bucket's geod
auto geod = SGGeod::fromDegFt(-86.678, 36.1248, 599.0);
#ifndef NO_DEPRECATED_API
SGBucket bna_airport;
bna_airport.set_bucket(geod);
#else
SGBucket bna_airport(geod);
#endif
SG_VERIFY(bna_airport.isValid());
SG_CHECK_EQUAL(bna_airport.get_chunk_lon(), -87); // left origin of the 1-degree chunk
SG_CHECK_EQUAL(bna_airport.get_chunk_lat(), 36); // bottom origin of the 1-degree chunk
SG_CHECK_EQUAL(bna_airport.get_x(), 1); // buckets are 0.25 deg wide at the W87 parallel
// we're 0.322 deg from the origin (second bucket)
SG_CHECK_EQUAL(bna_airport.get_y(), 0); // buckets are always 0.125 deg tall
// we're 0.1248 deg from the origin (first bucket)
SG_CHECK_EQUAL(bna_airport.gen_base_path(), "w090n30/w087n36");
SG_CHECK_EQUAL_EP2(bna_airport.get_width_m(), 22479.1, 0.1);
SG_CHECK_EQUAL_EP2(bna_airport.get_height_m(), 13914.9, 0.1);
SG_CHECK_EQUAL(bna_airport.gen_index_str(), "1531777"); // 0x175F81 = b01011101|01111110|000|001
// = 93-180 | 126-90 | 0 | 1
// = -87 | 36 | 0 | 1
// test stream output
cout << "[TEST] BNA Airport: " << bna_airport << endl;
auto center = bna_airport.get_center();
cout << "[TEST] BNA lon: " << center.getLongitudeDeg() << endl;
cout << "[TEST] BNA lat: " << center.getLatitudeDeg() << endl;
}
void testPolar()
{
SGBucket b1(0.0, 89.92);
SGBucket b2(10.0, 89.96);
COMPARE(b1.get_chunk_lat(), 89);
COMPARE(b1.get_chunk_lon(), 0);
COMPARE(b1.get_x(), 0);
COMPARE(b1.get_y(), 7);
COMPARE_EP(b1.get_highest_lat(), 90.0);
COMPARE_EP(b1.get_width_m(), 10.0);
COMPARE(b2.get_chunk_lat(), 89);
COMPARE(b2.get_chunk_lon(), 0);
COMPARE(b2.get_x(), 0);
COMPARE(b2.get_y(), 7);
COMPARE(b1.gen_index(), b2.gen_index());
SG_CHECK_EQUAL(b1.get_chunk_lat(), 89);
SG_CHECK_EQUAL(b1.get_chunk_lon(), 0);
SG_CHECK_EQUAL(b1.get_x(), 0);
SG_CHECK_EQUAL(b1.get_y(), 7);
SG_CHECK_EQUAL_EP(b1.get_highest_lat(), 90.0);
SG_CHECK_EQUAL_EP(b1.get_width_m(), 10.0);
SG_CHECK_EQUAL(b2.get_chunk_lat(), 89);
SG_CHECK_EQUAL(b2.get_chunk_lon(), 0);
SG_CHECK_EQUAL(b2.get_x(), 0);
SG_CHECK_EQUAL(b2.get_y(), 7);
SG_CHECK_EQUAL(b1.gen_index(), b2.gen_index());
SGGeod actualNorthPole1 = b1.get_corner(2);
SGGeod actualNorthPole2 = b1.get_corner(3);
COMPARE_EP(actualNorthPole1.getLatitudeDeg(), 90.0);
COMPARE_EP(actualNorthPole1.getLongitudeDeg(), 12.0);
COMPARE_EP(actualNorthPole2.getLatitudeDeg(), 90.0);
COMPARE_EP(actualNorthPole2.getLongitudeDeg(), 0.0);
SG_CHECK_EQUAL_EP(actualNorthPole1.getLatitudeDeg(), 90.0);
SG_CHECK_EQUAL_EP(actualNorthPole1.getLongitudeDeg(), 12.0);
SG_CHECK_EQUAL_EP(actualNorthPole2.getLatitudeDeg(), 90.0);
SG_CHECK_EQUAL_EP(actualNorthPole2.getLongitudeDeg(), 0.0);
SGBucket b3(-2, 89.88);
SGBucket b4(-7, 89.88);
COMPARE(b3.gen_index(), b4.gen_index());
SG_CHECK_EQUAL(b3.gen_index(), b4.gen_index());
// south pole
SGBucket b5(-170, -89.88);
SGBucket b6(-179, -89.88);
COMPARE(b5.get_chunk_lat(), -90);
COMPARE(b5.get_chunk_lon(), -180);
COMPARE(b5.get_x(), 0);
COMPARE(b5.get_y(), 0);
COMPARE(b5.gen_index(), b6.gen_index());
COMPARE_EP(b5.get_highest_lat(), -90.0);
COMPARE_EP(b5.get_width_m(), 10.0);
SG_CHECK_EQUAL(b5.get_chunk_lat(), -90);
SG_CHECK_EQUAL(b5.get_chunk_lon(), -180);
SG_CHECK_EQUAL(b5.get_x(), 0);
SG_CHECK_EQUAL(b5.get_y(), 0);
SG_CHECK_EQUAL(b5.gen_index(), b6.gen_index());
SG_CHECK_EQUAL_EP(b5.get_highest_lat(), -90.0);
SG_CHECK_EQUAL_EP(b5.get_width_m(), 10.0);
SGGeod actualSouthPole1 = b5.get_corner(0);
SGGeod actualSouthPole2 = b5.get_corner(1);
COMPARE_EP(actualSouthPole1.getLatitudeDeg(), -90.0);
COMPARE_EP(actualSouthPole1.getLongitudeDeg(), -180);
COMPARE_EP(actualSouthPole2.getLatitudeDeg(), -90.0);
COMPARE_EP(actualSouthPole2.getLongitudeDeg(), -168);
SGBucket b7(200, 89.88);
COMPARE(b7.get_chunk_lon(), -168);
SG_CHECK_EQUAL_EP(actualSouthPole1.getLatitudeDeg(), -90.0);
SG_CHECK_EQUAL_EP(actualSouthPole1.getLongitudeDeg(), -180);
SG_CHECK_EQUAL_EP(actualSouthPole2.getLatitudeDeg(), -90.0);
SG_CHECK_EQUAL_EP(actualSouthPole2.getLongitudeDeg(), -168);
SGBucket b7(200, 89.88);
SG_CHECK_EQUAL(b7.get_chunk_lon(), -168);
}
// test the tiles just below the pole (between 86 & 89 degrees N/S)
@@ -160,15 +188,15 @@ void testNearPolar()
{
SGBucket b1(1, 88.5);
SGBucket b2(-1, 88.8);
COMPARE(b1.get_chunk_lon(), 0);
COMPARE(b1.get_chunk_lat(), 88);
VERIFY(b1.gen_index() != b2.gen_index());
SG_CHECK_EQUAL(b1.get_chunk_lon(), 0);
SG_CHECK_EQUAL(b1.get_chunk_lat(), 88);
SG_VERIFY(b1.gen_index() != b2.gen_index());
SGBucket b3(176.1, 88.5);
COMPARE(b3.get_chunk_lon(), 176);
SG_CHECK_EQUAL(b3.get_chunk_lon(), 176);
SGBucket b4(-178, 88.5);
COMPARE(b4.get_chunk_lon(), -180);
SG_CHECK_EQUAL(b4.get_chunk_lon(), -180);
}
void testOffset()
@@ -176,74 +204,74 @@ void testOffset()
// bucket just below the 22 degree cutoff, so the next tile north
// is twice the width
SGBucket b1(-59.8, 21.9);
COMPARE(b1.get_chunk_lat(), 21);
COMPARE(b1.get_chunk_lon(), -60);
COMPARE(b1.get_x(), 1);
COMPARE(b1.get_y(), 7);
SG_CHECK_EQUAL(b1.get_chunk_lat(), 21);
SG_CHECK_EQUAL(b1.get_chunk_lon(), -60);
SG_CHECK_EQUAL(b1.get_x(), 1);
SG_CHECK_EQUAL(b1.get_y(), 7);
// offset vertically
SGBucket b2(b1.sibling(0, 1));
COMPARE(b2.get_chunk_lat(), 22);
COMPARE(b2.get_chunk_lon(), -60);
COMPARE(b2.get_x(), 0);
COMPARE(b2.get_y(), 0);
SG_CHECK_EQUAL(b2.get_chunk_lat(), 22);
SG_CHECK_EQUAL(b2.get_chunk_lon(), -60);
SG_CHECK_EQUAL(b2.get_x(), 0);
SG_CHECK_EQUAL(b2.get_y(), 0);
SG_CHECK_EQUAL(b2.gen_index(), sgBucketOffset(-59.8, 21.9, 0, 1));
COMPARE(b2.gen_index(), sgBucketOffset(-59.8, 21.9, 0, 1));
// offset vertically and horizontally. We compute horizontal (x)
// movement at the target latitude, so this should move 0.25 * -3 degrees,
// NOT 0.125 * -3 degrees.
SGBucket b3(b1.sibling(-3, 1));
COMPARE(b3.get_chunk_lat(), 22);
COMPARE(b3.get_chunk_lon(), -61);
COMPARE(b3.get_x(), 1);
COMPARE(b3.get_y(), 0);
COMPARE(b3.gen_index(), sgBucketOffset(-59.8, 21.9, -3, 1));
SG_CHECK_EQUAL(b3.get_chunk_lat(), 22);
SG_CHECK_EQUAL(b3.get_chunk_lon(), -61);
SG_CHECK_EQUAL(b3.get_x(), 1);
SG_CHECK_EQUAL(b3.get_y(), 0);
SG_CHECK_EQUAL(b3.gen_index(), sgBucketOffset(-59.8, 21.9, -3, 1));
}
void testPolarOffset()
{
SGBucket b1(-11.7, -89.6);
COMPARE(b1.get_chunk_lat(), -90);
COMPARE(b1.get_chunk_lon(), -12);
COMPARE(b1.get_x(), 0);
COMPARE(b1.get_y(), 3);
SG_CHECK_EQUAL(b1.get_chunk_lat(), -90);
SG_CHECK_EQUAL(b1.get_chunk_lon(), -12);
SG_CHECK_EQUAL(b1.get_x(), 0);
SG_CHECK_EQUAL(b1.get_y(), 3);
// offset horizontally
SGBucket b2(b1.sibling(-2, 0));
COMPARE(b2.get_chunk_lat(), -90);
COMPARE(b2.get_chunk_lon(), -36);
COMPARE(b2.get_x(), 0);
COMPARE(b2.get_y(), 3);
COMPARE(b2.gen_index(), sgBucketOffset(-11.7, -89.6, -2, 0));
// offset and wrap
SG_CHECK_EQUAL(b2.get_chunk_lat(), -90);
SG_CHECK_EQUAL(b2.get_chunk_lon(), -36);
SG_CHECK_EQUAL(b2.get_x(), 0);
SG_CHECK_EQUAL(b2.get_y(), 3);
SG_CHECK_EQUAL(b2.gen_index(), sgBucketOffset(-11.7, -89.6, -2, 0));
// offset and wrap
SGBucket b3(-170, 89.1);
SGBucket b4(b3.sibling(-1, 0));
COMPARE(b4.get_chunk_lat(), 89);
COMPARE(b4.get_chunk_lon(), 168);
COMPARE(b4.get_x(), 0);
COMPARE(b4.get_y(), 0);
COMPARE(b4.gen_index(), sgBucketOffset(-170, 89.1, -1, 0));
SG_CHECK_EQUAL(b4.get_chunk_lat(), 89);
SG_CHECK_EQUAL(b4.get_chunk_lon(), 168);
SG_CHECK_EQUAL(b4.get_x(), 0);
SG_CHECK_EQUAL(b4.get_y(), 0);
SG_CHECK_EQUAL(b4.gen_index(), sgBucketOffset(-170, 89.1, -1, 0));
SGBucket b5(177, 87.3);
SGBucket b6(b5.sibling(1, 1));
COMPARE(b6.get_chunk_lat(), 87);
COMPARE(b6.get_chunk_lon(), -180);
COMPARE(b6.get_x(), 0);
COMPARE(b6.get_y(), 3);
COMPARE(b6.gen_index(), sgBucketOffset(177, 87.3, 1, 1));
SG_CHECK_EQUAL(b6.get_chunk_lat(), 87);
SG_CHECK_EQUAL(b6.get_chunk_lon(), -180);
SG_CHECK_EQUAL(b6.get_x(), 0);
SG_CHECK_EQUAL(b6.get_y(), 3);
SG_CHECK_EQUAL(b6.gen_index(), sgBucketOffset(177, 87.3, 1, 1));
// offset vertically towards the pole
SGBucket b7(b1.sibling(0, -5));
VERIFY(!b7.isValid());
VERIFY(!SGBucket(0, 90).sibling(0, 1).isValid());
SG_VERIFY(!b7.isValid());
SG_VERIFY(!SGBucket(0, 90).sibling(0, 1).isValid());
}
// test behaviour of bucket-offset near the anti-meridian (180-meridian)
@@ -251,33 +279,84 @@ void testOffsetWrap()
{
// near the equator
SGBucket b1(-179.8, 16.8);
COMPARE(b1.get_chunk_lat(), 16);
COMPARE(b1.get_chunk_lon(), -180);
COMPARE(b1.get_x(), 1);
COMPARE(b1.get_y(), 6);
SG_CHECK_EQUAL(b1.get_chunk_lat(), 16);
SG_CHECK_EQUAL(b1.get_chunk_lon(), -180);
SG_CHECK_EQUAL(b1.get_x(), 1);
SG_CHECK_EQUAL(b1.get_y(), 6);
SGBucket b2(b1.sibling(-2, 0));
COMPARE(b2.get_chunk_lat(), 16);
COMPARE(b2.get_chunk_lon(), 179);
COMPARE(b2.get_x(), 7);
COMPARE(b2.get_y(), 6);
COMPARE(b2.gen_index(), sgBucketOffset(-179.8, 16.8, -2, 0));
SG_CHECK_EQUAL(b2.get_chunk_lat(), 16);
SG_CHECK_EQUAL(b2.get_chunk_lon(), 179);
SG_CHECK_EQUAL(b2.get_x(), 7);
SG_CHECK_EQUAL(b2.get_y(), 6);
SG_CHECK_EQUAL(b2.gen_index(), sgBucketOffset(-179.8, 16.8, -2, 0));
}
void testSiblings()
{
SGBucket bna_airport(-86.678, 36.1248);
SG_VERIFY(bna_airport.isValid());
// retrieve the sibling two positions north-east of my position
auto sib1 = bna_airport.sibling(2, 2);
SG_CHECK_EQUAL(sib1.get_chunk_lon(), bna_airport.get_chunk_lon());
SG_CHECK_EQUAL(sib1.get_chunk_lat(), bna_airport.get_chunk_lat());
SG_CHECK_EQUAL(sib1.get_x(), 3); // my x-pos (1) + 2 = 3
SG_CHECK_EQUAL(sib1.get_y(), 2); // my y-pos (0) + 2 = 2
SG_CHECK_EQUAL(sib1.gen_base_path(), bna_airport.gen_base_path());
// retrieve the one sibling two positions to the north-east
std::vector<SGBucket> siblings;
bna_airport.siblings(2, 2, siblings);
SG_CHECK_EQUAL(siblings.size(), static_cast<std::vector<SGBucket>::size_type>(1));
siblings.clear();
// retrieve the one sibling at the chunk origin of sib1
sib1.siblings(-2, -2, siblings);
SG_CHECK_EQUAL(siblings.size(), static_cast<std::vector<SGBucket>::size_type>(1));
siblings.clear();
// calculate delta between two buckets
int dx = 0;
int dy = 0;
sgBucketDiff(bna_airport, sib1, &dx, &dy);
SG_CHECK_EQUAL(dx, 2);
SG_CHECK_EQUAL(dy, 2);
// retrieve all siblings between two geodetic locations
auto geod_bna = SGGeod::fromDegFt(-86.678, 36.1248, 599.0);
auto geod_m54 = SGGeod::fromDegFt(-86.317, 36.1908, 122.0);
sgGetBuckets(geod_bna, geod_m54, siblings);
SG_CHECK_EQUAL(siblings.size(), static_cast<std::vector<SGBucket>::size_type>(4));
siblings.clear();
// edge cases
// ensure you cannot retrieve the sibling of an invalid bucket
SGBucket bad;
auto bad_sib = bad.sibling(1, 1);
SG_CHECK_EQUAL(bad_sib.get_chunk_lon(), -1000);
SG_CHECK_EQUAL(bad.siblings(2, 2, siblings), 0);
// if we drop below the 22nd parallel, the bucket widths are half the size
// expect this to retrieve two buckets
bna_airport.siblings(0, -160, siblings);
SG_CHECK_EQUAL(siblings.size(), static_cast<std::vector<SGBucket>::size_type>(2));
siblings.clear();
}
int main(int argc, char* argv[])
{
testBucketSpans();
testBasic();
testPolar();
testNearPolar();
testOffset();
testOffsetWrap();
testPolarOffset();
testSiblings();
cout << "all tests passed OK" << endl;
return 0; // passed
}

View File

@@ -15,6 +15,8 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear_config.h>
#include "BVHMaterial.hxx"
namespace simgear {

View File

@@ -15,6 +15,8 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear_config.h>
#include "BVHPageNode.hxx"
#include "BVHPager.hxx"

View File

@@ -15,6 +15,8 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear_config.h>
#include "BVHPageRequest.hxx"
namespace simgear {

View File

@@ -15,12 +15,14 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear_config.h>
#include "BVHPager.hxx"
#include <list>
#include <mutex>
#include <simgear/threads/SGThread.hxx>
#include <simgear/threads/SGGuard.hxx>
#include "BVHPageNode.hxx"
#include "BVHPageRequest.hxx"
@@ -35,12 +37,12 @@ struct BVHPager::_PrivateData : protected SGThread {
struct _LockedQueue {
void _push(const _Request& request)
{
SGGuard<SGMutex> scopeLock(_mutex);
std::lock_guard<std::mutex> scopeLock(_mutex);
_requestList.push_back(request);
}
_Request _pop()
{
SGGuard<SGMutex> scopeLock(_mutex);
std::lock_guard<std::mutex> scopeLock(_mutex);
if (_requestList.empty())
return _Request();
_Request request;
@@ -49,7 +51,7 @@ struct BVHPager::_PrivateData : protected SGThread {
return request;
}
private:
SGMutex _mutex;
std::mutex _mutex;
_RequestList _requestList;
};
@@ -60,7 +62,7 @@ struct BVHPager::_PrivateData : protected SGThread {
}
void _push(const _Request& request)
{
SGGuard<SGMutex> scopeLock(_mutex);
std::lock_guard<std::mutex> scopeLock(_mutex);
bool needSignal = _requestList.empty();
_requestList.push_back(request);
if (needSignal)
@@ -68,7 +70,7 @@ struct BVHPager::_PrivateData : protected SGThread {
}
_Request _pop()
{
SGGuard<SGMutex> scopeLock(_mutex);
std::lock_guard<std::mutex> scopeLock(_mutex);
while (_requestList.empty())
_waitCondition.wait(_mutex);
_Request request;
@@ -77,7 +79,7 @@ struct BVHPager::_PrivateData : protected SGThread {
return request;
}
private:
SGMutex _mutex;
std::mutex _mutex;
SGWaitCondition _waitCondition;
_RequestList _requestList;
};

View File

@@ -15,6 +15,8 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear_config.h>
#include "BVHStaticNode.hxx"
namespace simgear {

View File

@@ -15,6 +15,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
#include <simgear_config.h>
#include <iostream>
#include <simgear/structure/SGSharedPtr.hxx>

View File

@@ -1,4 +1,5 @@
// The canvas for rendering with the 2d API
///@file
/// The canvas for rendering with the 2d API
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,12 +17,16 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "Canvas.hxx"
#include "CanvasEventManager.hxx"
#include "CanvasEventVisitor.hxx"
#include "CanvasPlacement.hxx"
#include <simgear/canvas/events/KeyboardEvent.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/scene/util/RenderConstants.hxx>
@@ -30,13 +35,79 @@
#include <osgText/Text>
#include <osgViewer/Viewer>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
namespace simgear
{
namespace canvas
{
static int globalinstanceid = 1;
/**
* Camera Callback for moving completed canvas images to subscribed listener.
*/
class CanvasImageCallback : public osg::Camera::DrawCallback {
public:
osg::Image *_rawImage;
CanvasImageCallback(osg::Image *rawImage)
: _min_delta_tick(1.0 / 8.0) {
_previousFrameTick = osg::Timer::instance()->tick();
_rawImage = rawImage;
SG_LOG(SG_GENERAL,SG_INFO,"CanvasImageCallback created. instance is " << instanceid);
}
virtual void operator()(osg::RenderInfo& renderInfo) const {
osg::Timer_t n = osg::Timer::instance()->tick();
double dt = osg::Timer::instance()->delta_s(_previousFrameTick, n);
if (dt < _min_delta_tick)
return;
_previousFrameTick = n;
SG_LOG(SG_GENERAL,SG_DEBUG,"CanvasImageCallback " << instanceid << ": image available for " << _subscribers.size() << " subscribers. camera is " << renderInfo.getCurrentCamera());
bool hasSubscribers = false;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
hasSubscribers = !_subscribers.empty();
}
if (hasSubscribers) {
//Make sure image can be overwritten by next frame while it is still returned to the client
osg::Image* image = new osg::Image(*_rawImage, osg::CopyOp::DEEP_COPY_ALL);
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
while (!_subscribers.empty()) {
try {
CanvasImageReadyListener *subs = _subscribers.back();
if (subs){
subs->imageReady(image);
}else{
SG_LOG(SG_GENERAL,SG_WARN,"CanvasImageCallback subscriber null");
}
} catch (...) { }
_subscribers.pop_back();
}
}
}
}
void subscribe(CanvasImageReadyListener * subscriber) {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
_subscribers.push_back(subscriber);
}
void unsubscribe(CanvasImageReadyListener * subscriber) {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_lock);
_subscribers.remove(subscriber);
}
int getSubscriberCount() {
return _subscribers.size();
}
private:
mutable list<CanvasImageReadyListener*> _subscribers;
mutable OpenThreads::Mutex _lock;
mutable double _previousFrameTick;
double _min_delta_tick;
int instanceid = globalinstanceid++;
};
//----------------------------------------------------------------------------
Canvas::CullCallback::CullCallback(const CanvasWeakPtr& canvas):
@@ -62,18 +133,9 @@ namespace canvas
//----------------------------------------------------------------------------
Canvas::Canvas(SGPropertyNode* node):
PropertyBasedElement(node),
_canvas_mgr(0),
_event_manager(new EventManager),
_size_x(-1),
_size_y(-1),
_view_width(-1),
_view_height(-1),
_status(node, "status"),
_status_msg(node, "status-msg"),
_sampling_dirty(false),
_render_dirty(true),
_visible(true),
_render_always(false)
_status_msg(node, "status-msg")
{
_status = 0;
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
@@ -234,6 +296,10 @@ namespace canvas
if( _status & STATUS_DIRTY )
{
// Retrieve reference here, to ensure the scene group is not deleted while
// creating the new texture and camera
osg::ref_ptr<osg::Group> root_scene_group = _root_group->getSceneGroup();
_texture.setSize(_size_x, _size_y);
if( !_texture.serviceable() )
@@ -251,6 +317,21 @@ namespace canvas
osg::Camera* camera = _texture.getCamera();
string canvasname = _node->getStringValue("name");
int renderToImage = _node->getBoolValue("render-to-image");
if (renderToImage){
CanvasImageCallback *_screenshotCallback = dynamic_cast<CanvasImageCallback*> (camera->getFinalDrawCallback());
if (!_screenshotCallback) {
// no draw callback yet
osg::Image* shot = new osg::Image();
shot->allocateImage(getSizeX(), getSizeY(), 24, GL_RGB, GL_UNSIGNED_BYTE);
camera->attach(osg::Camera::COLOR_BUFFER, shot);
camera->setFinalDrawCallback(new CanvasImageCallback(shot));
SG_LOG(SG_GENERAL,SG_INFO,"CanvasImage: attached image and draw callback to camera " << camera << " for canvas " << canvasname << ". Ready for subscriber now.");
}
}
// TODO Allow custom render order? For now just keep in order with
// property tree.
camera->setRenderOrder(osg::Camera::PRE_RENDER, _node->getIndex());
@@ -259,7 +340,7 @@ namespace canvas
parseColor(_node->getStringValue("background"), clear_color);
camera->setClearColor(clear_color);
camera->addChild(_root_group->getMatrixTransform());
camera->addChild(root_scene_group);
if( _texture.serviceable() )
{
@@ -279,7 +360,7 @@ namespace canvas
if( _visible || _render_always )
{
BOOST_FOREACH(CanvasWeakPtr canvas_weak, _child_canvases)
for(auto& canvas_weak: _child_canvases)
{
// TODO should we check if the image the child canvas is displayed
// within is really visible?
@@ -291,7 +372,7 @@ namespace canvas
if( _render_dirty )
{
// Also mark all canvases this canvas is displayed within as dirty
BOOST_FOREACH(CanvasWeakPtr canvas_weak, _parent_canvases)
for(auto& canvas_weak: _parent_canvases)
{
CanvasPtr canvas = canvas_weak.lock();
if( canvas )
@@ -350,6 +431,41 @@ namespace canvas
}
}
int Canvas::subscribe(CanvasImageReadyListener * subscriber) {
osg::Camera* camera = _texture.getCamera();
const string canvasname = _node->getStringValue("name");
SG_LOG(SG_GENERAL,SG_DEBUG,"CanvasImage: subscribe to canvas " << canvasname.c_str() << ", camera ="<< camera);
if (!_node->getBoolValue("render-to-image")) {
SG_LOG(SG_GENERAL,SG_INFO,"CanvasImage: Setting render-to-image");
_node->addChild("render-to-image", 0)->setBoolValue(1);
setStatusFlags(STATUS_DIRTY, true);
}
CanvasImageCallback *_screenshotCallback = dynamic_cast<CanvasImageCallback*> (camera->getFinalDrawCallback());
if (_screenshotCallback) {
// Camera ready for subscriber. Otherwise, draw callback is created by canvas thread later.
SG_LOG(SG_GENERAL,SG_DEBUG,"CanvasImage: adding subscriber to camera draw callback");
_screenshotCallback->subscribe(subscriber);
// TODO: check: Is this the correct way to ensure the canvas will be available?
enableRendering(true);
return 1;
}
return 0;
}
int Canvas::unsubscribe(CanvasImageReadyListener * subscriber) {
osg::Camera* camera = _texture.getCamera();
SG_LOG(SG_GENERAL,SG_DEBUG,"CanvasImage: unsubscribe");
CanvasImageCallback *cb = dynamic_cast<CanvasImageCallback*> (camera->getFinalDrawCallback());
if (cb) {
SG_LOG(SG_GENERAL,SG_DEBUG,"CanvasImage: unsubscribe from camera " << camera);
cb->unsubscribe(subscriber);
}
return 0;
}
//----------------------------------------------------------------------------
bool Canvas::addEventListener( const std::string& type,
const EventListener& cb )
@@ -520,8 +636,8 @@ namespace canvas
{
const std::string& name = node->getNameString();
if( boost::starts_with(name, "status")
|| boost::starts_with(name, "data-") )
if( strutils::starts_with(name, "status")
|| strutils::starts_with(name, "data-") )
return;
_render_dirty = true;
@@ -536,7 +652,7 @@ namespace canvas
if( !placements.empty() )
{
bool placement_dirty = false;
BOOST_FOREACH(PlacementPtr& placement, placements)
for(auto& placement: placements)
{
// check if change can be directly handled by placement
if( placement->getProps() == node->getParent()

View File

@@ -33,7 +33,7 @@
#include <osg/NodeCallback>
#include <osg/observer_ptr>
#include <boost/scoped_ptr.hpp>
#include <memory>
#include <string>
namespace simgear
@@ -44,6 +44,17 @@ namespace canvas
class CanvasMgr;
class MouseEvent;
/**
* A listener interested in completed canvas drawing.
*/
class CanvasImageReadyListener {
public:
virtual void imageReady(osg::ref_ptr<osg::Image>) = 0;
virtual ~CanvasImageReadyListener()
{
}
};
/**
* Canvas to draw onto (to an off-screen render target).
*/
@@ -71,18 +82,18 @@ namespace canvas
public osg::NodeCallback
{
public:
CullCallback(const CanvasWeakPtr& canvas);
explicit CullCallback(const CanvasWeakPtr& canvas);
private:
CanvasWeakPtr _canvas;
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
void operator()(osg::Node* node, osg::NodeVisitor* nv) override;
};
typedef osg::ref_ptr<CullCallback> CullCallbackPtr;
Canvas(SGPropertyNode* node);
explicit Canvas(SGPropertyNode* node);
virtual ~Canvas();
virtual void onDestroy();
void onDestroy() override;
void setCanvasMgr(CanvasMgr* canvas_mgr);
CanvasMgr* getCanvasMgr() const;
@@ -160,7 +171,12 @@ namespace canvas
*/
void enableRendering(bool force = false);
void update(double delta_time_sec);
void update(double delta_time_sec) override;
osg::Camera* getCamera();
int subscribe(CanvasImageReadyListener * subscriber);
int unsubscribe(CanvasImageReadyListener * subscriber);
int getSubscriberCount();
bool addEventListener(const std::string& type, const EventListener& cb);
bool dispatchEvent(const EventPtr& event);
@@ -184,11 +200,9 @@ namespace canvas
bool propagateEvent( EventPtr const& event,
EventPropagationPath const& path );
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void valueChanged (SGPropertyNode * node);
void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override;
void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override;
void valueChanged(SGPropertyNode * node) override;
osg::Texture2D* getTexture() const;
@@ -211,21 +225,21 @@ namespace canvas
protected:
CanvasMgr *_canvas_mgr;
CanvasMgr *_canvas_mgr {nullptr};
boost::scoped_ptr<EventManager> _event_manager;
std::unique_ptr<EventManager> _event_manager;
int _size_x,
_size_y,
_view_width,
_view_height;
int _size_x {-1},
_size_y {-1},
_view_width {-1},
_view_height {-1};
PropertyObject<int> _status;
PropertyObject<std::string> _status_msg;
bool _sampling_dirty,
_render_dirty,
_visible;
bool _sampling_dirty {false},
_render_dirty {true},
_visible {true};
ODGauge _texture;
@@ -235,7 +249,9 @@ namespace canvas
ElementWeakPtr _focus_element;
CullCallbackPtr _cull_callback;
bool _render_always; //!< Used to disable automatic lazy rendering (culling)
/** Used to disable automatic lazy rendering (culling) */
bool _render_always {false};
std::vector<SGPropertyNode*> _dirty_placements;
std::vector<Placements> _placements;
@@ -252,8 +268,8 @@ namespace canvas
static SystemAdapterPtr _system_adapter;
Canvas(const Canvas&); // = delete;
Canvas& operator=(const Canvas&); // = delete;
Canvas(const Canvas&) = delete;
Canvas& operator=(const Canvas&) = delete;
};
} // namespace canvas

View File

@@ -1,4 +1,5 @@
// Canvas Event for event model similar to DOM Level 3 Event Model
///@file
/// Canvas Event for event model similar to DOM Level 3 Event Model
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasEvent.hxx"
namespace simgear
@@ -123,10 +126,10 @@ namespace canvas
//----------------------------------------------------------------------------
std::string Event::typeToStr(int type)
{
TypeMap const& type_map = getTypeMap();
auto const& map_by_id = getTypeMap().by<id>();
TypeMap::map_by<id>::const_iterator it = type_map.by<id>().find(type);
if( it == type_map.by<id>().end() )
auto it = map_by_id.find(type);
if( it == map_by_id.end() )
return "unknown";
return it->second;
}

View File

@@ -65,6 +65,11 @@ namespace canvas
// of the actual event instances.
virtual ~Event();
/**
* Clone event and set to the given type (Same type if not specified)
*/
virtual Event* clone(int type = 0) const = 0;
/**
* Get whether this events support bubbling
*/
@@ -110,7 +115,14 @@ namespace canvas
*/
bool defaultPrevented() const;
/**
* Register a new type string or get the id of an existing type string
*
* @param type Type string
* @return Id of the given @a type
*/
static int getOrRegisterType(const std::string& type);
static int strToType(const std::string& type);
static std::string typeToStr(int type);

View File

@@ -1,4 +1,5 @@
// Manage event handling inside a Canvas similar to the DOM Level 3 Event Model
///@file
/// Manage event handling inside a Canvas similar to the DOM Level 3 Event Model
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,9 +17,12 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasEventManager.hxx"
#include <simgear/canvas/events/MouseEvent.hxx>
#include <simgear/canvas/elements/CanvasElement.hxx>
#include "elements/CanvasElement.hxx"
#include "events/MouseEvent.hxx"
#include <cmath>
namespace simgear
@@ -113,6 +117,8 @@ namespace canvas
return handled;
}
case Event::DRAG:
case Event::DRAG_START:
case Event::DRAG_END:
if( !_last_mouse_down.valid() )
return false;
else

View File

@@ -1,4 +1,5 @@
// Manage event handling inside a Canvas similar to the DOM Level 3 Event Model
///@file
/// Manage event handling inside a Canvas similar to the DOM Level 3 Event Model
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//

View File

@@ -1,4 +1,5 @@
// Mapping between canvas gui Event types and their names
///@file
/// Mapping between canvas gui Event types and their names
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -25,6 +26,8 @@ ENUM_MAPPING(MOUSE_UP, "mouseup", MouseEvent)
ENUM_MAPPING(CLICK, "click", MouseEvent)
ENUM_MAPPING(DBL_CLICK, "dblclick", MouseEvent)
ENUM_MAPPING(DRAG, "drag", MouseEvent)
ENUM_MAPPING(DRAG_START, "dragstart", MouseEvent)
ENUM_MAPPING(DRAG_END, "dragend", MouseEvent)
ENUM_MAPPING(WHEEL, "wheel", MouseEvent)
ENUM_MAPPING(MOUSE_MOVE, "mousemove", MouseEvent)
ENUM_MAPPING(MOUSE_OVER, "mouseover", MouseEvent)

View File

@@ -1,5 +1,6 @@
// Visitor for traversing a canvas element hierarchy similar to the traversal
// of the DOM Level 3 Event Model
///@file
/// Visitor for traversing a canvas element hierarchy similar to the traversal
/// of the DOM Level 3 Event Model
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -17,9 +18,11 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasEvent.hxx"
#include "CanvasEventVisitor.hxx"
#include <simgear/canvas/elements/CanvasElement.hxx>
#include "elements/CanvasElement.hxx"
namespace simgear
{

View File

@@ -1,5 +1,6 @@
// Visitor for traversing a canvas element hierarchy similar to the traversal
// of the DOM Level 3 Event Model
///@file
/// Visitor for traversing a canvas element hierarchy similar to the traversal
/// of the DOM Level 3 Event Model
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//

View File

@@ -1,4 +1,5 @@
// Canvas with 2D rendering API
///@file
/// Canvas with 2D rendering API
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,12 +17,12 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasMgr.hxx"
#include "Canvas.hxx"
#include "CanvasEventManager.hxx"
#include <boost/bind.hpp>
namespace simgear
{
namespace canvas

View File

@@ -1,4 +1,5 @@
// Canvas with 2D rendering API
///@file
/// Canvas with 2D rendering API
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -27,42 +28,39 @@ namespace simgear
namespace canvas
{
class CanvasMgr:
public PropertyBasedMgr
{
public:
class CanvasMgr : public PropertyBasedMgr
{
public:
/**
* @param node Root node of branch used to control canvasses
*/
CanvasMgr(SGPropertyNode_ptr node);
/**
* @param node Root node of branch used to control canvasses
*/
CanvasMgr(SGPropertyNode_ptr node);
/**
* Create a new canvas
*
* @param name Name of the new canvas
*/
CanvasPtr createCanvas(const std::string& name = "");
/**
* Create a new canvas
*
* @param name Name of the new canvas
*/
CanvasPtr createCanvas(const std::string& name = "");
/**
* Get ::Canvas by index
*
* @param index Index of texture node in /canvas/by-index/
*/
CanvasPtr getCanvas(size_t index) const;
/**
* Get ::Canvas by index
*
* @param index Index of texture node in /canvas/by-index/
*/
CanvasPtr getCanvas(size_t index) const;
/**
* Get ::Canvas by name
*
* @param name Value of child node "name" in
* /canvas/by-index/texture[i]/name
*/
CanvasPtr getCanvas(const std::string& name) const;
/**
* Get ::Canvas by name
*
* @param name Value of child node "name" in
* /canvas/by-index/texture[i]/name
*/
CanvasPtr getCanvas(const std::string& name) const;
protected:
virtual void elementCreated(PropertyBasedElementPtr element);
};
protected:
void elementCreated(PropertyBasedElementPtr element) override;
};
} // namespace canvas
} // namespace simgear

View File

@@ -1,4 +1,5 @@
// Canvas placement for placing a canvas texture onto osg objects.
///@file
/// Canvas placement for placing a canvas texture onto osg objects
//
// It also provides a SGPickCallback for passing mouse events to the canvas and
// manages emissive lighting of the placed canvas.
@@ -19,6 +20,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "Canvas.hxx"
#include "CanvasObjectPlacement.hxx"
#include <simgear/canvas/events/MouseEvent.hxx>

View File

@@ -1,5 +1,5 @@
///@file
/// Placement for putting a canvas texture onto OpenSceneGraph objects.
/// Placement for putting a canvas texture onto OpenSceneGraph objects
///
/// It also provides a SGPickCallback for passing mouse events to the canvas and
/// manages emissive lighting of the placed canvas.
@@ -60,7 +60,7 @@ namespace canvas
*/
void setCaptureEvents(bool enable);
virtual bool childChanged(SGPropertyNode* child);
bool childChanged(SGPropertyNode* child) override;
protected:
typedef SGSharedPtr<SGPickCallback> PickCallbackPtr;

View File

@@ -1,4 +1,5 @@
// Base class for canvas placements
///@file
/// Base class for canvas placements
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,7 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasPlacement.hxx"
#include <simgear/props/props.hxx>

View File

@@ -1,4 +1,5 @@
// Base class for canvas placements
///@file
/// Base class for canvas placements
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -40,9 +41,8 @@ namespace canvas
protected:
SGPropertyNode_ptr _node;
private:
Placement(const Placement&) /* = delete */;
Placement& operator=(const Placement&) /* = delete */;
Placement(const Placement&) = delete;
Placement& operator=(const Placement&) = delete;
};
} // namespace canvas

View File

@@ -1,4 +1,5 @@
// Adapter for using the canvas with different applications
///@file
/// Adapter for using the canvas with different applications
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -29,6 +30,10 @@ namespace HTTP { class Client; }
namespace canvas
{
/**
* Provides access to different required systems of the application to the
* Canvas
*/
class SystemAdapter
{
public:

View File

@@ -1,4 +1,5 @@
// Window for placing a Canvas onto it (for dialogs, menus, etc.)
///@file
/// Window for placing a Canvas onto it (for dialogs, menus, etc.)
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,18 +17,17 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasMgr.hxx"
#include "CanvasSystemAdapter.hxx"
#include "CanvasWindow.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/misc/strutils.hxx>
#include <simgear/scene/util/OsgMath.hxx>
#include <osgGA/GUIEventHandler>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
namespace simgear
{
namespace canvas
@@ -42,9 +42,6 @@ namespace canvas
const Style& parent_style,
Element* parent ):
Image(canvas, node, parent_style, parent),
_attributes_dirty(0),
_resizable(false),
_capture_events(true),
_resize_top(node, "resize-top"),
_resize_right(node, "resize-right"),
_resize_bottom(node, "resize-bottom"),
@@ -91,7 +88,7 @@ namespace canvas
_capture_events = node->getBoolValue();
else if( name == "decoration-border" )
parseDecorationBorder(node->getStringValue());
else if( boost::starts_with(name, "shadow-")
else if( strutils::starts_with(name, "shadow-")
|| name == "content-size" )
_attributes_dirty |= DECORATION;
else
@@ -102,16 +99,10 @@ namespace canvas
Image::valueChanged(node);
}
//----------------------------------------------------------------------------
osg::Group* Window::getGroup()
{
return getMatrixTransform();
}
//----------------------------------------------------------------------------
const SGVec2<float> Window::getPosition() const
{
const osg::Matrix& m = getMatrixTransform()->getMatrix();
auto const& m = getMatrix();
return SGVec2<float>( m(3, 0), m(3, 1) );
}
@@ -222,6 +213,19 @@ namespace canvas
_resize_left = getRegion().l() + offset.x();
}
//----------------------------------------------------------------------------
bool Window::handleEvent(const EventPtr& event)
{
if( auto mouse_event = dynamic_cast<MouseEvent*>(event.get()) )
{
mouse_event->local_pos =
mouse_event->client_pos =
mouse_event->screen_pos - toOsg(getPosition());
}
return Image::handleEvent(event);
}
//----------------------------------------------------------------------------
void Window::parseDecorationBorder(const std::string& str)
{

View File

@@ -1,4 +1,5 @@
// Window for placing a Canvas onto it (for dialogs, menus, etc.)
///@file
/// Window for placing a Canvas onto it (for dialogs, menus, etc.)
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -67,10 +68,9 @@ namespace canvas
Element* parent = 0 );
virtual ~Window();
virtual void update(double delta_time_sec);
virtual void valueChanged(SGPropertyNode* node);
void update(double delta_time_sec) override;
void valueChanged(SGPropertyNode* node) override;
osg::Group* getGroup();
const SGVec2<float> getPosition() const;
const SGRect<float> getScreenRegion() const;
@@ -84,8 +84,8 @@ namespace canvas
bool isResizable() const;
bool isCapturingEvents() const;
virtual void setVisible(bool visible);
virtual bool isVisible() const;
void setVisible(bool visible) override;
bool isVisible() const override;
/**
* Moves window on top of all other windows with the same z-index.
@@ -97,6 +97,8 @@ namespace canvas
void handleResize( uint8_t mode,
const osg::Vec2f& offset = osg::Vec2f() );
bool handleEvent(const EventPtr& event) override;
protected:
enum Attributes
@@ -104,7 +106,7 @@ namespace canvas
DECORATION = 1
};
uint32_t _attributes_dirty;
uint32_t _attributes_dirty {0};
CanvasPtr _canvas_decoration;
CanvasWeakPtr _canvas_content;
@@ -113,8 +115,8 @@ namespace canvas
ImagePtr _image_content,
_image_shadow;
bool _resizable,
_capture_events;
bool _resizable {false},
_capture_events {true};
PropertyObject<int> _resize_top,
_resize_right,

View File

@@ -1,4 +1,5 @@
// Owner Drawn Gauge helper class
///@file
/// Owner Drawn Gauge helper class
//
// Written by Harald JOHNSEN, started May 2005.
//
@@ -6,9 +7,9 @@
//
// Ported to OSG by Tim Moore - Jun 2007
//
// Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April 2012
// Supports now multisampling/mipmapping, usage of the stencil buffer and placing
// the texture in the scene by certain filter criteria
// Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April
// 2012 Supports now multisampling/mipmapping, usage of the stencil buffer and
// placing the texture in the scene by certain filter criteria.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
@@ -249,10 +250,16 @@ namespace canvas
if( !texture )
{
// It shouldn't be necessary to allocate an image for the
// texture that is the target of dynamic rendering, but
// otherwise OSG won't construct all the mipmaps for the texture
// and dynamic mipmap generation doesn't work.
osg::Image* image = new osg::Image;
image->allocateImage(_size_x, _size_y, 1, GL_RGBA, GL_UNSIGNED_BYTE);
texture = new osg::Texture2D;
texture->setResizeNonPowerOfTwoHint(false);
texture->setTextureSize(_size_x, _size_y);
texture->setInternalFormat(GL_RGBA);
texture->setImage(image);
texture->setUnRefImageDataAfterApply(true);
}
updateSampling();

View File

@@ -1,4 +1,5 @@
// Owner Drawn Gauge helper class
///@file
/// Owner Drawn Gauge helper class
//
// Written by Harald JOHNSEN, started May 2005.
//
@@ -6,9 +7,9 @@
//
// Ported to OSG by Tim Moore - Jun 2007
//
// Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April 2012
// Supports now multisampling/mipmapping, usage of the stencil buffer and placing
// the texture in the scene by certain filter criteria
// Heavily modified to be usable for the 2d Canvas by Thomas Geymayer - April
// 2012 Supports now multisampling/mipmapping, usage of the stencil buffer and
// placing the texture in the scene by certain filter criteria.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public

View File

@@ -31,6 +31,11 @@
// FreeBSD
#define VG_API_FREEBSD
#elif defined(__OpenBSD__)
// FreeBSD
#define VG_API_OPENBSD
#else
// Unsupported system

View File

@@ -34,7 +34,7 @@
#include <math.h>
#include <float.h>
#if !defined(VG_API_MACOSX) && !defined(__FreeBSD__)
#if !defined(VG_API_MACOSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
# include <malloc.h>
#endif
@@ -44,6 +44,11 @@
#if defined(_MSC_VER)
# pragma warning(disable:4311)
# pragma warning(disable:4312)
# define ALIGN16 __declspec(align(16))
# define ALIGN16C
#elif defined(__GNUC__)
# define ALIGN16
# define ALIGN16C __attribute__((aligned(16)))
#endif
/* Type definitions */
@@ -156,7 +161,7 @@ SHfloat getMaxFloat();
/* OpenGL headers */
#if defined(VG_API_LINUX) || defined(VG_API_FREEBSD)
#if defined(VG_API_LINUX) || defined(VG_API_FREEBSD) || defined(VG_API_OPENBSD)
#include <GL/gl.h>
#include <GL/glx.h>
#elif defined(VG_API_MACOSX)

View File

@@ -1193,7 +1193,7 @@ VG_API_CALL VGboolean vgInterpolatePath(VGPath dstPath, VGPath startPath,
SHfloat *procData1, *procData2;
SHint procSegCount1=0, procSegCount2=0;
SHint procDataCount1=0, procDataCount2=0;
SHuint8 *newSegs, *newData;
SHuint8 *newSegs, *newData=0;
void *userData[4];
SHint segment1, segment2;
SHint segindex, s,d,i;

View File

@@ -35,21 +35,33 @@ void SHVector2_dtor(SHVector2 *v) {
}
void SHVector3_ctor(SHVector3 *v) {
#ifdef SHIVA_USE_SIMD
v->vec = _mm_setzero_ps();
#else
v->x=0.0f; v->y=0.0f; v->z=0.0f;
#endif
}
void SHVector3_dtor(SHVector3 *v) {
}
void SHVector4_ctor(SHVector4 *v) {
#ifdef SHIVA_USE_SIMD
v->vec = _mm_setzero_ps();
#else
v->x=0.0f; v->y=0.0f; v->z=0.0f; v->w=0.0f;
#endif
}
void SHVector4_dtor(SHVector4 *v) {
}
void SHRectangle_ctor(SHRectangle *r) {
#ifdef SHIVA_USE_SIMD
r->vec = _mm_setzero_ps();
#else
r->x=0.0f; r->y=0.0f; r->w=0.0f; r->h=0.0f;
#endif
}
void SHRectangle_dtor(SHRectangle *r) {
@@ -135,3 +147,24 @@ int shLineLineXsection(SHVector2 *o1, SHVector2 *v1,
xsection->y = o1->y + t1*v1->y;
return 1;
}
#ifdef SHIVA_USE_SIMD
# ifdef __SSE3__
# include <pmmintrin.h>
inline float hsum_ps_sse(__m128 v) {
__m128 shuf = _mm_movehdup_ps(v);
__m128 sums = _mm_add_ps(v, shuf);
shuf = _mm_movehl_ps(shuf, sums);
sums = _mm_add_ss(sums, shuf);
return _mm_cvtss_f32(sums);
}
# else
inline float hsum_ps_sse(__m128 v) {
__m128 shuf = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 3, 0, 1));
__m128 sums = _mm_add_ps(v, shuf);
shuf = _mm_movehl_ps(shuf, sums);
sums = _mm_add_ss(sums, shuf);
return _mm_cvtss_f32(sums);
}
# endif
#endif

View File

@@ -21,6 +21,21 @@
#ifndef __SHVECTORS_H
#define __SHVECTORS_H
#ifdef HAVE_CONFIG_H
# include <simgear/simgear_config.h>
#endif
#ifdef ENABLE_SIMD
# ifdef __SSE__
// # define SHIVA_USE_SIMD
# endif
# endif
#ifdef SHIVA_USE_SIMD
# include <xmmintrin.h>
float hsum_ps_sse(__m128 v);
#endif
#include "shDefs.h"
/* Vector structures
@@ -33,9 +48,17 @@ typedef struct
void SHVector2_ctor(SHVector2 *v);
void SHVector2_dtor(SHVector2 *v);
typedef struct
{
#ifdef SHIVA_USE_SIMD
union ALIGN16 {
__m128 vec;
struct { SHfloat x,y,z,w; };
} ALIGN16C;
#else
SHfloat x,y,z;
#endif
} SHVector3;
void SHVector3_ctor(SHVector3 *v);
@@ -43,7 +66,14 @@ void SHVector3_dtor(SHVector3 *v);
typedef struct
{
#ifdef SHIVA_USE_SIMD
union ALIGN16 {
__m128 vec;
struct { SHfloat x,y,z,w; };
} ALIGN16C;
#else
SHfloat x,y,z,w;
#endif
} SHVector4;
void SHVector4_ctor(SHVector4 *v);
@@ -51,7 +81,14 @@ void SHVector4_dtor(SHVector4 *v);
typedef struct
{
#ifdef SHIVA_USE_SIMD
union ALIGN16 {
__m128 vec;
struct { SHfloat x,y,w,h; };
} ALIGN16C;
#else
SHfloat x,y,w,h;
#endif
} SHRectangle;
void SHRectangle_ctor(SHRectangle *r);
@@ -61,7 +98,14 @@ void shRectangleSet(SHRectangle *r, SHfloat x,
typedef struct
{
#ifdef SHIVA_USE_SIMD
union ALIGN16 {
__m128 mtx[4];
SHfloat m[4][4];
} ALIGN16C;
#else
SHfloat m[3][3];
#endif
} SHMatrix3x3;
void SHMatrix3x3_ctor(SHMatrix3x3 *m);
@@ -83,12 +127,22 @@ void SHMatrix3x3_dtor(SHMatrix3x3 *m);
*--------------------------------------------------------- */
#define SET2(v,xs,ys) { v.x=xs; v.y=ys; }
#define SET3(v,xs,ys,zs) { v.x=xs; v.y=ys; v.z=zs; }
#define SET4(v,xs,ys,zs,ws) { v.x=xs; v.y=ys; v.z=zs; v.w=ws; }
#ifdef SHIVA_USE_SIMD
# define SET3(v,xs,ys,zs,ws) { v.vec=_mm_set_ps(0,zs,ys,xs); }
# define SET4(v,xs,ys,zs,ws) { v.vec=_mm_set_ps(ws,zs,ys,xs); }
#else
# define SET3(v,xs,ys,zs) { v.x=xs; v.y=ys; v.z=zs; }
# define SET4(v,xs,ys,zs,ws) { v.x=xs; v.y=ys; v.z=zs; v.w=ws; }
#endif
#define SET2V(v1,v2) { v1.x=v2.x; v1.y=v2.y; }
#define SET3V(v1,v2) { v1.x=v2.x; v1.y=v2.y; v1.z=v2.z; }
#define SET4V(v1,v2) { v1.x=v2.x; v1.y=v2.y; v1.z=v2.z; v1.w=v2.w; }
#ifdef SHIVA_USE_SIMD
# define SET3V(v1,v2) { v1.vec=v2.vec; }
# define SET4V(v1,v2) { v1.vec=v2.vec; }
#else
# define SET3V(v1,v2) { v1.x=v2.x; v1.y=v2.y; v1.z=v2.z; }
# define SET4V(v1,v2) { v1.x=v2.x; v1.y=v2.y; v1.z=v2.z; v1.w=v2.w; }
#endif
#define EQ2(v,xx,yy) ( v.x==xx && v.y==yy )
#define EQ3(v,xx,yy,zz) ( v.x==xx && v.y==yy && v.z==zz )
@@ -103,48 +157,89 @@ void SHMatrix3x3_dtor(SHMatrix3x3 *m);
#define EQ4V(v1,v2) ( v1.x==v2.x && v1.y==v2.y && v1.z==v2.z && v1.w==v2.w )
#define ADD2(v,xx,yy) { v.x+=xx; v.y+=yy; }
#define ADD3(v,xx,yy,zz) { v.x+=xx; v.y+=yy; v.z+=zz; }
#define ADD4(v,xx,yy,zz,ww) { v.x+=xx; v.y+=yy; v.z+=zz; v.w+=ww; }
#ifdef SHIVA_USE_SIMD
# define ADD3(v,xx,yy,zz,ww) { v.vec=_mm_add_ps(v.vec,_mm_set_ps(0,zz,yy,xx)); }
# define ADD4(v,xx,yy,zz,ww) { v.vec=_mm_add_ps(v.vec,_mm_set_ps(ww,zz,yy,xx)); }
#else
# define ADD3(v,xx,yy,zz) { v.x+=xx; v.y+=yy; v.z+=zz; }
# define ADD4(v,xx,yy,zz,ww) { v.x+=xx; v.y+=yy; v.z+=zz; v.w+=ww; }
#endif
#define ADD2V(v1,v2) { v1.x+=v2.x; v1.y+=v2.y; }
#define ADD3V(v1,v2) { v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z; }
#define ADD4V(v1,v2) { v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z; v1.w+=v2.w; }
#ifdef SHIVA_USE_SIMD
# define ADD3V(v1,v2) { v1.vec=_mm_add_ps(v1.vec,v2.vec); }
# define ADD4V(v1,v2) { v1.vec=_mm_add_ps(v1.vec,v2.vec); }
#else
# define ADD3V(v1,v2) { v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z; }
# define ADD4V(v1,v2) { v1.x+=v2.x; v1.y+=v2.y; v1.z+=v2.z; v1.w+=v2.w; }
#endif
#define SUB2(v,xx,yy) { v.x-=xx; v.y-=yy; }
#define SUB3(v,xx,yy,zz) { v.x-=xx; v.y-=yy; v.z-=zz; }
#define SUB4(v,xx,yy,zz,ww) { v.x-=xx; v.y-=yy; v.z-=zz; v.w-=v2.w; }
#ifdef SHIVA_USE_SIMD
# define SUB3(v,xx,yy,zz,ww) { v.vec=_mm_sub_ps(v.vec,_mm_set_ps(0,zz,yy,xx)); }
# define SUB4(v,xx,yy,zz,ww) { v.vec=_mm_sub_ps(v.vec,_mm_set_ps(ww,zz,yy,xx)); }
#else
# define SUB3(v,xx,yy,zz) { v.x-=xx; v.y-=yy; v.z-=zz; }
# define SUB4(v,xx,yy,zz,ww) { v.x-=xx; v.y-=yy; v.z-=zz; v.w-=v2.w; }
#endif
#define SUB2V(v1,v2) { v1.x-=v2.x; v1.y-=v2.y; }
#define SUB3V(v1,v2) { v1.x-=v2.x; v1.y-=v2.y; v1.z-=v2.z; }
#define SUB4V(v1,v2) { v1.x-=v2.x; v1.y-=v2.y; v1.z-=v2.z; v1.w-=v2.w; }
#ifdef SHIVA_USE_SIMD
# define SUB3V(v1,v2) { v1.vec=_mm_sub_ps(v1.vec,v2.vec); }
# define SUB4V(v1,v2) { v1.vec=_mm_sub_ps(v1.vec,v2.vec); }
#else
# define SUB3V(v1,v2) { v1.x-=v2.x; v1.y-=v2.y; v1.z-=v2.z; }
# define SUB4V(v1,v2) { v1.x-=v2.x; v1.y-=v2.y; v1.z-=v2.z; v1.w-=v2.w; }
#endif
#define MUL2(v,f) { v.x*=f; v.y*=f; }
#define MUL3(v,f) { v.x*=f; v.y*=f; v.z*=z; }
#define MUL4(v,f) { v.x*=f; v.y*=f; v.z*=z; v.w*=w; }
#ifdef SHIVA_USE_SIMD
# define MUL3(v,f) { v.vec=_mm_mul_ps(v.vec,_mm_set1_ps(f)); }
# define MUL4(v,f) { v.vec=_mm_mul_ps(v.vec,_mm_set1_ps(f)); }
#else
# define MUL3(v,f) { v.x*=f; v.y*=f; v.z*=z; }
# define MUL4(v,f) { v.x*=f; v.y*=f; v.z*=z; v.w*=w; }
#endif
#define DIV2(v,f) { v.x/=f; v.y/=f; }
#define DIV3(v,f) { v.x/=f; v.y/=f; v.z/=z; }
#define DIV4(v,f) { v.x/=f; v.y/=f; v.z/=z; v.w/=w; }
#ifdef SHIVA_USE_SIMD
# define DIV3(v,f) { v.vec=_mm_div_ps(v.vec,_mm_set1_ps(f)); }
# define DIV4(v,f) { v.vec=_mm_div_ps(v.vec,_mm_set1_ps(f)); }
#else
# define DIV3(v,f) { v.x/=f; v.y/=f; v.z/=z; }
# define DIV4(v,f) { v.x/=f; v.y/=f; v.z/=z; v.w/=w; }
#endif
#define ABS2(v) { v.x=SH_ABS(v.x); v.y=SH_ABS(v.y); }
#define ABS3(v) { v.x=SH_ABS(v.x); v.y=SH_ABS(v.y); v.z=SH_ABS(v.z); }
#define ABS4(v) { v.x=SH_ABS(v.x); v.y=SH_ABS(v.y); v.z=SH_ABS(v.z); v.w=SH_ABS(v.w); }
#ifdef SHIVA_USE_SIMD
# define ABS_MASK _mm_set1_ps(-0.f)
# define ABS3(v) { v.vec=_mm_andnot_ps(ABS_MASK, v.vec); }
# define ABS4(v) { v.vec=_mm_andnot_ps(ABS_MASK, v.vec); }
#else
# define ABS3(v) { v.x=SH_ABS(v.x); v.y=SH_ABS(v.y); v.z=SH_ABS(v.z); }
# define ABS4(v) { v.x=SH_ABS(v.x); v.y=SH_ABS(v.y); v.z=SH_ABS(v.z); v.w=SH_ABS(v.w); }
#endif
#define NORMSQ2(v) (v.x*v.x + v.y*v.y)
#define NORMSQ3(v) (v.x*v.x + v.y*v.y + v.z*v.z)
#define NORMSQ4(v) (v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w)
#define NORMSQ2(v) DOT2(v,v)
#define NORMSQ3(v) DOT3(v,v)
#define NORMSQ4(v) DOT4(v,v)
#define NORM2(v) SH_SQRT(NORMSQ2(v))
#define NORM3(v) SH_SQRT(NORMSQ3(v))
#define NORM4(v) SH_SQRT(NORMSQ4(v))
#define NORMALIZE2(v) { SHfloat n=NORM2(v); v.x/=n; v.y/=n; }
#define NORMALIZE3(v) { SHfloat n=NORM3(v); v.x/=n; v.y/=n; v.z/=n; }
#define NORMALIZE4(v) { SHfloat n=NORM4(v); v.x/=n; v.y/=n; v.z/=n; v.w/=w; }
#define NORMALIZE2(v) { SHfloat n=NORM2(v); DIV2(v,n); }
#define NORMALIZE3(v) { SHfloat n=NORM3(v); DIV3(v,n); }
#define NORMALIZE4(v) { SHfloat n=NORM4(v); DIV4(v,n); }
#define DOT2(v1,v2) (v1.x*v2.x + v1.y*v2.y)
#define DOT3(v1,v2) (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)
#define DOT4(v1,v2) (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w)
#ifdef SHIVA_USE_SIMD
# define DOT4(v1,v2) hsum_ps_sse(_mm_mul_ps(v1.vec,v2.vec))
# define DOT4(v1,v2) hsum_ps_sse(_mm_mul_ps(v1.vec,v2.vec))
#else
# define DOT3(v1,v2) (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z)
# define DOT4(v1,v2) (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z + v1.w*v2.w)
#endif
#define CROSS2(v1,v2) (v1.x*v2.y - v2.x*v1.y)
@@ -152,37 +247,84 @@ void SHMatrix3x3_dtor(SHMatrix3x3 *m);
#define ANGLE2N(v1,v2) (SH_ACOS( DOT2(v1,v2) ))
#define OFFSET2V(v, o, s) { v.x += o.x*s; v.y += o.y*s; }
#define OFFSET3V(v, o, s) { v.x += o.x*s; v.y += o.y*s; v.z += o.z*s; }
#define OFFSET4V(v, o, s) { v.x += o.x*s; v.y += o.y*s; v.z += o.z*s; v.w += o.w*s; }
#ifdef SHIVA_USE_SIMD
# define OFFSET4V(v, o, s) { v.vec=_mm_add_ps(v.vec,_mm_mul_ps(o.vec,_mm_set1_ps(s))); }
# define OFFSET4V(v, o, s) { v.vec=_mm_add_ps(v.vec,_mm_mul_ps(o.vec,_mm_set1_ps(s))); }
#else
# define OFFSET3V(v, o, s) { v.x += o.x*s; v.y += o.y*s; v.z += o.z*s; }
# define OFFSET4V(v, o, s) { v.x += o.x*s; v.y += o.y*s; v.z += o.z*s; v.w += o.w*s; }
#endif
/*-----------------------------------------------------
* Macros for matrix operations
*-----------------------------------------------------*/
#define SETMAT(mat, m00, m01, m02, m10, m11, m12, m20, m21, m22) { \
mat.m[0][0] = m00; mat.m[0][1] = m01; mat.m[0][2] = m02; \
#ifdef SHIVA_USE_SIMD
# define SETMAT(mat, m00, m01, m02, m10, m11, m12, m20, m21, m22) { \
mat.mtx[0] = _mm_set_ps(0,m02,m01,m00); \
mat.mtx[1] = _mm_set_ps(0,m12,m11,m10); \
mat.mtx[2] = _mm_set_ps(0,m22,m21,m20); \
mat.mtx[3] = _mm_setzero_ps(); }
#else
# define SETMAT(mat, m00, m01, m02, m10, m11, m12, m20, m21, m22) { \
mat.m[0][0] = m00; mat.m[0][1] = m01; mat.m[0][2] = m02; \
mat.m[1][0] = m10; mat.m[1][1] = m11; mat.m[1][2] = m12; \
mat.m[2][0] = m20; mat.m[2][1] = m21; mat.m[2][2] = m22; }
#endif
#define SETMATMAT(m1, m2) { \
#ifdef SHIVA_USE_SIMD
# define SETMATMAT(m1, m2) { \
m1.mtx[0] = m2.mtx[0]; \
m1.mtx[1] = m2.mtx[1]; \
m1.mtx[2] = m2.mtx[2]; }
#else
# define SETMATMAT(m1, m2) { \
int i,j; \
for(i=0;i<3;i++) \
for(j=0;j<3;j++) \
m1.m[i][j] = m2.m[i][j]; }
#endif
#define MULMATS(mat, s) { \
#ifdef SHIVA_USE_SIMD
# define MULMATS(mat, s) { \
mat.mtx[0] = _mm_mul_ps(mat.mtx[0],_mm_set1_ps(s)); \
mat.mtx[1] = _mm_mul_ps(mat.mtx[1],_mm_set1_ps(s)); \
mat.mtx[2] = _mm_mul_ps(mat.mtx[2],_mm_set1_ps(s)); }
#else
# define MULMATS(mat, s) { \
int i,j; \
for(i=0;i<3;i++) \
for(j=0;j<3;j++) \
mat.m[i][j] *= s; }
#endif
#define DIVMATS(mat, s) { \
#ifdef SHIVA_USE_SIMD
# define DIVMATS(mat, s) { \
mat.mtx[0] = _mm_mul_ps(mat.mtx[0],_mm_set1_ps(1/s)); \
mat.mtx[1] = _mm_mul_ps(mat.mtx[1],_mm_set1_ps(1/s)); \
mat.mtx[2] = _mm_mul_ps(mat.mtx[2],_mm_set1_ps(1/s)); }
#else
# define DIVMATS(mat, s) { \
int i,j; \
for(i=0;i<3;i++) \
for(j=0;j<3;j++) \
mat.m[i][j] /= s; }
#endif
#define MULMATMAT(m1, m2, mout) { \
#ifdef SHIVA_USE_SIMD
# define MULMATMAT(m2, m1, mout) { \
int i,j; \
for (i=0;i<4;i++) { \
__m128 a = m1.mtx[0]; \
__m128 b = _mm_set1_ps(m2.m[i][0]); \
mout.mtx[i] = a*b; \
for (j=1;j<4;j++) { \
a = m1.mtx[j]; \
b = _mm_set1_ps(m2.m[i][j]); \
mout.mtx[i] += a*b; } } }
#else
# define MULMATMAT(m1, m2, mout) { \
int i,j; \
for(i=0;i<3;i++) \
for(j=0;j<3;j++) \
@@ -190,6 +332,7 @@ int i,j; \
m1.m[i][0] * m2.m[0][j] + \
m1.m[i][1] * m2.m[1][j] + \
m1.m[i][2] * m2.m[2][j]; }
#endif
#define IDMAT(mat) SETMAT(mat, 1,0,0, 0,1,0, 0,0,1)

View File

@@ -1,4 +1,5 @@
// osg::Operation to initialize the OpenVG context used for path rendering
///@file
/// osg::Operation to initialize the OpenVG context used for path rendering
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//

View File

@@ -1,4 +1,5 @@
// osg::Operation to initialize the OpenVG context used for path rendering
///@file
/// osg::Operation to initialize the OpenVG context used for path rendering
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//

View File

@@ -1,4 +1,5 @@
// Canvas forward declarations
///@file
/// Canvas forward declarations
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -25,11 +26,9 @@
#include <osg/ref_ptr>
#include <osgText/Font>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <functional>
#include <map>
#include <memory>
#include <vector>
namespace simgear
@@ -61,8 +60,8 @@ namespace canvas
#define SG_FWD_DECL(name)\
class name;\
typedef boost::shared_ptr<name> name##Ptr;\
typedef boost::weak_ptr<name> name##WeakPtr;
typedef std::shared_ptr<name> name##Ptr;\
typedef std::weak_ptr<name> name##WeakPtr;
SG_FWD_DECL(Placement)
SG_FWD_DECL(SystemAdapter)
@@ -84,10 +83,10 @@ namespace canvas
typedef osg::ref_ptr<osgText::Font> FontPtr;
typedef std::vector<PlacementPtr> Placements;
typedef boost::function<Placements( SGPropertyNode*,
CanvasPtr )> PlacementFactory;
typedef std::function<Placements( SGPropertyNode*,
CanvasPtr )> PlacementFactory;
typedef boost::function<void(const EventPtr&)> EventListener;
typedef std::function<void(const EventPtr&)> EventListener;
} // namespace canvas
} // namespace simgear

View File

@@ -9,10 +9,6 @@ set(HEADERS
CanvasText.hxx
)
set(DETAIL_HEADERS
detail/add_segment_variadic.hxx
)
set(SOURCES
CanvasElement.cxx
CanvasGroup.cxx
@@ -23,7 +19,6 @@ set(SOURCES
)
simgear_scene_component(canvas-elements canvas/elements "${SOURCES}" "${HEADERS}")
simgear_component(canvas-elements/detail canvas/elements/detail "" "${DETAIL_HEADERS}")
add_boost_test(canvas_element
SOURCES canvas_element_test.cpp

View File

@@ -1,4 +1,5 @@
// Interface for 2D Canvas element
///@file
/// Interface for 2D Canvas element
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasElement.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasEventVisitor.hxx>
@@ -29,10 +32,6 @@
#include <osg/StateAttribute>
#include <osg/Version>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <cassert>
#include <cmath>
#include <cstring>
@@ -212,22 +211,22 @@ namespace canvas
//----------------------------------------------------------------------------
void Element::onDestroy()
{
if( !_transform.valid() )
if( !_scene_group.valid() )
return;
// The transform node keeps a reference on this element, so ensure it is
// deleted.
BOOST_FOREACH(osg::Group* parent, _transform->getParents())
for(osg::Group* parent: _scene_group->getParents())
{
parent->removeChild(_transform.get());
parent->removeChild(_scene_group.get());
}
// Hide in case someone still holds a reference
setVisible(false);
removeListener();
_parent = 0;
_transform = 0;
_parent = nullptr;
_scene_group = nullptr;
}
//----------------------------------------------------------------------------
@@ -245,29 +244,8 @@ namespace canvas
//----------------------------------------------------------------------------
void Element::update(double dt)
{
if( !isVisible() )
return;
// Trigger matrix update
getMatrix();
// Update bounding box on manual update (manual updates pass zero dt)
if( dt == 0 && _drawable )
_drawable->getBound();
if( (_attributes_dirty & BLEND_FUNC) && _transform.valid() )
{
parseBlendFunc(
_transform->getOrCreateStateSet(),
_node->getChild("blend-source"),
_node->getChild("blend-destination"),
_node->getChild("blend-source-rgb"),
_node->getChild("blend-destination-rgb"),
_node->getChild("blend-source-alpha"),
_node->getChild("blend-destination-alpha")
);
_attributes_dirty &= ~BLEND_FUNC;
}
if( isVisible() )
updateImpl(dt);
}
//----------------------------------------------------------------------------
@@ -294,8 +272,7 @@ namespace canvas
//----------------------------------------------------------------------------
void Element::setFocus()
{
CanvasPtr canvas = _canvas.lock();
if( canvas )
if( auto canvas = _canvas.lock() )
canvas->setFocusElement(this);
}
@@ -339,7 +316,8 @@ namespace canvas
if( listeners == _listener.end() )
return false;
BOOST_FOREACH(EventListener const& listener, listeners->second)
for(auto const& listener: listeners->second)
{
try
{
listener(event);
@@ -352,6 +330,7 @@ namespace canvas
"canvas::Element: event handler error: '" << ex.what() << "'"
);
}
}
return true;
}
@@ -393,9 +372,9 @@ namespace canvas
getBoundingBox()
#endif
.contains(osg::Vec3f(local_pos, 0));
else if( _transform.valid() )
else if( _scene_group.valid() )
// ... for other elements, i.e. groups only a bounding sphere is available
return _transform->getBound().contains(osg::Vec3f(parent_pos, 0));
return _scene_group->getBound().contains(osg::Vec3f(parent_pos, 0));
else
return false;
}
@@ -404,34 +383,32 @@ namespace canvas
//----------------------------------------------------------------------------
void Element::setVisible(bool visible)
{
if( _transform.valid() )
if( _scene_group.valid() )
// TODO check if we need another nodemask
_transform->setNodeMask(visible ? 0xffffffff : 0);
_scene_group->setNodeMask(visible ? 0xffffffff : 0);
}
//----------------------------------------------------------------------------
bool Element::isVisible() const
{
return _transform.valid() && _transform->getNodeMask() != 0;
return _scene_group.valid() && _scene_group->getNodeMask() != 0;
}
//----------------------------------------------------------------------------
osg::MatrixTransform* Element::getMatrixTransform()
osg::MatrixTransform* Element::getSceneGroup() const
{
return _transform.get();
}
//----------------------------------------------------------------------------
osg::MatrixTransform const* Element::getMatrixTransform() const
{
return _transform.get();
return _scene_group.get();
}
//----------------------------------------------------------------------------
osg::Vec2f Element::posToLocal(const osg::Vec2f& pos) const
{
getMatrix();
const osg::Matrix& m = _transform->getInverseMatrix();
if( !_scene_group )
// TODO log warning?
return pos;
updateMatrix();
const osg::Matrix& m = _scene_group->getInverseMatrix();
return osg::Vec2f
(
m(0, 0) * pos[0] + m(1, 0) * pos[1] + m(3, 0),
@@ -484,9 +461,6 @@ namespace canvas
{
if( child->getNameString() == NAME_TRANSFORM )
{
if( !_transform.valid() )
return;
if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
{
SG_LOG
@@ -523,7 +497,7 @@ namespace canvas
if( parent == _node )
{
const std::string& name = child->getNameString();
if( boost::starts_with(name, "data-") )
if( strutils::starts_with(name, "data-") )
return;
else if( StyleInfo const* style_info = getStyleInfo(name) )
{
@@ -538,7 +512,7 @@ namespace canvas
}
else if( name == "update" )
return update(0);
else if( boost::starts_with(name, "blend-") )
else if( strutils::starts_with(name, "blend-") )
return (void)(_attributes_dirty |= BLEND_FUNC);
}
else if( parent
@@ -562,6 +536,10 @@ namespace canvas
//----------------------------------------------------------------------------
void Element::setClip(const std::string& clip)
{
if( !_scene_group )
// TODO warn?
return;
osg::StateSet* ss = getOrCreateStateSet();
if( !ss )
return;
@@ -575,8 +553,8 @@ namespace canvas
// TODO generalize CSS property parsing
const std::string RECT("rect(");
if( !boost::ends_with(clip, ")")
|| !boost::starts_with(clip, RECT) )
if( !strutils::ends_with(clip, ")")
|| !strutils::starts_with(clip, RECT) )
{
SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
return;
@@ -616,7 +594,7 @@ namespace canvas
}
if( !_scissor )
_scissor = new RelativeScissor(_transform.get());
_scissor = new RelativeScissor(_scene_group.get());
// <top>, <right>, <bottom>, <left>
_scissor->x() = values[3];
@@ -640,6 +618,27 @@ namespace canvas
_scissor->_coord_reference = rf;
}
//----------------------------------------------------------------------------
void Element::setRotation(unsigned int index, double r)
{
_node->getChild(NAME_TRANSFORM, index, true)->setDoubleValue("rot", r);
}
//----------------------------------------------------------------------------
void Element::setTranslation(unsigned int index, double x, double y)
{
SGPropertyNode* tf = _node->getChild(NAME_TRANSFORM, index, true);
tf->getChild("t", 0, true)->setDoubleValue(x);
tf->getChild("t", 1, true)->setDoubleValue(y);
}
//----------------------------------------------------------------------------
void Element::setTransformEnabled(unsigned int index, bool enabled)
{
SGPropertyNode* tf = _node->getChild(NAME_TRANSFORM, index, true);
tf->setBoolValue("enabled", enabled);
}
//----------------------------------------------------------------------------
osg::BoundingBox Element::getBoundingBox() const
{
@@ -652,8 +651,8 @@ namespace canvas
osg::BoundingBox bb;
if( _transform.valid() )
bb.expandBy(_transform->getBound());
if( _scene_group.valid() )
bb.expandBy( _scene_group->getBound() );
return bb;
}
@@ -687,70 +686,11 @@ namespace canvas
//----------------------------------------------------------------------------
osg::Matrix Element::getMatrix() const
{
if( !_transform )
if( !_scene_group )
return osg::Matrix::identity();
if( !(_attributes_dirty & TRANSFORM) )
return _transform->getMatrix();
osg::Matrix m;
for( size_t i = 0; i < _transform_types.size(); ++i )
{
// Skip unused indizes...
if( _transform_types[i] == TT_NONE )
continue;
SGPropertyNode* tf_node = _node->getChild("tf", i, true);
// Build up the matrix representation of the current transform node
osg::Matrix tf;
switch( _transform_types[i] )
{
case TT_MATRIX:
tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
tf_node->getDoubleValue("m[1]", 0),
0,
tf_node->getDoubleValue("m[6]", 0),
tf_node->getDoubleValue("m[2]", 0),
tf_node->getDoubleValue("m[3]", 1),
0,
tf_node->getDoubleValue("m[7]", 0),
0,
0,
1,
0,
tf_node->getDoubleValue("m[4]", 0),
tf_node->getDoubleValue("m[5]", 0),
0,
tf_node->getDoubleValue("m[8]", 1) );
break;
case TT_TRANSLATE:
tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
tf_node->getDoubleValue("t[1]", 0),
0 ) );
break;
case TT_ROTATE:
tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
break;
case TT_SCALE:
{
float sx = tf_node->getDoubleValue("s[0]", 1);
// sy defaults to sx...
tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
break;
}
default:
break;
}
m.postMult( tf );
}
_transform->setMatrix(m);
_attributes_dirty &= ~TRANSFORM;
return m;
updateMatrix();
return _scene_group->getMatrix();
}
//----------------------------------------------------------------------------
@@ -764,11 +704,8 @@ namespace canvas
PropertyBasedElement(node),
_canvas( canvas ),
_parent( parent ),
_attributes_dirty( 0 ),
_transform( new osg::MatrixTransform ),
_style( parent_style ),
_scissor( 0 ),
_drawable( 0 )
_scene_group( new osg::MatrixTransform ),
_style( parent_style )
{
staticInit();
@@ -780,15 +717,15 @@ namespace canvas
);
// Ensure elements are drawn in order they appear in the element tree
_transform->getOrCreateStateSet()
->setRenderBinDetails
(
0,
"PreOrderBin",
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS
);
_scene_group
->getOrCreateStateSet()
->setRenderBinDetails(
0,
"PreOrderBin",
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS
);
_transform->setUserData( new OSGUserData(this) );
_scene_group->setUserData( new OSGUserData(this) );
}
//----------------------------------------------------------------------------
@@ -876,11 +813,21 @@ namespace canvas
void Element::setDrawable( osg::Drawable* drawable )
{
_drawable = drawable;
assert( _drawable );
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
if( !_drawable )
{
SG_LOG(SG_GL, SG_WARN, "canvas::Element::setDrawable: NULL drawable");
return;
}
if( !_scene_group )
{
SG_LOG(SG_GL, SG_WARN, "canvas::Element::setDrawable: NULL scenegroup");
return;
}
auto geode = new osg::Geode;
geode->addDrawable(_drawable);
_transform->addChild(geode);
_scene_group->addChild(geode);
}
//----------------------------------------------------------------------------
@@ -888,18 +835,109 @@ namespace canvas
{
if( _drawable.valid() )
return _drawable->getOrCreateStateSet();
if( _transform.valid() )
return _transform->getOrCreateStateSet();
return 0;
else if( _scene_group.valid() )
return _scene_group->getOrCreateStateSet();
else
return nullptr;
}
//----------------------------------------------------------------------------
void Element::setupStyle()
{
BOOST_FOREACH( Style::value_type style, _style )
for(auto const& style: _style)
setStyle(style.second);
}
//----------------------------------------------------------------------------
void Element::updateMatrix() const
{
if( !(_attributes_dirty & TRANSFORM) || !_scene_group )
return;
osg::Matrix m;
for( size_t i = 0; i < _transform_types.size(); ++i )
{
// Skip unused indizes...
if( _transform_types[i] == TT_NONE )
continue;
SGPropertyNode* tf_node = _node->getChild("tf", i, true);
if (!tf_node->getBoolValue("enabled", true)) {
continue; // skip disabled transforms
}
// Build up the matrix representation of the current transform node
osg::Matrix tf;
switch( _transform_types[i] )
{
case TT_MATRIX:
tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
tf_node->getDoubleValue("m[1]", 0),
0,
tf_node->getDoubleValue("m[6]", 0),
tf_node->getDoubleValue("m[2]", 0),
tf_node->getDoubleValue("m[3]", 1),
0,
tf_node->getDoubleValue("m[7]", 0),
0,
0,
1,
0,
tf_node->getDoubleValue("m[4]", 0),
tf_node->getDoubleValue("m[5]", 0),
0,
tf_node->getDoubleValue("m[8]", 1) );
break;
case TT_TRANSLATE:
tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
tf_node->getDoubleValue("t[1]", 0),
0 ) );
break;
case TT_ROTATE:
tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
break;
case TT_SCALE:
{
float sx = tf_node->getDoubleValue("s[0]", 1);
// sy defaults to sx...
tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
break;
}
default:
break;
}
m.postMult( tf );
}
_scene_group->setMatrix(m);
_attributes_dirty &= ~TRANSFORM;
}
//----------------------------------------------------------------------------
void Element::updateImpl(double dt)
{
updateMatrix();
// Update bounding box on manual update (manual updates pass zero dt)
if( dt == 0 && _drawable )
_drawable->getBound();
if( (_attributes_dirty & BLEND_FUNC) )
{
parseBlendFunc(
_scene_group->getOrCreateStateSet(),
_node->getChild("blend-source"),
_node->getChild("blend-destination"),
_node->getChild("blend-source-rgb"),
_node->getChild("blend-destination-rgb"),
_node->getChild("blend-source-alpha"),
_node->getChild("blend-destination-alpha")
);
_attributes_dirty &= ~BLEND_FUNC;
}
}
} // namespace canvas
} // namespace simgear

View File

@@ -24,14 +24,11 @@
#include <simgear/canvas/CanvasEvent.hxx>
#include <simgear/props/PropertyBasedElement.hxx>
#include <simgear/misc/stdint.hxx> // for uint32_t
#include <simgear/std/type_traits.hxx>
#include <osg/BoundingBox>
#include <osg/MatrixTransform>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace osg
{
class Drawable;
@@ -49,6 +46,7 @@ namespace canvas
public PropertyBasedElement
{
public:
using SceneGroupWeakPtr = osg::observer_ptr<osg::MatrixTransform>;
/**
* Store pointer to window as user data
@@ -61,9 +59,9 @@ namespace canvas
OSGUserData(ElementPtr element);
};
typedef boost::function<bool(Element&, const SGPropertyNode*)>
typedef std::function<bool(Element&, const SGPropertyNode*)>
StyleSetterFunc;
typedef boost::function<void(Element&, const SGPropertyNode*)>
typedef std::function<void(Element&, const SGPropertyNode*)>
StyleSetterFuncUnchecked;
struct StyleSetter:
public SGReferenced
@@ -94,7 +92,7 @@ namespace canvas
*
*/
virtual ~Element() = 0;
virtual void onDestroy();
void onDestroy() override;
ElementPtr getParent() const;
CanvasWeakPtr getCanvas() const;
@@ -104,7 +102,7 @@ namespace canvas
*
* @param dt Frame time in seconds
*/
virtual void update(double dt);
void update(double dt) override;
bool addEventListener(const std::string& type, const EventListener& cb);
virtual void clearEventListener();
@@ -142,19 +140,20 @@ namespace canvas
*/
virtual bool isVisible() const;
osg::MatrixTransform* getMatrixTransform();
osg::MatrixTransform const* getMatrixTransform() const;
/**
* Get the according group in the OSG scene graph
*/
// TODO ref_ptr
osg::MatrixTransform* getSceneGroup() const;
/**
* Transform position to local coordinages.
*/
osg::Vec2f posToLocal(const osg::Vec2f& pos) const;
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void valueChanged(SGPropertyNode * child);
void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override;
void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override;
void valueChanged(SGPropertyNode* child) override;
virtual bool setStyle( const SGPropertyNode* child,
const StyleInfo* style_info = 0 );
@@ -172,6 +171,22 @@ namespace canvas
*/
void setClipFrame(ReferenceFrame rf);
/**
*
*/
void setRotation(unsigned int index, double r);
/**
*
*/
void setTranslation(unsigned int index, double x, double y);
/**
*
*
*/
void setTransformEnabled(unsigned int index, bool enabled);
/**
* Get bounding box (may not be as tight as bounding box returned by
* #getTightBoundingBox)
@@ -201,13 +216,14 @@ namespace canvas
*/
template<typename Derived>
static
typename boost::enable_if<
boost::is_base_of<Element, Derived>,
std::enable_if_t<
std::is_base_of<Element, Derived>::value,
ElementPtr
>::type create( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& style = Style(),
Element* parent = NULL )
>
create( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& style = Style(),
Element* parent = NULL )
{
return ElementPtr( new Derived(canvas, node, style, parent) );
}
@@ -235,13 +251,13 @@ namespace canvas
CanvasWeakPtr _canvas;
ElementWeakPtr _parent;
mutable uint32_t _attributes_dirty;
mutable uint32_t _attributes_dirty = 0;
osg::observer_ptr<osg::MatrixTransform> _transform;
std::vector<TransformType> _transform_types;
SceneGroupWeakPtr _scene_group;
std::vector<TransformType> _transform_types;
Style _style;
RelativeScissor *_scissor;
RelativeScissor *_scissor = nullptr;
typedef std::vector<EventListener> Listener;
typedef std::map<int, Listener> ListenerMap;
@@ -300,7 +316,7 @@ namespace canvas
StyleSetter
addStyle( const std::string& name,
const std::string& type,
const boost::function<void (Derived&, T2)>& setter,
const std::function<void (Derived&, T2)>& setter,
bool inheritable = true )
{
StyleInfo& style_info = _style_setters[ name ];
@@ -326,13 +342,10 @@ namespace canvas
if( style->func )
style = style->next = new StyleSetter;
style->func = boost::bind
(
&type_match<Derived>::call,
_1,
_2,
bindStyleSetter<T1>(name, setter)
);
style->func = std::bind(&type_match<Derived>::call,
std::placeholders::_1,
std::placeholders::_2,
bindStyleSetter<T1>(name, setter));
return *style;
}
@@ -344,7 +357,7 @@ namespace canvas
StyleSetter
addStyle( const std::string& name,
const std::string& type,
const boost::function<void (Derived&, T)>& setter,
const std::function<void (Derived&, T)>& setter,
bool inheritable = true )
{
return addStyle<T, T>(name, type, setter, inheritable);
@@ -365,7 +378,7 @@ namespace canvas
(
name,
type,
boost::function<void (Derived&, T)>(setter),
std::function<void (Derived&, T)>(setter),
inheritable
);
}
@@ -386,7 +399,7 @@ namespace canvas
(
name,
type,
boost::function<void (Derived&, T2)>(setter),
std::function<void (Derived&, T2)>(setter),
inheritable
);
}
@@ -405,7 +418,7 @@ namespace canvas
(
name,
type,
boost::function<void (Derived&, const std::string&)>(setter),
std::function<void (Derived&, const std::string&)>(setter),
inheritable
);
}
@@ -468,7 +481,7 @@ namespace canvas
StyleSetter
addStyle( const std::string& name,
const std::string& type,
const boost::function<void (Other&, T2)>& setter,
const std::function<void (Other&, T2)>& setter,
OtherRef Derived::*instance_ref,
bool inheritable = true )
{
@@ -498,7 +511,7 @@ namespace canvas
(
name,
type,
boost::function<void (Other&, const std::string&)>(setter),
std::function<void (Other&, const std::string&)>(setter),
instance_ref,
inheritable
);
@@ -506,44 +519,37 @@ namespace canvas
template<typename T, class Derived, class Other, class OtherRef>
static
boost::function<void (Derived&, T)>
std::function<void (Derived&, T)>
bindOther( void (Other::*setter)(T), OtherRef Derived::*instance_ref )
{
return boost::bind(setter, boost::bind(instance_ref, _1), _2);
return std::bind(setter,
std::bind(instance_ref, std::placeholders::_1),
std::placeholders::_2);
}
template<typename T, class Derived, class Other, class OtherRef>
static
boost::function<void (Derived&, T)>
bindOther( const boost::function<void (Other&, T)>& setter,
std::function<void (Derived&, T)>
bindOther( const std::function<void (Other&, T)>& setter,
OtherRef Derived::*instance_ref )
{
return boost::bind
(
setter,
boost::bind
(
&reference_from_pointer<Other, OtherRef>,
boost::bind(instance_ref, _1)
),
_2
);
return std::bind(setter,
std::bind(&reference_from_pointer<Other, OtherRef>,
std::bind(instance_ref, std::placeholders::_1)),
std::placeholders::_2);
}
template<typename T1, typename T2, class Derived>
static
StyleSetterFuncUnchecked
bindStyleSetter( const std::string& name,
const boost::function<void (Derived&, T2)>& setter )
const std::function<void (Derived&, T2)>& setter )
{
return boost::bind
(
setter,
// We will only call setters with Derived instances, so we can safely
// cast here.
boost::bind(&derived_cast<Derived>, _1),
boost::bind(&getValue<T1>, _2)
);
return std::bind(setter,
// We will only call setters with Derived instances, so we can safely
// cast here.
std::bind(&derived_cast<Derived>, std::placeholders::_1),
std::bind(&getValue<T1>, std::placeholders::_2));
}
bool isStyleEmpty(const SGPropertyNode* child) const;
@@ -568,11 +574,15 @@ namespace canvas
void setupStyle();
void updateMatrix() const;
virtual void updateImpl(double dt);
private:
osg::ref_ptr<osg::Drawable> _drawable;
Element(const Element&);// = delete
Element(const Element&) = delete;
template<class Derived>
static Derived& derived_cast(Element& el)

View File

@@ -1,4 +1,5 @@
// A group of 2D Canvas elements
///@file
/// A group of 2D Canvas elements
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,18 +17,17 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasGroup.hxx"
#include "CanvasImage.hxx"
#include "CanvasMap.hxx"
#include "CanvasPath.hxx"
#include "CanvasText.hxx"
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/events/MouseEvent.hxx>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/lambda/core.hpp>
namespace simgear
{
namespace canvas
@@ -46,7 +46,7 @@ namespace canvas
ElementFactories Group::_child_factories;
const std::string Group::TYPE_NAME = "group";
void warnTransformExpired(const char* member_name)
void warnSceneGroupExpired(const char* member_name)
{
SG_LOG( SG_GENERAL,
SG_WARN,
@@ -133,63 +133,58 @@ namespace canvas
//----------------------------------------------------------------------------
ElementPtr Group::getElementById(const std::string& id)
{
if( !_transform.valid() )
if( !_scene_group.valid() )
{
warnTransformExpired("getElementById");
return ElementPtr();
warnSceneGroupExpired("getElementById");
return {};
}
std::vector<GroupPtr> groups;
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
// TODO check search algorithm. Not completely breadth-first and might be
// possible with using less dynamic memory
std::vector<GroupPtr> child_groups;
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
{
const ElementPtr& el = getChildByIndex(i);
if( el->get<std::string>("id") == id )
return el;
Group* group = dynamic_cast<Group*>(el.get());
if( group )
groups.push_back(group);
if( Group* child_group = dynamic_cast<Group*>(el.get()) )
child_groups.push_back(child_group);
}
BOOST_FOREACH( GroupPtr group, groups )
for(auto group: child_groups)
{
ElementPtr el = group->getElementById(id);
if( el )
if( ElementPtr el = group->getElementById(id) )
return el;
}
return ElementPtr();
return {};
}
//----------------------------------------------------------------------------
void Group::clearEventListener()
{
if( !_transform.valid() )
return warnTransformExpired("clearEventListener");
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
getChildByIndex(i)->clearEventListener();
Element::clearEventListener();
}
//----------------------------------------------------------------------------
void Group::update(double dt)
{
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
getChildByIndex(i)->update(dt);
if( !_scene_group.valid() )
return warnSceneGroupExpired("clearEventListener");
Element::update(dt);
// TODO should this be recursive?
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
getChildByIndex(i)->clearEventListener();
}
//----------------------------------------------------------------------------
bool Group::traverse(EventVisitor& visitor)
{
// Iterate in reverse order as last child is displayed on top
for(size_t i = _transform->getNumChildren(); i --> 0;)
if( _scene_group.valid() )
{
if( getChildByIndex(i)->accept(visitor) )
return true;
// Iterate in reverse order as last child is displayed on top
for(size_t i = _scene_group->getNumChildren(); i --> 0;)
{
if( getChildByIndex(i)->accept(visitor) )
return true;
}
}
return false;
}
@@ -204,13 +199,13 @@ namespace canvas
bool handled = setStyleImpl(style, style_info);
if( style_info->inheritable )
{
if( !_transform.valid() )
if( !_scene_group.valid() )
{
warnTransformExpired("setStyle");
warnSceneGroupExpired("setStyle");
return false;
}
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
handled |= getChildByIndex(i)->setStyle(style, style_info);
}
@@ -220,26 +215,20 @@ namespace canvas
//----------------------------------------------------------------------------
osg::BoundingBox Group::getTransformedBounds(const osg::Matrix& m) const
{
osg::BoundingBox bb;
if( !_transform.valid() )
if( !_scene_group.valid() )
{
warnTransformExpired("getTransformedBounds");
return bb;
warnSceneGroupExpired("getTransformedBounds");
return {};
}
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
osg::BoundingBox bb;
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
{
const ElementPtr& child = getChildByIndex(i);
if( !child->getMatrixTransform()->getNodeMask() )
auto child = getChildByIndex(i);
if( !child || !child->isVisible() )
continue;
bb.expandBy
(
child->getTransformedBounds
(
child->getMatrixTransform()->getMatrix() * m
)
);
bb.expandBy( child->getTransformedBounds(child->getMatrix() * m) );
}
return bb;
@@ -255,6 +244,15 @@ namespace canvas
return ElementFactory();
}
//----------------------------------------------------------------------------
void Group::updateImpl(double dt)
{
Element::updateImpl(dt);
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
getChildByIndex(i)->update(dt);
}
//----------------------------------------------------------------------------
void Group::childAdded(SGPropertyNode* child)
{
@@ -264,13 +262,13 @@ namespace canvas
ElementFactory child_factory = getChildFactory( child->getNameString() );
if( child_factory )
{
if( !_transform.valid() )
return warnTransformExpired("childAdded");
if( !_scene_group.valid() )
return warnSceneGroupExpired("childAdded");
ElementPtr element = child_factory(_canvas, child, _style, this);
// Add to osg scene graph...
_transform->addChild( element->getMatrixTransform() );
_scene_group->addChild(element->getSceneGroup());
// ...and ensure correct ordering
handleZIndexChanged(element);
@@ -291,7 +289,7 @@ namespace canvas
if( getChildFactory(node->getNameString()) )
{
if( !_transform.valid() )
if( !_scene_group.valid() )
// If transform is destroyed also all children are destroyed, so we can
// not do anything here.
return;
@@ -321,7 +319,7 @@ namespace canvas
void Group::childChanged(SGPropertyNode* node)
{
SGPropertyNode* parent = node->getParent();
SGPropertyNode* grand_parent = parent ? parent->getParent() : NULL;
SGPropertyNode* grand_parent = parent ? parent->getParent() : nullptr;
if( grand_parent == _node
&& node->getNameString() == "z-index" )
@@ -331,16 +329,18 @@ namespace canvas
//----------------------------------------------------------------------------
void Group::handleZIndexChanged(ElementPtr child, int z_index)
{
if( !child || !_transform.valid() )
if( !child || !_scene_group.valid() )
return;
osg::ref_ptr<osg::MatrixTransform> tf = child->getMatrixTransform();
size_t index = _transform->getChildIndex(tf),
// Keep reference to prevent deleting while removing and re-inserting later
osg::ref_ptr<osg::MatrixTransform> tf = child->getSceneGroup();
size_t index = _scene_group->getChildIndex(tf),
index_new = index;
for(;; ++index_new)
{
if( index_new + 1 == _transform->getNumChildren() )
if( index_new + 1 == _scene_group->getNumChildren() )
break;
// Move to end of block with same index (= move upwards until the next
@@ -367,13 +367,13 @@ namespace canvas
return;
}
_transform->removeChild(index);
_transform->insertChild(index_new, tf);
_scene_group->removeChild(index);
_scene_group->insertChild(index_new, tf);
SG_LOG
(
SG_GENERAL,
SG_INFO,
SG_DEBUG,
"canvas::Group: Moved element " << index << " to position " << index_new
);
}
@@ -381,24 +381,27 @@ namespace canvas
//----------------------------------------------------------------------------
ElementPtr Group::getChildByIndex(size_t index) const
{
assert(_transform.valid());
OSGUserData* ud =
static_cast<OSGUserData*>(_transform->getChild(index)->getUserData());
assert(ud);
return ud->element;
assert( _scene_group.valid() );
auto child = _scene_group->getChild(index);
if( !child )
return {};
auto ud = static_cast<OSGUserData*>(child->getUserData());
return ud ? ud->element : ElementPtr();
}
//----------------------------------------------------------------------------
ElementPtr Group::findChild( const SGPropertyNode* node,
const std::string& id ) const
{
if( !_transform.valid() )
if( !_scene_group.valid() )
{
warnTransformExpired("findChild");
return ElementPtr();
warnSceneGroupExpired("findChild");
return {};
}
for(size_t i = 0; i < _transform->getNumChildren(); ++i)
for(size_t i = 0; i < _scene_group->getNumChildren(); ++i)
{
ElementPtr el = getChildByIndex(i);
@@ -414,7 +417,7 @@ namespace canvas
}
}
return ElementPtr();
return {};
}
} // namespace canvas

View File

@@ -1,4 +1,5 @@
// A group of 2D Canvas elements
///@file
/// A group of 2D Canvas elements
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -86,16 +87,15 @@ namespace canvas
*/
ElementPtr getElementById(const std::string& id);
virtual void clearEventListener();
void clearEventListener() override;
virtual void update(double dt);
bool traverse(EventVisitor& visitor) override;
virtual bool traverse(EventVisitor& visitor);
bool setStyle( const SGPropertyNode* child,
const StyleInfo* style_info = 0 ) override;
virtual bool setStyle( const SGPropertyNode* child,
const StyleInfo* style_info = 0 );
virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
osg::BoundingBox
getTransformedBounds(const osg::Matrix& m) const override;
protected:
@@ -107,9 +107,11 @@ namespace canvas
*/
virtual ElementFactory getChildFactory(const std::string& type) const;
virtual void childAdded(SGPropertyNode * child);
virtual void childRemoved(SGPropertyNode * child);
virtual void childChanged(SGPropertyNode * child);
void updateImpl(double dt) override;
void childAdded(SGPropertyNode * child) override;
void childRemoved(SGPropertyNode * child) override;
void childChanged(SGPropertyNode * child) override;
void handleZIndexChanged(ElementPtr child, int z_index = 0);

View File

@@ -1,4 +1,5 @@
// An image on the Canvas
///@file
/// An image on the Canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasImage.hxx"
#include <simgear/canvas/Canvas.hxx>
@@ -115,9 +118,7 @@ namespace canvas
ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent),
_texture(new osg::Texture2D),
_node_src_rect( node->getNode("source", 0, true) ),
_src_rect(0,0),
_region(0,0)
_node_src_rect( node->getNode("source", 0, true) )
{
staticInit();
@@ -155,22 +156,207 @@ namespace canvas
//----------------------------------------------------------------------------
Image::~Image()
{
if( _http_request ) {
Canvas::getSystemAdapter()->getHTTPClient()->cancelRequest(_http_request, "image destroyed");
}
if( _http_request )
{
Canvas::getSystemAdapter()
->getHTTPClient()
->cancelRequest(_http_request, "image destroyed");
}
}
//----------------------------------------------------------------------------
void Image::update(double dt)
void Image::valueChanged(SGPropertyNode* child)
{
Element::update(dt);
// If the image is switched from invisible to visible, and it shows a
// canvas, we need to delay showing it by one frame to ensure the canvas is
// updated before the image is displayed.
//
// As canvas::Element handles and filters changes to the "visible" property
// we can not check this in Image::childChanged but instead have to override
// Element::valueChanged.
if( !isVisible()
&& child->getParent() == _node
&& child->getNameString() == "visible"
&& child->getBoolValue() )
{
CullCallback* cb =
#if OSG_VERSION_LESS_THAN(3,3,2)
static_cast<CullCallback*>
#else
dynamic_cast<CullCallback*>
#endif
( _geom->getCullCallback() );
if( cb )
cb->cullNextFrame();
}
Element::valueChanged(child);
}
//----------------------------------------------------------------------------
void Image::setSrcCanvas(CanvasPtr canvas)
{
CanvasPtr src_canvas = _src_canvas.lock(),
self_canvas = _canvas.lock();
if( src_canvas )
src_canvas->removeParentCanvas(self_canvas);
if( self_canvas )
self_canvas->removeChildCanvas(src_canvas);
_src_canvas = src_canvas = canvas;
_attributes_dirty |= SRC_CANVAS;
_geom->setCullCallback(canvas ? new CullCallback(canvas) : 0);
if( src_canvas )
{
setupDefaultDimensions();
if( self_canvas )
{
self_canvas->addChildCanvas(src_canvas);
src_canvas->addParentCanvas(self_canvas);
}
}
}
//----------------------------------------------------------------------------
CanvasWeakPtr Image::getSrcCanvas() const
{
return _src_canvas;
}
//----------------------------------------------------------------------------
void Image::setImage(osg::ref_ptr<osg::Image> img)
{
// remove canvas...
setSrcCanvas( CanvasPtr() );
_texture->setResizeNonPowerOfTwoHint(false);
_texture->setImage(img);
_texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
_texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
_geom->getOrCreateStateSet()
->setTextureAttributeAndModes(0, _texture);
if( img )
setupDefaultDimensions();
}
//----------------------------------------------------------------------------
void Image::setFill(const std::string& fill)
{
osg::Vec4 color(1,1,1,1);
if( !fill.empty() // If no color is given default to white
&& !parseColor(fill, color) )
return;
setFill(color);
}
//----------------------------------------------------------------------------
void Image::setFill(const osg::Vec4& color)
{
_colors->front() = color;
_colors->dirty();
}
//----------------------------------------------------------------------------
void Image::setOutset(const std::string& outset)
{
_outset = CSSBorder::parse(outset);
_attributes_dirty |= DEST_SIZE;
}
//----------------------------------------------------------------------------
void Image::setPreserveAspectRatio(const std::string& scale)
{
_preserve_aspect_ratio = SVGpreserveAspectRatio::parse(scale);
_attributes_dirty |= SRC_RECT;
}
//----------------------------------------------------------------------------
void Image::setSourceRect(const SGRect<float>& sourceRect)
{
_attributes_dirty |= SRC_RECT;
_src_rect = sourceRect;
}
//----------------------------------------------------------------------------
void Image::setSlice(const std::string& slice)
{
_slice = CSSBorder::parse(slice);
_attributes_dirty |= SRC_RECT | DEST_SIZE;
}
//----------------------------------------------------------------------------
void Image::setSliceWidth(const std::string& width)
{
_slice_width = CSSBorder::parse(width);
_attributes_dirty |= DEST_SIZE;
}
//----------------------------------------------------------------------------
const SGRect<float>& Image::getRegion() const
{
return _region;
}
//----------------------------------------------------------------------------
bool Image::handleEvent(const EventPtr& event)
{
bool handled = Element::handleEvent(event);
CanvasPtr src_canvas = _src_canvas.lock();
if( !src_canvas )
return handled;
if( MouseEventPtr mouse_event = dynamic_cast<MouseEvent*>(event.get()) )
{
mouse_event.reset( new MouseEvent(*mouse_event) );
mouse_event->client_pos = mouse_event->local_pos
- toOsg(_region.getMin());
osg::Vec2f size(_region.width(), _region.height());
if( _outset.isValid() )
{
CSSBorder::Offsets outset =
_outset.getAbsOffsets(getTextureDimensions());
mouse_event->client_pos += osg::Vec2f(outset.l, outset.t);
size.x() += outset.l + outset.r;
size.y() += outset.t + outset.b;
}
// Scale event pos according to canvas view size vs. displayed/screen size
mouse_event->client_pos.x() *= src_canvas->getViewWidth() / size.x();
mouse_event->client_pos.y() *= src_canvas->getViewHeight()/ size.y();
mouse_event->local_pos = mouse_event->client_pos;
handled |= src_canvas->handleMouseEvent(mouse_event);
}
else if( KeyboardEventPtr keyboard_event =
dynamic_cast<KeyboardEvent*>(event.get()) )
{
handled |= src_canvas->handleKeyboardEvent(keyboard_event);
}
return handled;
}
//----------------------------------------------------------------------------
void Image::updateImpl(double dt)
{
Element::updateImpl(dt);
osg::Texture2D* texture = dynamic_cast<osg::Texture2D*>
(
_geom->getOrCreateStateSet()
->getTextureAttribute(0, osg::StateAttribute::TEXTURE)
);
simgear::canvas::CanvasPtr canvas = _src_canvas.lock();
auto canvas = _src_canvas.lock();
if( (_attributes_dirty & SRC_CANVAS)
// check if texture has changed (eg. due to resizing)
@@ -400,175 +586,6 @@ namespace canvas
}
}
//----------------------------------------------------------------------------
void Image::valueChanged(SGPropertyNode* child)
{
// If the image is switched from invisible to visible, and it shows a
// canvas, we need to delay showing it by one frame to ensure the canvas is
// updated before the image is displayed.
//
// As canvas::Element handles and filters changes to the "visible" property
// we can not check this in Image::childChanged but instead have to override
// Element::valueChanged.
if( !isVisible()
&& child->getParent() == _node
&& child->getNameString() == "visible"
&& child->getBoolValue() )
{
CullCallback* cb =
#if OSG_VERSION_LESS_THAN(3,3,2)
static_cast<CullCallback*>
#else
dynamic_cast<CullCallback*>
#endif
( _geom->getCullCallback() );
if( cb )
cb->cullNextFrame();
}
Element::valueChanged(child);
}
//----------------------------------------------------------------------------
void Image::setSrcCanvas(CanvasPtr canvas)
{
CanvasPtr src_canvas = _src_canvas.lock(),
self_canvas = _canvas.lock();
if( src_canvas )
src_canvas->removeParentCanvas(self_canvas);
if( self_canvas )
self_canvas->removeChildCanvas(src_canvas);
_src_canvas = src_canvas = canvas;
_attributes_dirty |= SRC_CANVAS;
_geom->setCullCallback(canvas ? new CullCallback(canvas) : 0);
if( src_canvas )
{
setupDefaultDimensions();
if( self_canvas )
{
self_canvas->addChildCanvas(src_canvas);
src_canvas->addParentCanvas(self_canvas);
}
}
}
//----------------------------------------------------------------------------
CanvasWeakPtr Image::getSrcCanvas() const
{
return _src_canvas;
}
//----------------------------------------------------------------------------
void Image::setImage(osg::ref_ptr<osg::Image> img)
{
// remove canvas...
setSrcCanvas( CanvasPtr() );
_texture->setResizeNonPowerOfTwoHint(false);
_texture->setImage(img);
_texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
_texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
_geom->getOrCreateStateSet()
->setTextureAttributeAndModes(0, _texture);
if( img )
setupDefaultDimensions();
}
//----------------------------------------------------------------------------
void Image::setFill(const std::string& fill)
{
osg::Vec4 color(1,1,1,1);
if( !fill.empty() // If no color is given default to white
&& !parseColor(fill, color) )
return;
_colors->front() = color;
_colors->dirty();
}
//----------------------------------------------------------------------------
void Image::setOutset(const std::string& outset)
{
_outset = CSSBorder::parse(outset);
_attributes_dirty |= DEST_SIZE;
}
//----------------------------------------------------------------------------
void Image::setPreserveAspectRatio(const std::string& scale)
{
_preserve_aspect_ratio = SVGpreserveAspectRatio::parse(scale);
_attributes_dirty |= SRC_RECT;
}
//----------------------------------------------------------------------------
void Image::setSlice(const std::string& slice)
{
_slice = CSSBorder::parse(slice);
_attributes_dirty |= SRC_RECT | DEST_SIZE;
}
//----------------------------------------------------------------------------
void Image::setSliceWidth(const std::string& width)
{
_slice_width = CSSBorder::parse(width);
_attributes_dirty |= DEST_SIZE;
}
//----------------------------------------------------------------------------
const SGRect<float>& Image::getRegion() const
{
return _region;
}
//----------------------------------------------------------------------------
bool Image::handleEvent(const EventPtr& event)
{
bool handled = Element::handleEvent(event);
CanvasPtr src_canvas = _src_canvas.lock();
if( !src_canvas )
return handled;
if( MouseEventPtr mouse_event = dynamic_cast<MouseEvent*>(event.get()) )
{
mouse_event.reset( new MouseEvent(*mouse_event) );
mouse_event->client_pos = mouse_event->local_pos
- toOsg(_region.getMin());
osg::Vec2f size(_region.width(), _region.height());
if( _outset.isValid() )
{
CSSBorder::Offsets outset =
_outset.getAbsOffsets(getTextureDimensions());
mouse_event->client_pos += osg::Vec2f(outset.l, outset.t);
size.x() += outset.l + outset.r;
size.y() += outset.t + outset.b;
}
// Scale event pos according to canvas view size vs. displayed/screen size
mouse_event->client_pos.x() *= src_canvas->getViewWidth() / size.x();
mouse_event->client_pos.y() *= src_canvas->getViewHeight()/ size.y();
mouse_event->local_pos = mouse_event->client_pos;
handled |= src_canvas->handleMouseEvent(mouse_event);
}
else if( KeyboardEventPtr keyboard_event =
dynamic_cast<KeyboardEvent*>(event.get()) )
{
handled |= src_canvas->handleKeyboardEvent(keyboard_event);
}
return handled;
}
//----------------------------------------------------------------------------
void Image::childChanged(SGPropertyNode* child)
{
@@ -619,7 +636,9 @@ namespace canvas
// Abort pending request
if( _http_request )
{
Canvas::getSystemAdapter()->getHTTPClient()->cancelRequest(_http_request, "setting new image");
Canvas::getSystemAdapter()
->getHTTPClient()
->cancelRequest(_http_request, "setting new image");
_http_request.reset();
}
@@ -819,5 +838,143 @@ namespace canvas
return false;
}
void Image::fillRect(const SGRect<int>& rect, const std::string& c)
{
osg::Vec4 color(1,1,1,1);
if(!c.empty() && !parseColor(c, color))
return;
fillRect(rect, color);
}
void fillRow(GLubyte* row, GLuint pixel, GLuint width, GLuint pixelBytes)
{
GLubyte* dst = row;
for (int x = 0; x < width; ++x) {
memcpy(dst, &pixel, pixelBytes);
dst += pixelBytes;
}
}
SGRect<int> intersectRect(const SGRect<int>& a, const SGRect<int>& b)
{
SGVec2<int> m1 = max(a.getMin(), b.getMin());
SGVec2<int> m2 = min(a.getMax(), b.getMax());
return SGRect<int>(m1, m2);
}
void Image::fillRect(const SGRect<int>& rect, const osg::Vec4& color)
{
osg::ref_ptr<osg::Image> image = _texture->getImage();
if (!image) {
allocateImage();
image = _texture->getImage();
}
if (image->getDataVariance() != osg::Object::DYNAMIC) {
image->setDataVariance(osg::Object::DYNAMIC);
}
const auto format = image->getInternalTextureFormat();
auto clippedRect = intersectRect(rect, SGRect<int>(0, 0, image->s(), image->t()));
if ((clippedRect.width() == 0) || (clippedRect.height() == 0)) {
return;
}
GLubyte* rowData = nullptr;
size_t rowByteSize = 0;
GLuint pixelWidth = clippedRect.width();
GLuint pixel = 0;
GLuint pixelBytes = 0;
switch (format) {
case GL_RGBA8:
case GL_RGBA:
rowByteSize = pixelWidth * 4;
rowData = static_cast<GLubyte*>(alloca(rowByteSize));
// assume litte-endian, so read out backwards, hence when we memcpy
// the data, it ends up in RGBA order
pixel = color.asABGR();
pixelBytes = 4;
fillRow(rowData, pixel, pixelWidth, pixelBytes);
break;
case GL_RGB8:
case GL_RGB:
rowByteSize = pixelWidth * 3;
rowData = static_cast<GLubyte*>(alloca(rowByteSize));
pixel = color.asABGR();
pixelBytes = 3;
fillRow(rowData, pixel, pixelWidth, pixelBytes);
break;
default:
SG_LOG(SG_IO, SG_WARN, "Image::fillRect: unsupported internal image format:" << format);
return;
}
for (int row=clippedRect.t(); row < clippedRect.b(); ++row) {
GLubyte* imageData = image->data(clippedRect.l(), row);
memcpy(imageData, rowData, rowByteSize);
}
image->dirty();
auto c = getCanvas().lock();
c->enableRendering(true); // force a repaint
}
void Image::setPixel(int x, int y, const std::string& c)
{
osg::Vec4 color(1,1,1,1);
if(!c.empty() && !parseColor(c, color))
return;
setPixel(x, y, color);
}
void Image::setPixel(int x, int y, const osg::Vec4& color)
{
osg::ref_ptr<osg::Image> image = _texture->getImage();
if (!image) {
allocateImage();
image = _texture->getImage();
}
if (image->getDataVariance() != osg::Object::DYNAMIC) {
image->setDataVariance(osg::Object::DYNAMIC);
}
image->setColor(color, x, y);
}
void Image::dirtyPixels()
{
osg::ref_ptr<osg::Image> image = _texture->getImage();
if (!image)
return;
image->dirty();
auto c = getCanvas().lock();
c->enableRendering(true); // force a repaint
}
void Image::allocateImage()
{
osg::Image* image = new osg::Image;
// default to RGBA
image->allocateImage(_node->getIntValue("size[0]"), _node->getIntValue("size[1]"), 1, GL_RGBA, GL_UNSIGNED_BYTE);
image->setInternalTextureFormat(GL_RGBA);
_texture->setImage(image);
}
osg::ref_ptr<osg::Image> Image::getImage() const
{
if (!_texture)
return {};
return _texture->getImage();
}
} // namespace canvas
} // namespace simgear

View File

@@ -1,4 +1,5 @@
// An image on the Canvas
///@file
/// An image on the Canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -53,14 +54,14 @@ namespace canvas
ElementWeakPtr parent = 0 );
virtual ~Image();
virtual void update(double dt);
virtual void valueChanged(SGPropertyNode* child);
void valueChanged(SGPropertyNode* child) override;
void setSrcCanvas(CanvasPtr canvas);
CanvasWeakPtr getSrcCanvas() const;
void setImage(osg::ref_ptr<osg::Image> img);
void setFill(const std::string& fill);
void setFill(const osg::Vec4& color);
/**
* @see http://www.w3.org/TR/css3-background/#border-image-outset
@@ -93,10 +94,36 @@ namespace canvas
const SGRect<float>& getRegion() const;
bool handleEvent(const EventPtr& event);
bool handleEvent(const EventPtr& event) override;
/**
*
*/
void setSourceRect(const SGRect<float>& sourceRect);
/**
* fill the specified rectangle of the image, with an RGB value
*/
void fillRect(const SGRect<int>& rect, const std::string& color);
/**
* fill the specified rectangle of the image, with an RGB value
*/
void fillRect(const SGRect<int>& rect, const osg::Vec4& color);
void setPixel(int x, int y, const std::string& color);
void setPixel(int x, int y, const osg::Vec4& color);
/**
* mark the image pixels as modified, so the canvas is re-painted
*/
void dirtyPixels();
osg::ref_ptr<osg::Image> getImage() const;
// void setRow(int row, int offset, )
protected:
enum ImageAttributes
{
SRC_RECT = LAST_ATTRIBUTE << 1, // Source image rectangle
@@ -104,7 +131,9 @@ namespace canvas
SRC_CANVAS = DEST_SIZE << 1
};
virtual void childChanged(SGPropertyNode * child);
void updateImpl(double dt) override;
void childChanged(SGPropertyNode * child) override;
void setupDefaultDimensions();
SGRect<int> getTextureDimensions() const;
@@ -118,6 +147,8 @@ namespace canvas
HTTP::Request& request,
const std::string& type );
void allocateImage();
osg::ref_ptr<osg::Texture2D> _texture;
// TODO optionally forward events to canvas
CanvasWeakPtr _src_canvas;
@@ -129,9 +160,9 @@ namespace canvas
osg::ref_ptr<osg::Vec2Array> _texCoords;
osg::ref_ptr<osg::Vec4Array> _colors;
SGPropertyNode *_node_src_rect;
SGRect<float> _src_rect,
_region;
SGPropertyNode *_node_src_rect = nullptr;
SGRect<float> _src_rect {0, 0},
_region {0, 0};
SVGpreserveAspectRatio _preserve_aspect_ratio;

View File

@@ -1,5 +1,6 @@
// A group of 2D Canvas elements which get automatically transformed according
// to the map parameters.
///@file
/// A group of 2D Canvas elements which get automatically transformed according
/// to the map parameters.
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -17,13 +18,15 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasMap.hxx"
#include "map/geo_node_pair.hxx"
#include "map/projection.hxx"
#include <cmath>
#include <simgear/misc/strutils.hxx>
#include <boost/algorithm/string/predicate.hpp>
#include <cmath>
#define LOG_GEO_RET(msg) \
{\
@@ -46,6 +49,12 @@ namespace canvas
const std::string GEO = "-geo";
const std::string HDG = "hdg";
const std::string Map::TYPE_NAME = "map";
const std::string WEB_MERCATOR = "webmercator";
const std::string REF_LAT = "ref-lat";
const std::string REF_LON = "ref-lon";
const std::string SCREEN_RANGE = "screen-range";
const std::string RANGE = "range";
const std::string PROJECTION = "projection";
//----------------------------------------------------------------------------
void Map::staticInit()
@@ -63,12 +72,11 @@ namespace canvas
const SGPropertyNode_ptr& node,
const Style& parent_style,
ElementWeakPtr parent ):
Group(canvas, node, parent_style, parent),
// TODO make projection configurable
_projection(new SansonFlamsteedProjection),
_projection_dirty(true)
Group(canvas, node, parent_style, parent)
{
staticInit();
projectionNodeChanged(node->getChild(PROJECTION));
}
//----------------------------------------------------------------------------
@@ -78,42 +86,49 @@ namespace canvas
}
//----------------------------------------------------------------------------
void Map::update(double dt)
void Map::updateImpl(double dt)
{
for( GeoNodes::iterator it = _geo_nodes.begin();
it != _geo_nodes.end();
++it )
Group::updateImpl(dt);
for(auto& it: _geo_nodes)
{
GeoNodePair* geo_node = it->second.get();
GeoNodePair* geo_node = it.second.get();
if( !geo_node->isComplete()
|| (!geo_node->isDirty() && !_projection_dirty) )
continue;
GeoCoord lat = parseGeoCoord(geo_node->getLat());
if( lat.type != GeoCoord::LATITUDE )
continue;
GeoCoord lon = parseGeoCoord(geo_node->getLon());
if( lon.type != GeoCoord::LONGITUDE )
continue;
Projection::ScreenPosition pos =
_projection->worldToScreen(lat.value, lon.value);
double latD = -9999.0, lonD = -9999.0;
if (geo_node->isDirty()) {
GeoCoord lat = parseGeoCoord(geo_node->getLat());
if( lat.type != GeoCoord::LATITUDE )
continue;
GeoCoord lon = parseGeoCoord(geo_node->getLon());
if( lon.type != GeoCoord::LONGITUDE )
continue;
// save the parsed values so we can re-use them if only projection
// is changed (very common case for moving vehicle)
latD = lat.value;
lonD = lon.value;
geo_node->setCachedLatLon(std::make_pair(latD, lonD));
} else {
std::tie(latD, lonD) = geo_node->getCachedLatLon();
}
Projection::ScreenPosition pos = _projection->worldToScreen(latD, lonD);
geo_node->setScreenPos(pos.x, pos.y);
// geo_node->print();
geo_node->setDirty(false);
}
_projection_dirty = false;
Group::update(dt);
}
//----------------------------------------------------------------------------
void Map::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
{
if( boost::ends_with(child->getNameString(), GEO) )
if( strutils::ends_with(child->getNameString(), GEO) )
_geo_nodes[child].reset(new GeoNodePair());
else if( parent != _node && child->getNameString() == HDG )
_hdg_nodes.insert(child);
@@ -124,7 +139,7 @@ namespace canvas
//----------------------------------------------------------------------------
void Map::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
{
if( boost::ends_with(child->getNameString(), GEO) )
if( strutils::ends_with(child->getNameString(), GEO) )
// TODO remove from other node
_geo_nodes.erase(child);
else if( parent != _node && child->getName() == HDG )
@@ -146,7 +161,7 @@ namespace canvas
{
const std::string& name = child->getNameString();
if( boost::ends_with(name, GEO) )
if( strutils::ends_with(name, GEO) )
return geoNodeChanged(child);
else if( name == HDG )
return hdgNodeChanged(child);
@@ -161,10 +176,10 @@ namespace canvas
if( child->getParent() != _node )
return Group::childChanged(child);
if( child->getNameString() == "ref-lat"
|| child->getNameString() == "ref-lon" )
_projection->setWorldPosition( _node->getDoubleValue("ref-lat"),
_node->getDoubleValue("ref-lon") );
if( child->getNameString() == REF_LAT
|| child->getNameString() == REF_LON )
_projection->setWorldPosition( _node->getDoubleValue(REF_LAT),
_node->getDoubleValue(REF_LON) );
else if( child->getNameString() == HDG )
{
_projection->setOrientation(child->getFloatValue());
@@ -173,16 +188,43 @@ namespace canvas
++it )
hdgNodeChanged(*it);
}
else if( child->getNameString() == "range" )
else if( child->getNameString() == RANGE )
_projection->setRange(child->getDoubleValue());
else if( child->getNameString() == "screen-range" )
else if( child->getNameString() == SCREEN_RANGE )
_projection->setScreenRange(child->getDoubleValue());
else if( child->getNameString() == PROJECTION )
projectionNodeChanged(child);
else
return Group::childChanged(child);
_projection_dirty = true;
}
//----------------------------------------------------------------------------
void Map::projectionNodeChanged(SGPropertyNode* child)
{
if(child && child->getStringValue() == WEB_MERCATOR)
_projection = std::make_shared<WebMercatorProjection>();
else
_projection = std::make_shared<SansonFlamsteedProjection>();
_projection->setWorldPosition(_node->getDoubleValue(REF_LAT),
_node->getDoubleValue(REF_LON));
// Only set existing properties to prevent using 0 instead of default values
if( auto heading = _node->getChild(HDG) )
_projection->setOrientation(heading->getFloatValue());
if( auto screen_range = _node->getChild(SCREEN_RANGE) )
_projection->setScreenRange(screen_range->getDoubleValue());
if( auto range = _node->getChild(RANGE) )
_projection->setRange(range->getDoubleValue());
_projection_dirty = true;
}
//----------------------------------------------------------------------------
void Map::geoNodeChanged(SGPropertyNode* child)
{

View File

@@ -1,5 +1,6 @@
// A group of 2D Canvas elements which get automatically transformed according
// to the map parameters.
///@file
/// A group of 2D Canvas elements which get automatically transformed according
/// to the map parameters.
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -22,9 +23,9 @@
#include "CanvasGroup.hxx"
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include <memory>
#include <unordered_map>
#include <unordered_set>
namespace simgear
{
@@ -45,45 +46,39 @@ namespace canvas
ElementWeakPtr parent = 0 );
virtual ~Map();
virtual void update(double dt);
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void valueChanged(SGPropertyNode * child);
protected:
void updateImpl(double dt) override;
virtual void childChanged(SGPropertyNode * child);
void updateProjection(SGPropertyNode* type_node);
typedef boost::unordered_map< SGPropertyNode*,
boost::shared_ptr<GeoNodePair>
> GeoNodes;
typedef boost::unordered_set<SGPropertyNode*> NodeSet;
void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override;
void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override;
void valueChanged(SGPropertyNode* child) override;
void childChanged(SGPropertyNode* child) override;
using GeoNodes =
std::unordered_map<SGPropertyNode*, std::shared_ptr<GeoNodePair>>;
using NodeSet = std::unordered_set<SGPropertyNode*>;
GeoNodes _geo_nodes;
NodeSet _hdg_nodes;
boost::shared_ptr<HorizontalProjection> _projection;
bool _projection_dirty;
std::shared_ptr<HorizontalProjection> _projection;
bool _projection_dirty = false;
struct GeoCoord
{
GeoCoord():
type(INVALID),
value(0)
{}
enum
{
INVALID,
LATITUDE,
LONGITUDE
} type;
double value;
} type = INVALID;
double value = 0;
};
void geoNodeChanged(SGPropertyNode * child);
void hdgNodeChanged(SGPropertyNode * child);
void projectionNodeChanged(SGPropertyNode* child);
void geoNodeChanged(SGPropertyNode* child);
void hdgNodeChanged(SGPropertyNode* child);
GeoCoord parseGeoCoord(const std::string& val) const;
};

View File

@@ -1,4 +1,5 @@
// An OpenVG path on the Canvas
///@file
/// An OpenVG path on the Canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,14 +17,18 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasPath.hxx"
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/misc/strutils.hxx>
#include <osg/Drawable>
#include <osg/Version>
#include <vg/openvg.h>
#include <cassert>
#include <cctype>
namespace simgear
{
@@ -57,21 +62,158 @@ namespace canvas
*/
std::vector<float> splitAndConvert(const char del[], const std::string& str);
static float parseCSSNumber(const std::string& s)
{
if (strutils::ends_with(s, "px")) {
return std::stof(s.substr(0, s.length() - 2));
} else if (s.back() == '%') {
float f = std::stof(s.substr(0, s.length() - 1));
return f / 100.0f;
}
return std::stof(s);
}
//----------------------------------------------------------------------------
static bool parseSVGPathToVGPath(const std::string& svgPath, CmdList& commands, CoordList& coords)
{
const string_list& tokens = simgear::strutils::split_on_any_of(svgPath, "\t \n\r,");
char activeSVGCommand = 0;
bool isRelative = false;
int tokensNeeded = 0;
for (auto it = tokens.begin(); it != tokens.end(); ) {
// set up the new command data
if ((it->size() == 1) && std::isalpha(it->at(0))) {
const char svgCommand = std::toupper(it->at(0));
isRelative = std::islower(it->at(0));
switch (svgCommand) {
case 'Z':
tokensNeeded = 0;
break;
case 'M':
case 'L':
case 'T':
tokensNeeded = 2;
break;
case 'H':
case 'V':
tokensNeeded = 1;
break;
case 'C':
tokensNeeded = 6;
break;
case 'S':
case 'Q':
tokensNeeded = 4;
break;
case 'A':
tokensNeeded = 7;
break;
default:
SG_LOG(SG_GENERAL, SG_WARN, "unrecognized SVG path command: "
<< *it << " at token " << std::distance(tokens.begin(), it));
return false;
}
activeSVGCommand = svgCommand;
++it; // advance to first coordinate token
}
const int numTokensRemaining = std::distance(it, tokens.end());
if (numTokensRemaining < tokensNeeded) {
SG_LOG(SG_GENERAL, SG_WARN, "insufficent SVG path tokens");
return false;
}
bool pushTokensDirectly = true;
if (activeSVGCommand == 'Z') {
commands.push_back(VG_CLOSE_PATH);
activeSVGCommand = 0;
} else if (activeSVGCommand == 'M') {
commands.push_back(VG_MOVE_TO | isRelative);
activeSVGCommand = 'L';
} else if (activeSVGCommand == 'L') {
commands.push_back(VG_LINE_TO | isRelative);
} else if (activeSVGCommand == 'H') {
commands.push_back(VG_HLINE_TO | isRelative);
} else if (activeSVGCommand == 'V') {
commands.push_back(VG_HLINE_TO | isRelative);
} else if (activeSVGCommand == 'C') {
commands.push_back(VG_CUBIC_TO | isRelative);
} else if (activeSVGCommand == 'S') {
commands.push_back(VG_SCUBIC_TO | isRelative);
} else if (activeSVGCommand == 'Q') {
commands.push_back(VG_SCUBIC_TO | isRelative);
} else if (activeSVGCommand == 'T') {
commands.push_back(VG_SCUBIC_TO | isRelative);
} else if (activeSVGCommand == 'A') {
pushTokensDirectly = false; // deal with tokens manually
coords.push_back(parseCSSNumber(*it++)); // rx
coords.push_back(parseCSSNumber(*it++)); // ry
coords.push_back(parseCSSNumber(*it++)); // x-axis rotation
const bool isLargeArc = std::stoi(*it++); // large-angle
const bool isCCW = std::stoi(*it++); // sweep-flag
int vgCmd = isLargeArc ? (isCCW ? VG_LCCWARC_TO : VG_LCWARC_TO) :
(isCCW ? VG_SCCWARC_TO : VG_SCWARC_TO);
coords.push_back(parseCSSNumber(*it++));
coords.push_back(parseCSSNumber(*it++));
commands.push_back(vgCmd | isRelative);
} else {
SG_LOG(SG_GENERAL, SG_WARN, "malformed SVG path string: expected a command at token:"
<< std::distance(tokens.begin(), it) << " :" << *it);
return false;
}
if (pushTokensDirectly) {
for (int i=0; i<tokensNeeded;++i) {
coords.push_back(parseCSSNumber(*it++));
}
}
} // of tokens iteration
return true;
}
//---------------------------------------------------------------------------
static SGVec2f parseRectCornerRadius(SGPropertyNode* node, const std::string& xDir, const std::string& yDir, bool& haveCorner)
{
haveCorner = false;
std::string propName = "border-" + yDir + "-" + xDir + "-radius";
if (!node->hasChild(propName)) {
propName = "border-" + yDir + "-radius";
if (!node->hasChild(propName)) {
propName = "border-radius";
}
}
PropertyList props = node->getChildren(propName);
if (props.size() == 1) {
double r = props.at(0)->getDoubleValue(propName);
haveCorner = true;
return SGVec2f(r, r);
}
if (props.size() >= 2 ) {
haveCorner = true;
return SGVec2f(props.at(0)->getDoubleValue(),
props.at(1)->getDoubleValue());
}
return SGVec2f(-1.0f, -1.0f);
}
//----------------------------------------------------------------------------
class Path::PathDrawable:
public osg::Drawable
{
public:
PathDrawable(Path* path):
_path_element(path),
_path(VG_INVALID_HANDLE),
_paint(VG_INVALID_HANDLE),
_paint_fill(VG_INVALID_HANDLE),
_attributes_dirty(~0),
_mode(0),
_fill_rule(VG_EVEN_ODD),
_stroke_width(1),
_stroke_linecap(VG_CAP_BUTT),
_stroke_linejoin(VG_JOIN_MITER)
_path_element(path)
{
setSupportsDisplayList(false);
setDataVariance(Object::DYNAMIC);
@@ -89,9 +231,12 @@ namespace canvas
vgDestroyPaint(_paint_fill);
}
virtual const char* className() const { return "PathDrawable"; }
virtual osg::Object* cloneType() const { return new PathDrawable(_path_element); }
virtual osg::Object* clone(const osg::CopyOp&) const { return new PathDrawable(_path_element); }
const char* className() const override
{ return "PathDrawable"; }
osg::Object* cloneType() const override
{ return new PathDrawable(_path_element); }
osg::Object* clone(const osg::CopyOp&) const override
{ return new PathDrawable(_path_element); }
/**
* Replace the current path segments with the new ones
@@ -132,6 +277,16 @@ namespace canvas
}
}
/**
* Set path fill opacity (Only used if fill is not "none")
*/
void setFillOpacity(float opacity)
{
_fill_opacity =
static_cast<uint8_t>(SGMiscf::clip(opacity, 0.f, 1.f) * 255);
_attributes_dirty |= FILL_COLOR;
}
/**
* Set path fill rule ("pseudo-nonzero" or "evenodd")
*
@@ -159,7 +314,7 @@ namespace canvas
else if( parseColor(stroke, _stroke_color) )
{
_mode |= VG_STROKE_PATH;
_attributes_dirty |= STROKE_COLOR;
_attributes_dirty |= STROKE_COLOR;
}
else
{
@@ -172,6 +327,16 @@ namespace canvas
}
}
/**
* Set path stroke opacity (only used if stroke is not "none")
*/
void setStrokeOpacity(float opacity)
{
_stroke_opacity =
static_cast<uint8_t>(SGMiscf::clip(opacity, 0.f, 1.f) * 255);
_attributes_dirty |= STROKE_COLOR;
}
/**
* Set stroke width
*/
@@ -222,7 +387,7 @@ namespace canvas
/**
* Draw callback
*/
virtual void drawImplementation(osg::RenderInfo& renderInfo) const
void drawImplementation(osg::RenderInfo& renderInfo) const override
{
if( _attributes_dirty & PATH )
return;
@@ -239,31 +404,22 @@ namespace canvas
osg::StateAttribute const* blend_func =
state->getLastAppliedAttribute(osg::StateAttribute::BLENDFUNC);
// Initialize/Update the paint
if( _attributes_dirty & STROKE_COLOR )
{
if( _paint == VG_INVALID_HANDLE )
_paint = vgCreatePaint();
vgSetParameterfv(_paint, VG_PAINT_COLOR, 4, _stroke_color._v);
_attributes_dirty &= ~STROKE_COLOR;
}
// Initialize/update fill paint
if( _attributes_dirty & FILL_COLOR )
{
if( _paint_fill == VG_INVALID_HANDLE )
_paint_fill = vgCreatePaint();
vgSetParameterfv(_paint_fill, VG_PAINT_COLOR, 4, _fill_color._v);
_attributes_dirty &= ~FILL_COLOR;
}
// Setup paint
if( _mode & VG_STROKE_PATH )
{
// Initialize/Update the paint
if( _attributes_dirty & STROKE_COLOR )
{
if( _paint == VG_INVALID_HANDLE )
_paint = vgCreatePaint();
auto color = _stroke_color;
color.a() *= _stroke_opacity / 255.f;
vgSetParameterfv(_paint, VG_PAINT_COLOR, 4, color._v);
_attributes_dirty &= ~STROKE_COLOR;
}
vgSetPaint(_paint, VG_STROKE_PATH);
vgSetf(VG_STROKE_LINE_WIDTH, _stroke_width);
@@ -275,6 +431,19 @@ namespace canvas
}
if( _mode & VG_FILL_PATH )
{
// Initialize/update fill paint
if( _attributes_dirty & FILL_COLOR )
{
if( _paint_fill == VG_INVALID_HANDLE )
_paint_fill = vgCreatePaint();
auto color = _fill_color;
color.a() *= _fill_opacity / 255.f;
vgSetParameterfv(_paint_fill, VG_PAINT_COLOR, 4, color._v);
_attributes_dirty &= ~FILL_COLOR;
}
vgSetPaint(_paint_fill, VG_FILL_PATH);
vgSeti(VG_FILL_RULE, _fill_rule);
@@ -390,13 +559,13 @@ namespace canvas
/**
* Compute the bounding box
*/
virtual osg::BoundingBox
osg::BoundingBox
#if OSG_VERSION_LESS_THAN(3,3,2)
computeBound()
#else
computeBoundingBox()
#endif
const
const override
{
if( _path == VG_INVALID_HANDLE || (_attributes_dirty & PATH) )
return osg::BoundingBox();
@@ -428,22 +597,24 @@ namespace canvas
Path *_path_element;
mutable VGPath _path;
mutable VGPaint _paint;
mutable VGPaint _paint_fill;
mutable uint32_t _attributes_dirty;
mutable VGPath _path {VG_INVALID_HANDLE};
mutable VGPaint _paint {VG_INVALID_HANDLE};
mutable VGPaint _paint_fill {VG_INVALID_HANDLE};
mutable uint32_t _attributes_dirty {~0u};
CmdList _cmds;
CoordList _coords;
VGbitfield _mode;
VGbitfield _mode {0};
osg::Vec4f _fill_color;
VGFillRule _fill_rule;
uint8_t _fill_opacity {255};
VGFillRule _fill_rule {VG_EVEN_ODD};
osg::Vec4f _stroke_color;
VGfloat _stroke_width;
uint8_t _stroke_opacity {255};
VGfloat _stroke_width {1};
std::vector<VGfloat> _stroke_dash;
VGCapStyle _stroke_linecap;
VGJoinStyle _stroke_linejoin;
VGCapStyle _stroke_linecap {VG_CAP_BUTT};
VGJoinStyle _stroke_linejoin {VG_JOIN_MITER};
osg::Vec3f transformPoint( const osg::Matrix& m,
osg::Vec2f pos ) const
@@ -500,7 +671,7 @@ namespace canvas
struct PathUpdateCallback:
public osg::Drawable::UpdateCallback
{
virtual void update(osg::NodeVisitor*, osg::Drawable* drawable)
void update(osg::NodeVisitor*, osg::Drawable* drawable) override
{
static_cast<PathDrawable*>(drawable)->update();
}
@@ -519,8 +690,10 @@ namespace canvas
PathDrawableRef Path::*path = &Path::_path;
addStyle("fill", "color", &PathDrawable::setFill, path);
addStyle("fill-opacity", "numeric", &PathDrawable::setFillOpacity, path);
addStyle("fill-rule", "", &PathDrawable::setFillRule, path);
addStyle("stroke", "color", &PathDrawable::setStroke, path);
addStyle("stroke-opacity", "numeric", &PathDrawable::setStrokeOpacity, path);
addStyle("stroke-width", "numeric", &PathDrawable::setStrokeWidth, path);
addStyle("stroke-dasharray", "", &PathDrawable::setStrokeDashArray, path);
addStyle("stroke-linecap", "", &PathDrawable::setStrokeLinecap, path);
@@ -533,7 +706,9 @@ namespace canvas
const Style& parent_style,
ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent),
_path( new PathDrawable(this) )
_path( new PathDrawable(this) ),
_hasSVG(false),
_hasRect(false)
{
staticInit();
@@ -547,75 +722,69 @@ namespace canvas
}
//----------------------------------------------------------------------------
void Path::update(double dt)
{
if( _attributes_dirty & (CMDS | COORDS) )
{
_path->setSegments
(
_node->getChildValues<VGubyte, int>("cmd"),
_node->getChildValues<VGfloat, float>("coord")
);
_attributes_dirty &= ~(CMDS | COORDS);
}
Element::update(dt);
}
//----------------------------------------------------------------------------
osg::BoundingBox Path::getTransformedBounds(const osg::Matrix& m) const
{
return _path->getTransformedBounds(m);
}
//----------------------------------------------------------------------------
Path& Path::addSegment(uint8_t cmd, std::initializer_list<float> coords)
{
_node->addChild("cmd")->setIntValue(cmd);
for(float coord: coords)
_node->addChild("coord")->setFloatValue(coord);
return *this;
}
//----------------------------------------------------------------------------
Path& Path::moveTo(float x_abs, float y_abs)
{
return addSegment(VG_MOVE_TO_ABS, x_abs, y_abs);
return addSegment(VG_MOVE_TO_ABS, {x_abs, y_abs});
}
//----------------------------------------------------------------------------
Path& Path::move(float x_rel, float y_rel)
{
return addSegment(VG_MOVE_TO_REL, x_rel, y_rel);
return addSegment(VG_MOVE_TO_REL, {x_rel, y_rel});
}
//----------------------------------------------------------------------------
Path& Path::lineTo(float x_abs, float y_abs)
{
return addSegment(VG_LINE_TO_ABS, x_abs, y_abs);
return addSegment(VG_LINE_TO_ABS, {x_abs, y_abs});
}
//----------------------------------------------------------------------------
Path& Path::line(float x_rel, float y_rel)
{
return addSegment(VG_LINE_TO_REL, x_rel, y_rel);
return addSegment(VG_LINE_TO_REL, {x_rel, y_rel});
}
//----------------------------------------------------------------------------
Path& Path::horizTo(float x_abs)
{
return addSegment(VG_HLINE_TO_ABS, x_abs);
return addSegment(VG_HLINE_TO_ABS, {x_abs});
}
//----------------------------------------------------------------------------
Path& Path::horiz(float x_rel)
{
return addSegment(VG_HLINE_TO_REL, x_rel);
return addSegment(VG_HLINE_TO_REL, {x_rel});
}
//----------------------------------------------------------------------------
Path& Path::vertTo(float y_abs)
{
return addSegment(VG_VLINE_TO_ABS, y_abs);
return addSegment(VG_VLINE_TO_ABS, {y_abs});
}
//----------------------------------------------------------------------------
Path& Path::vert(float y_rel)
{
return addSegment(VG_VLINE_TO_REL, y_rel);
return addSegment(VG_VLINE_TO_REL, {y_rel});
}
//----------------------------------------------------------------------------
@@ -630,16 +799,111 @@ namespace canvas
childChanged(child);
}
//----------------------------------------------------------------------------
void Path::setSVGPath(const std::string& svgPath)
{
_node->setStringValue("svg", svgPath);
_hasSVG = true;
_attributes_dirty |= SVG;
}
//----------------------------------------------------------------------------
void Path::setRect(const SGRect<float> &r)
{
_rect = r;
_hasRect = true;
_attributes_dirty |= RECT;
}
//----------------------------------------------------------------------------
void Path::setRoundRect(const SGRect<float> &r, float radiusX, float radiusY)
{
if (radiusY < 0.0) {
radiusY = radiusX;
}
setRect(r);
_node->getChild("border-radius", 0, true)->setDoubleValue(radiusX);
_node->getChild("border-radius", 1, true)->setDoubleValue(radiusY);
}
//----------------------------------------------------------------------------
void Path::updateImpl(double dt)
{
Element::updateImpl(dt);
if( _attributes_dirty & (CMDS | COORDS) )
{
_path->setSegments
(
_node->getChildValues<VGubyte, int>("cmd"),
_node->getChildValues<VGfloat, float>("coord")
);
_attributes_dirty &= ~(CMDS | COORDS);
}
// SVG path overrides manual cmd/coord specification
if( _hasSVG && (_attributes_dirty & SVG) )
{
CmdList cmds;
CoordList coords;
parseSVGPathToVGPath(_node->getStringValue("svg"), cmds, coords);
_path->setSegments(cmds, coords);
_attributes_dirty &= ~SVG;
}
if( _hasRect &&(_attributes_dirty & RECT) )
{
parseRectToVGPath();
_attributes_dirty &= ~RECT;
}
}
//----------------------------------------------------------------------------
void Path::childChanged(SGPropertyNode* child)
{
if( child->getParent() != _node )
return;
const std::string& name = child->getNameString();
const std::string &prName = child->getParent()->getNameString();
if( child->getNameString() == "cmd" )
if( strutils::starts_with(name, "border-") )
{
_attributes_dirty |= RECT;
return;
}
if (prName == "rect")
{
_hasRect = true;
if (name == "left") {
_rect.setLeft(child->getDoubleValue());
} else if (name == "top") {
_rect.setTop(child->getDoubleValue());
} else if (name == "right") {
_rect.setRight(child->getDoubleValue());
} else if (name == "bottom") {
_rect.setBottom(child->getDoubleValue());
} else if (name == "width") {
_rect.setWidth(child->getDoubleValue());
} else if (name == "height") {
_rect.setHeight(child->getDoubleValue());
}
_attributes_dirty |= RECT;
return;
}
if( name == "cmd" )
_attributes_dirty |= CMDS;
else if( child->getNameString() == "coord" )
else if( name == "coord" )
_attributes_dirty |= COORDS;
else if ( name == "svg")
{
_hasSVG = true;
_attributes_dirty |= SVG;
}
}
//----------------------------------------------------------------------------
@@ -664,5 +928,68 @@ namespace canvas
return values;
}
//----------------------------------------------------------------------------
void operator+=(CoordList& base, const std::initializer_list<VGfloat>& other)
{
base.insert(base.end(), other.begin(), other.end());
}
//----------------------------------------------------------------------------
void Path::parseRectToVGPath()
{
CmdList commands;
CoordList coords;
commands.reserve(4);
coords.reserve(8);
bool haveCorner = false;
SGVec2f topLeft = parseRectCornerRadius(_node, "left", "top", haveCorner);
if (haveCorner) {
commands.push_back(VG_MOVE_TO_ABS);
coords += {_rect.l(), _rect.t() + topLeft.y()};
commands.push_back(VG_SCCWARC_TO_REL);
coords += {topLeft.x(), topLeft.y(), 0.0, topLeft.x(), -topLeft.y()};
} else {
commands.push_back(VG_MOVE_TO_ABS);
coords += {_rect.l(), _rect.t()};
}
SGVec2f topRight = parseRectCornerRadius(_node, "right", "top", haveCorner);
if (haveCorner) {
commands.push_back(VG_HLINE_TO_ABS);
coords += {_rect.r() - topRight.x()};
commands.push_back(VG_SCCWARC_TO_REL);
coords += {topRight.x(), topRight.y(), 0.0, topRight.x(), topRight.y()};
} else {
commands.push_back(VG_HLINE_TO_ABS);
coords += {_rect.r()};
}
SGVec2f bottomRight = parseRectCornerRadius(_node, "right", "bottom", haveCorner);
if (haveCorner) {
commands.push_back(VG_VLINE_TO_ABS);
coords += {_rect.b() - bottomRight.y()};
commands.push_back(VG_SCCWARC_TO_REL);
coords += {bottomRight.x(), bottomRight.y(), 0.0, -bottomRight.x(), bottomRight.y()};
} else {
commands.push_back(VG_VLINE_TO_ABS);
coords += {_rect.b()};
}
SGVec2f bottomLeft = parseRectCornerRadius(_node, "left", "bottom", haveCorner);
if (haveCorner) {
commands.push_back(VG_HLINE_TO_ABS);
coords += {_rect.l() + bottomLeft.x()};
commands.push_back(VG_SCCWARC_TO_REL);
coords += {bottomLeft.x(), bottomLeft.y(), 0.0, -bottomLeft.x(), -bottomLeft.y()};
} else {
commands.push_back(VG_HLINE_TO_ABS);
coords += {_rect.l()};
}
commands.push_back(VG_CLOSE_PATH);
_path->setSegments(commands, coords);
}
} // namespace canvas
} // namespace simgear

View File

@@ -1,4 +1,5 @@
// An OpenVG path on the Canvas
///@file
/// An OpenVG path on the Canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -20,7 +21,8 @@
#define CANVAS_PATH_HXX_
#include "CanvasElement.hxx"
#include <boost/preprocessor/iteration/iterate.hpp>
#include <simgear/math/SGRect.hxx>
#include <initializer_list>
namespace simgear
{
@@ -39,14 +41,11 @@ namespace canvas
ElementWeakPtr parent = 0 );
virtual ~Path();
virtual void update(double dt);
osg::BoundingBox
getTransformedBounds(const osg::Matrix& m) const override;
virtual osg::BoundingBox getTransformedBounds(const osg::Matrix& m) const;
#define BOOST_PP_ITERATION_LIMITS (0, 6)
#define BOOST_PP_FILENAME_1 \
<simgear/canvas/elements/detail/add_segment_variadic.hxx>
#include BOOST_PP_ITERATE()
/** Add a segment with the given command and coordinates */
Path& addSegment(uint8_t cmd, std::initializer_list<float> coords = {});
/** Move path cursor */
Path& moveTo(float x_abs, float y_abs);
@@ -67,20 +66,34 @@ namespace canvas
/** Close the path (implicit lineTo to first point of path) */
Path& close();
protected:
void setSVGPath(const std::string& svgPath);
void setRect(const SGRectf& r);
void setRoundRect(const SGRectf& r, float radiusX, float radiusY = -1.0);
protected:
enum PathAttributes
{
CMDS = LAST_ATTRIBUTE << 1,
COORDS = CMDS << 1
COORDS = CMDS << 1,
SVG = COORDS << 1,
RECT = SVG << 1
};
class PathDrawable;
typedef osg::ref_ptr<PathDrawable> PathDrawableRef;
PathDrawableRef _path;
virtual void childRemoved(SGPropertyNode * child);
virtual void childChanged(SGPropertyNode * child);
bool _hasSVG : 1;
bool _hasRect : 1;
SGRectf _rect;
void updateImpl(double dt) override;
void childRemoved(SGPropertyNode * child) override;
void childChanged(SGPropertyNode * child) override;
void parseRectToVGPath();
};
} // namespace canvas

View File

@@ -1,4 +1,5 @@
// A text on the Canvas
///@file
/// A text on the Canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CanvasText.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasSystemAdapter.hxx>
@@ -50,27 +53,31 @@ namespace canvas
TextLine lineAt(size_t i) const;
/// Get nearest line to given y-coordinate
#if OSG_VERSION_LESS_THAN(3,6,5)
TextLine nearestLine(float pos_y) const;
SGVec2i sizeForWidth(int w) const;
virtual osg::BoundingBox
#if OSG_VERSION_LESS_THAN(3,3,2)
computeBound()
#else
computeBoundingBox()
TextLine nearestLine(float pos_y);
SGVec2i sizeForWidth(int w);
#endif
#if OSG_VERSION_LESS_THAN(3,3,2)
osg::BoundingBox computeBound() const override;
#else
osg::BoundingBox computeBoundingBox() const override;
#endif
const;
protected:
friend class TextLine;
canvas::Text *_text_element;
virtual void computePositions(unsigned int contextID) const;
};
#if OSG_VERSION_LESS_THAN(3,5,6)
void computePositions(unsigned int contextID) const override;
#else
void computePositionsImplementation() override;
#endif
};
class TextLine
{
@@ -120,6 +127,7 @@ namespace canvas
_quads = &text->_textureGlyphQuadMap.begin()->second;
#if OSG_VERSION_LESS_THAN(3,5,6)
GlyphQuads::LineNumbers const& line_numbers = _quads->_lineNumbers;
GlyphQuads::LineNumbers::const_iterator begin_it =
std::lower_bound(line_numbers.begin(), line_numbers.end(), _line);
@@ -131,6 +139,9 @@ namespace canvas
_begin = begin_it - line_numbers.begin();
_end = std::upper_bound(begin_it, line_numbers.end(), _line)
- line_numbers.begin();
#else
// TODO: Need 3.5.6 version of this
#endif
}
//----------------------------------------------------------------------------
@@ -159,34 +170,40 @@ namespace canvas
if( empty() )
return pos;
#if OSG_VERSION_LESS_THAN(3,3,5)
GlyphQuads::Coords2 const& coords = _quads->_coords;
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,6)
// TODO: need 3.5.6 version of this.
#else
GlyphQuads::Coords2 refCoords = _quads->_coords;
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
#if OSG_VERSION_LESS_THAN(3,3,5)
GlyphQuads::Coords2 const& coords = _quads->_coords;
#else
GlyphQuads::Coords2 refCoords = _quads->_coords;
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
#endif
size_t global_i = _begin + i;
if( global_i == _begin )
// before first character of line
pos.x() = coords[_begin * 4].x();
else if( global_i == _end )
// After Last character of line
pos.x() = coords[(_end - 1) * 4 + 2].x();
else
{
float prev_l = coords[(global_i - 1) * 4].x(),
prev_r = coords[(global_i - 1) * 4 + 2].x(),
cur_l = coords[global_i * 4].x();
size_t global_i = _begin + i;
if( prev_l == prev_r )
// If previous character width is zero set to begin of next character
// (Happens eg. with spaces)
pos.x() = cur_l;
if (global_i == _begin)
// before first character of line
pos.x() = coords[_begin * 4].x();
else if (global_i == _end)
// After Last character of line
pos.x() = coords[(_end - 1) * 4 + 2].x();
else
// position at center between characters
pos.x() = 0.5 * (prev_r + cur_l);
}
{
float prev_l = coords[(global_i - 1) * 4].x(),
prev_r = coords[(global_i - 1) * 4 + 2].x(),
cur_l = coords[global_i * 4].x();
if (prev_l == prev_r)
// If previous character width is zero set to begin of next character
// (Happens eg. with spaces)
pos.x() = cur_l;
else
// position at center between characters
pos.x() = 0.5 * (prev_r + cur_l);
}
#endif
return pos;
}
@@ -194,17 +211,22 @@ namespace canvas
//----------------------------------------------------------------------------
osg::Vec2 TextLine::nearestCursor(float x) const
{
if( empty() )
if (empty())
return cursorPos(0);
GlyphQuads::Glyphs const& glyphs = _quads->_glyphs;
#if OSG_VERSION_LESS_THAN(3,3,5)
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,6)
// TODO: need 3.5.7 version of this.
return cursorPos(0);
#else
#if OSG_VERSION_LESS_THAN(3,3,5)
GlyphQuads::Coords2 const& coords = _quads->_coords;
#else
GlyphQuads::Coords2 refCoords = _quads->_coords;
GlyphQuads::Coords2::element_type &coords = *refCoords.get();
#endif
GlyphQuads::Glyphs const& glyphs = _quads->_glyphs;
float const HIT_FRACTION = 0.6;
float const character_width = _text->getCharacterHeight()
* _text->getCharacterAspectRatio();
@@ -223,6 +245,7 @@ namespace canvas
}
return cursorPos(i - _begin);
#endif
}
//----------------------------------------------------------------------------
@@ -301,9 +324,16 @@ namespace canvas
}
//----------------------------------------------------------------------------
#if OSG_VERSION_LESS_THAN(3,6,5)
TextLine Text::TextOSG::nearestLine(float pos_y) const
{
osgText::Font const* font = getActiveFont();
#else
TextLine Text::TextOSG::nearestLine(float pos_y)
{
auto font = getActiveFont();
#endif
if( !font || lineCount() <= 0 )
return TextLine(0, this);
@@ -325,12 +355,21 @@ namespace canvas
// simplified version of osgText::Text::computeGlyphRepresentation() to
// just calculate the size for a given weight. Glpyh calculations/creating
// is not necessary for this...
#if OSG_VERSION_LESS_THAN(3,6,5)
SGVec2i Text::TextOSG::sizeForWidth(int w) const
#else
SGVec2i Text::TextOSG::sizeForWidth(int w)
#endif
{
if( _text.empty() )
return SGVec2i(0, 0);
#if OSG_VERSION_LESS_THAN(3,6,5)
osgText::Font* activefont = const_cast<osgText::Font*>(getActiveFont());
#else
auto activefont = getActiveFont();
#endif
if( !activefont )
return SGVec2i(-1, -1);
@@ -496,18 +535,31 @@ namespace canvas
{
case LEFT_TO_RIGHT:
{
osg::Vec2 delta( activefont->getKerning( previous_charcode,
charcode,
_kerningType ) );
#if OSG_VERSION_LESS_THAN(3,5,2)
osg::Vec2 delta(activefont->getKerning(previous_charcode,
charcode,
_kerningType));
#else
osg::Vec2 delta(activefont->getKerning(_fontSize,
previous_charcode,
charcode,
_kerningType));
#endif
cursor.x() += delta.x() * wr;
cursor.y() += delta.y() * hr;
break;
}
case RIGHT_TO_LEFT:
{
osg::Vec2 delta( activefont->getKerning( charcode,
previous_charcode,
_kerningType ) );
#if OSG_VERSION_LESS_THAN(3,5,2)
osg::Vec2 delta(activefont->getKerning(charcode,
previous_charcode,
_kerningType));
#else
osg::Vec2 delta(activefont->getKerning(_fontSize, charcode,
previous_charcode,
_kerningType));
#endif
cursor.x() -= delta.x() * wr;
cursor.y() -= delta.y() * hr;
break;
@@ -597,19 +649,16 @@ namespace canvas
}
//----------------------------------------------------------------------------
osg::BoundingBox
#if OSG_VERSION_LESS_THAN(3,3,2)
Text::TextOSG::computeBound()
osg::BoundingBox Text::TextOSG::computeBound() const
#else
Text::TextOSG::computeBoundingBox()
osg::BoundingBox Text::TextOSG::computeBoundingBox() const
#endif
const
{
osg::BoundingBox bb =
#if OSG_VERSION_LESS_THAN(3,3,2)
osgText::Text::computeBound();
osg::BoundingBox bb = osgText::Text::computeBound();
#else
osgText::Text::computeBoundingBox();
osg::BoundingBox bb = osgText::Text::computeBoundingBox();
#endif
#if OSG_VERSION_LESS_THAN(3,1,0)
@@ -625,7 +674,7 @@ namespace canvas
return bb;
}
//----------------------------------------------------------------------------
#if OSG_VERSION_LESS_THAN(3,5,6)
void Text::TextOSG::computePositions(unsigned int contextID) const
{
if( _textureGlyphQuadMap.empty() || _layout == VERTICAL )
@@ -695,6 +744,14 @@ namespace canvas
return osgText::Text::computePositions(contextID);
}
#else
void Text::TextOSG::computePositionsImplementation()
{
TextBase::computePositionsImplementation();
}
#endif
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
const std::string Text::TYPE_NAME = "text";
@@ -851,12 +908,12 @@ namespace canvas
//----------------------------------------------------------------------------
osg::StateSet* Text::getOrCreateStateSet()
{
if( !_transform.valid() )
return 0;
if( !_scene_group.valid() )
return nullptr;
// Only check for StateSet on Transform, as the text stateset is shared
// between all text instances using the same font (texture).
return _transform->getOrCreateStateSet();
return _scene_group->getOrCreateStateSet();
}
} // namespace canvas

View File

@@ -1,4 +1,5 @@
// A text on the Canvas
///@file
/// A text on the Canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//

View File

@@ -1,21 +0,0 @@
#ifndef CANVAS_PATH_HXX_
# error Canvas - do not include this file!
#endif
#define n BOOST_PP_ITERATION()
Path& addSegment( uint8_t cmd
BOOST_PP_COMMA_IF(n)
BOOST_PP_ENUM_PARAMS(n, float coord) )
{
_node->addChild("cmd")->setIntValue(cmd);
#define SG_CANVAS_PATH_SET_COORD(z, n, dummy)\
_node->addChild("coord")->setFloatValue(coord##n);
BOOST_PP_REPEAT(n, SG_CANVAS_PATH_SET_COORD, 0)
#undef SG_CANVAS_PATH_SET_COORD
return *this;
}
#undef n

View File

@@ -67,7 +67,8 @@ namespace canvas
{
_node_lat = node;
_status &= ~LAT_MISSING;
_xNode.reset();
if( node == _node_lon )
{
_node_lon = 0;
@@ -79,7 +80,8 @@ namespace canvas
{
_node_lon = node;
_status &= ~LON_MISSING;
_yNode.reset();
if( node == _node_lat )
{
_node_lat = 0;
@@ -97,19 +99,34 @@ namespace canvas
return _node_lon ? _node_lon->getStringValue() : "";
}
void setCachedLatLon(const std::pair<double, double>& latLon)
{ _cachedLatLon = latLon; }
std::pair<double, double> getCachedLatLon()
{ return _cachedLatLon; }
void setTargetName(const std::string& name)
{
_target_name = name;
_xNode.reset();
_yNode.reset();
}
void setScreenPos(float x, float y)
{
assert( isComplete() );
SGPropertyNode *parent = _node_lat->getParent();
parent->getChild(_target_name, _node_lat->getIndex(), true)
->setDoubleValue(x);
parent->getChild(_target_name, _node_lon->getIndex(), true)
->setDoubleValue(y);
if (!_xNode) {
SGPropertyNode *parent = _node_lat->getParent();
_xNode = parent->getChild(_target_name, _node_lat->getIndex(), true);
}
if (!_yNode) {
SGPropertyNode *parent = _node_lat->getParent();
_yNode = parent->getChild(_target_name, _node_lon->getIndex(), true);
}
_xNode->setDoubleValue(x);
_yNode->setDoubleValue(y);
}
void print()
@@ -125,6 +142,9 @@ namespace canvas
SGPropertyNode *_node_lat,
*_node_lon;
std::string _target_name;
SGPropertyNode_ptr _xNode,
_yNode;
std::pair<double, double> _cachedLatLon;
};

View File

@@ -1,4 +1,5 @@
// Geographic projections for Canvas map element
///@file
/// Geographic projections for Canvas map element
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@gmail.com>
//
@@ -190,6 +191,32 @@ namespace canvas
}
};
/**
* WebMercator projection, relative to the projection center.
* Required for Slippy Maps - i.e. openstreetmap
*/
class WebMercatorProjection:
public HorizontalProjection
{
protected:
virtual ScreenPosition project(double lat, double lon) const
{
double d_lat = lat - _ref_lat,
d_lon = lon - _ref_lon;
double r = 6378137.f / 1852; // Equatorial radius divided by ?
ScreenPosition pos;
pos.x = r * d_lon;
pos.y = r * (log(tan(d_lat) + 1.0 / cos(d_lat)));
//pos.x = lon;
//pos.y = log(tan(lat) + 1.0 / cos(lat));
return pos;
}
};
} // namespace canvas
} // namespace simgear

View File

@@ -1,4 +1,5 @@
// Canvas user defined event
///@file
/// Canvas user defined event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,7 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "CustomEvent.hxx"
namespace simgear
@@ -45,6 +47,14 @@ namespace canvas
// assert( type_map.find(type_id) != type_map.end() );
}
//----------------------------------------------------------------------------
CustomEvent* CustomEvent::clone(int type) const
{
auto event = new CustomEvent(*this);
event->type = type;
return event;
}
//----------------------------------------------------------------------------
void CustomEvent::setDetail(StringMap const& data)
{

View File

@@ -38,6 +38,7 @@ namespace canvas
public:
/**
* @brief Construct a user defined event from a type string
*
* @param type_str Event type name (if name does not exist yet it will
* be registered as new event type)
@@ -49,6 +50,10 @@ namespace canvas
StringMap const& data = StringMap() );
/**
* @brief Construct a user defined event from a (previously registered)
* type id
*
* @see getOrRegisterType()
*
* @param type_id Event type id
* @param bubbles If this event should take part in the bubbling phase
@@ -58,6 +63,8 @@ namespace canvas
bool bubbles = false,
StringMap const& data = StringMap() );
CustomEvent* clone(int type = 0) const override;
/**
* Set user data
*/
@@ -74,7 +81,7 @@ namespace canvas
* @see #bubbles
* @see CustomEvent()
*/
virtual bool canBubble() const { return bubbles; }
bool canBubble() const override { return bubbles; }
StringMap detail; //!< User data map
bool bubbles; //!< Whether the event supports bubbling

View File

@@ -1,4 +1,5 @@
// Input device event
///@file
/// Input device event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "DeviceEvent.hxx"
#include <osgGA/GUIEventAdapter>

View File

@@ -1,4 +1,5 @@
// Keyboard event
///@file
/// Keyboard event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,8 +17,9 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "KeyboardEvent.hxx"
#include "utf8.h"
#include <osgGA/GUIEventAdapter>
@@ -40,6 +42,7 @@ namespace canvas
// TODO check Win/Mac keycode for altgr/ISO Level3 Shift
const uint32_t KEY_AltGraph = 0xfe03;
//----------------------------------------------------------------------------
KeyboardEvent::KeyboardEvent():
@@ -67,6 +70,14 @@ namespace canvas
// // TODO what to do with wrong event type?
}
//----------------------------------------------------------------------------
KeyboardEvent* KeyboardEvent::clone(int type) const
{
auto event = new KeyboardEvent(*this);
event->type = type;
return event;
}
//----------------------------------------------------------------------------
void KeyboardEvent::setKey(uint32_t key)
{
@@ -267,10 +278,24 @@ namespace canvas
// Empty or no mapping -> convert UTF-32 key value to UTF-8
if( _name.empty() )
{
if( !utf8::internal::is_code_point_valid(_key) )
if (( _key >= 0xd800u && _key <= 0xdfffu ) || _key > 0x10ffffu )
_name = "Unidentified";
else
utf8::unchecked::append(_key, std::back_inserter(_name));
if ( _key <= 0x7f ) {
_name.push_back(static_cast<uint8_t>(_key));
} else if ( _key <= 0x7ff ) {
_name.push_back(static_cast<uint8_t>((_key >> 6) | 0xc0));
_name.push_back(static_cast<uint8_t>((_key & 0x3f) | 0x80));
} else if ( _key <= 0xffff ) {
_name.push_back(static_cast<uint8_t>((_key >> 12) | 0xe0));
_name.push_back(static_cast<uint8_t>(((_key >> 6) & 0x3f) | 0x80));
_name.push_back(static_cast<uint8_t>((_key & 0x3f) | 0x80));
} else {
_name.push_back(static_cast<uint8_t>((_key >> 18) | 0xf0));
_name.push_back(static_cast<uint8_t>(((_key >> 12) & 0x3f) | 0x80));
_name.push_back(static_cast<uint8_t>(((_key >> 6) & 0x3f) | 0x80));
_name.push_back(static_cast<uint8_t>((_key & 0x3f) | 0x80));
}
}
// Keys on the numpad with NumLock enabled are reported just like their
@@ -305,11 +330,30 @@ namespace canvas
if( key_name.empty() )
return false;
std::string::const_iterator it = key_name.begin();
uint32_t cp = utf8::next(it, key_name.end());
// Convert the key name to the corresponding code point by checking the
// sequence length (the first bits of the first byte) and performing the
// conversion accordingly.
uint32_t cp = key_name[0] & 0xff;
size_t len;
if (cp < 0x80) {
len = 1;
} else if ((cp >> 5) == 0x6) {
cp = ((cp << 6) & 0x7ff) + (key_name[1] & 0x3f);
len = 2;
} else if ((cp >> 4) == 0xe) {
cp = ((cp << 12) & 0xffff) + (((key_name[1] & 0xff) << 6) & 0xfff)
+ (key_name[2] & 0x3f);
len = 3;
} else if ((cp >> 3) == 0x1e) {
cp = ((cp << 18) & 0x1fffff) + (((key_name[1] & 0xff) << 12) & 0x3ffff)
+ (((key_name[2] & 0xff) << 6) & 0xfff) + (key_name[3] & 0x3f);
len = 4;
} else {
return false;
}
// Check if _name contains exactly one (UTF-8 encoded) character.
if( it != key_name.end() )
if (key_name.length() > len)
return false;
// C0 and C1 control characters are not printable.

View File

@@ -45,6 +45,7 @@ namespace canvas
KeyboardEvent();
KeyboardEvent(const osgGA::GUIEventAdapter& ea);
KeyboardEvent* clone(int type = 0) const override;
void setKey(uint32_t key);
void setUnmodifiedKey(uint32_t key);

View File

@@ -1,4 +1,5 @@
// Mouse event
///@file
/// Mouse event
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "MouseEvent.hxx"
#include <osgGA/GUIEventAdapter>
@@ -46,6 +49,14 @@ namespace canvas
button += 1;
}
//----------------------------------------------------------------------------
MouseEvent* MouseEvent::clone(int type) const
{
auto event = new MouseEvent(*this);
event->type = type;
return event;
}
//----------------------------------------------------------------------------
bool MouseEvent::canBubble() const
{

View File

@@ -36,8 +36,9 @@ namespace canvas
public:
MouseEvent();
MouseEvent(const osgGA::GUIEventAdapter& ea);
MouseEvent* clone(int type = 0) const override;
virtual bool canBubble() const;
bool canBubble() const override;
osg::Vec2f getScreenPos() const { return screen_pos; }
osg::Vec2f getClientPos() const { return client_pos; }

View File

@@ -1,4 +1,5 @@
// Keyboard event demo. Press some keys and get some info...
///@file
/// Keyboard event demo. Press some keys and get some info...
//
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
//
@@ -16,6 +17,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "KeyboardEvent.hxx"
#include <osgViewer/Viewer>

View File

@@ -16,6 +16,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "BoxLayout.hxx"
#include "SpacerItem.hxx"
#include <simgear/canvas/Canvas.hxx>

View File

@@ -16,7 +16,11 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "Layout.hxx"
#include <algorithm>
#include <simgear/debug/logstream.hxx>
namespace simgear

View File

@@ -16,6 +16,7 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "LayoutItem.hxx"
#include <simgear/canvas/Canvas.hxx>

View File

@@ -16,6 +16,8 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "NasalWidget.hxx"
#include <simgear/canvas/Canvas.hxx>
@@ -43,7 +45,7 @@ namespace canvas
//----------------------------------------------------------------------------
NasalWidget::~NasalWidget()
{
onRemove();
}
//----------------------------------------------------------------------------
@@ -148,7 +150,7 @@ namespace canvas
//----------------------------------------------------------------------------
bool NasalWidget::hasHeightForWidth() const
{
return !_height_for_width.empty() || !_min_height_for_width.empty();
return _height_for_width || _min_height_for_width;
}
//----------------------------------------------------------------------------
@@ -184,13 +186,13 @@ namespace canvas
int NasalWidget::callHeightForWidthFunc( const HeightForWidthFunc& hfw,
int w ) const
{
if( hfw.empty() )
if( !hfw )
return -1;
naContext c = naNewContext();
try
{
return hfw(nasal::to_nasal(c, const_cast<NasalWidget*>(this)), w);
nasal::Context ctx;
return hfw(ctx.to_me(const_cast<NasalWidget*>(this)), w);
}
catch( std::exception const& ex )
{
@@ -200,7 +202,6 @@ namespace canvas
"NasalWidget.heightForWidth: callback error: '" << ex.what() << "'"
);
}
naFreeContext(c);
return -1;
}
@@ -238,17 +239,17 @@ namespace canvas
//----------------------------------------------------------------------------
int NasalWidget::heightForWidthImpl(int w) const
{
return callHeightForWidthFunc( _height_for_width.empty()
? _min_height_for_width
: _height_for_width, w );
return callHeightForWidthFunc( _height_for_width
? _height_for_width
: _min_height_for_width, w );
}
//----------------------------------------------------------------------------
int NasalWidget::minimumHeightForWidthImpl(int w) const
{
return callHeightForWidthFunc( _min_height_for_width.empty()
? _height_for_width
: _min_height_for_width, w );
return callHeightForWidthFunc( _min_height_for_width
? _min_height_for_width
: _height_for_width, w );
}
@@ -260,8 +261,8 @@ namespace canvas
try
{
nasal::Context c;
_set_geometry(nasal::to_nasal(c, this), rect);
nasal::Context ctx;
_set_geometry(ctx.to_me(this), rect);
_flags &= ~LAYOUT_DIRTY;
}
catch( std::exception const& ex )

View File

@@ -40,8 +40,8 @@ namespace canvas
{
public:
typedef boost::function<void (nasal::Me, const SGRecti&)> SetGeometryFunc;
typedef boost::function<int (nasal::Me, int)> HeightForWidthFunc;
typedef std::function<void (nasal::Me, const SGRecti&)> SetGeometryFunc;
typedef std::function<int (nasal::Me, int)> HeightForWidthFunc;
/**
*

View File

@@ -16,6 +16,7 @@
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#include <simgear_config.h>
#include "SpacerItem.hxx"
namespace simgear

View File

@@ -40,23 +40,12 @@
#define SG_DO_STRINGIZE(X) #X
#ifdef __GNUC__
# if __GNUC__ < 3
# error Time to upgrade. GNU compilers < 3.0 not supported
# elif (__GNUC__ == 3) && (__GNUC_MINOR__ < 4)
# warning GCC compilers prior to 3.4 are suspect
# endif
# define SG_GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
# define SG_COMPILER_STR "GNU C++ version " SG_STRINGIZE(__GNUC__) "." SG_STRINGIZE(__GNUC_MINOR__)
#endif // __GNUC__
/* KAI C++ */
#if defined(__KCC)
# define SG_COMPILER_STR "Kai C++ version " SG_STRINGIZE(__KCC_VERSION)
#endif // __KCC
//
// Microsoft compilers.
//
@@ -70,12 +59,6 @@
# define strdup _strdup
# define copysign _copysign
# endif
# if _MSC_VER < 1800
# define isnan _isnan
# endif
# if _MSC_VER < 1500
# define vsnprintf _vsnprintf
# endif
# pragma warning(disable: 4786) // identifier was truncated to '255' characters
# pragma warning(disable: 4244) // conversion from double to float
@@ -91,49 +74,6 @@
#endif // _MSC_VER
//
// Native SGI compilers
//
#if defined ( sgi ) && !defined( __GNUC__ )
# if (_COMPILER_VERSION < 740)
# error Need MipsPro 7.4.0 or higher now
# endif
#define SG_HAVE_NATIVE_SGI_COMPILERS
#pragma set woff 1001,1012,1014,1116,1155,1172,1174
#pragma set woff 1401,1460,1551,1552,1681
#ifdef __cplusplus
# pragma set woff 1682,3303
# pragma set woff 3624
#endif
# define SG_COMPILER_STR "SGI MipsPro compiler version " SG_STRINGIZE(_COMPILER_VERSION)
#endif // Native SGI compilers
#if defined (__sun)
# define SG_UNIX
# include <strings.h>
# include <memory.h>
# if defined ( __cplusplus )
// typedef unsigned int size_t;
extern "C" {
extern void *memmove(void *, const void *, size_t);
}
# else
extern void *memmove(void *, const void *, size_t);
# endif // __cplusplus
# if !defined( __GNUC__ )
# define SG_COMPILER_STR "Sun compiler version " SG_STRINGIZE(__SUNPRO_CC)
# endif
#endif // sun
//
// Intel C++ Compiler
//
@@ -148,29 +88,10 @@
#ifdef __APPLE__
# define SG_MAC
# define SG_UNIX
# ifdef __GNUC__
# if ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 3 )
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
# else
// any C++ header file undefines isinf and isnan
// so this should be included before <iostream>
// the functions are STILL in libm (libSystem on mac os x)
extern "C" int (isnan)(double);
extern "C" int (isinf)(double);
# endif
# else
inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
# endif
#endif
#if defined (__FreeBSD__)
# define SG_UNIX
#include <sys/param.h>
# if __FreeBSD_version < 500000
extern "C" {
inline int isnan(double r) { return !(r <= 0 || r >= 0); }
}
# endif
#endif
#if defined (__CYGWIN__)
@@ -188,10 +109,13 @@ inline int (isnan)(double r) { return !(r <= 0 || r >= 0); }
# define SG_UNIX
#endif
#if defined( __GNUC__ )
# define DEPRECATED __attribute__ ((deprecated))
#ifdef __GNUC__
#define SG_DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define SG_DEPRECATED(func) __declspec(deprecated) func
#else
# define DEPRECATED
#pragma message("WARNING: You need to implement SG_DEPRECATED for this compiler")
#define SG_DEPRECATED(func) func
#endif
#if defined(__clang__)

Some files were not shown because too many files have changed in this diff Show More