You can subscribe to this list here.
| 2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(28) |
Nov
(193) |
Dec
(199) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2011 |
Jan
(214) |
Feb
(133) |
Mar
(81) |
Apr
(67) |
May
(101) |
Jun
(141) |
Jul
(134) |
Aug
(168) |
Sep
(153) |
Oct
(200) |
Nov
(137) |
Dec
(185) |
| 2012 |
Jan
(168) |
Feb
(153) |
Mar
(155) |
Apr
(183) |
May
(145) |
Jun
(166) |
Jul
(264) |
Aug
(285) |
Sep
(247) |
Oct
(108) |
Nov
(224) |
Dec
(193) |
| 2013 |
Jan
(173) |
Feb
(161) |
Mar
(205) |
Apr
(86) |
May
(81) |
Jun
(115) |
Jul
(115) |
Aug
(89) |
Sep
(83) |
Oct
(155) |
Nov
(123) |
Dec
(111) |
| 2014 |
Jan
(152) |
Feb
(180) |
Mar
(184) |
Apr
(106) |
May
(106) |
Jun
(144) |
Jul
(95) |
Aug
(109) |
Sep
(75) |
Oct
(75) |
Nov
(90) |
Dec
(64) |
| 2015 |
Jan
(59) |
Feb
(114) |
Mar
(64) |
Apr
(73) |
May
(113) |
Jun
(129) |
Jul
(127) |
Aug
(150) |
Sep
(127) |
Oct
(77) |
Nov
(178) |
Dec
(98) |
| 2016 |
Jan
(154) |
Feb
(151) |
Mar
(128) |
Apr
(62) |
May
(185) |
Jun
(120) |
Jul
(105) |
Aug
(91) |
Sep
(90) |
Oct
(165) |
Nov
(299) |
Dec
(203) |
| 2017 |
Jan
(184) |
Feb
(187) |
Mar
(209) |
Apr
(142) |
May
(189) |
Jun
(96) |
Jul
(54) |
Aug
(79) |
Sep
(151) |
Oct
(77) |
Nov
(142) |
Dec
(142) |
| 2018 |
Jan
(194) |
Feb
(175) |
Mar
(111) |
Apr
(85) |
May
(114) |
Jun
(205) |
Jul
(159) |
Aug
(102) |
Sep
(238) |
Oct
(179) |
Nov
(92) |
Dec
(76) |
| 2019 |
Jan
(199) |
Feb
(85) |
Mar
(100) |
Apr
(118) |
May
(80) |
Jun
(69) |
Jul
(91) |
Aug
(91) |
Sep
(137) |
Oct
(59) |
Nov
(82) |
Dec
(70) |
| 2020 |
Jan
(56) |
Feb
(70) |
Mar
(258) |
Apr
(385) |
May
(249) |
Jun
(344) |
Jul
(169) |
Aug
(362) |
Sep
(185) |
Oct
(416) |
Nov
(465) |
Dec
(267) |
| 2021 |
Jan
(279) |
Feb
(312) |
Mar
(378) |
Apr
(230) |
May
(150) |
Jun
(229) |
Jul
(358) |
Aug
(184) |
Sep
(155) |
Oct
(67) |
Nov
(98) |
Dec
(240) |
| 2022 |
Jan
(231) |
Feb
(215) |
Mar
(206) |
Apr
(144) |
May
(71) |
Jun
(18) |
Jul
(27) |
Aug
(66) |
Sep
(95) |
Oct
(65) |
Nov
(95) |
Dec
(76) |
| 2023 |
Jan
(149) |
Feb
(70) |
Mar
(84) |
Apr
(116) |
May
(218) |
Jun
(22) |
Jul
(15) |
Aug
(33) |
Sep
(93) |
Oct
(65) |
Nov
(43) |
Dec
(51) |
| 2024 |
Jan
(87) |
Feb
(84) |
Mar
(64) |
Apr
(33) |
May
(27) |
Jun
(107) |
Jul
(12) |
Aug
(16) |
Sep
(94) |
Oct
(472) |
Nov
(344) |
Dec
(185) |
| 2025 |
Jan
(244) |
Feb
(110) |
Mar
(135) |
Apr
(46) |
May
(50) |
Jun
(73) |
Jul
(74) |
Aug
(63) |
Sep
(55) |
Oct
(82) |
Nov
(39) |
Dec
(22) |
| 2026 |
Jan
(58) |
Feb
(47) |
Mar
(63) |
Apr
(81) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <fli...@li...> - 2026-04-23 21:49:49
|
unknown user pushed a commit to branch release/2024.1 in repository fgmeta. SF URL: http://sourceforge.net/p/flightgear/fgmeta/ci/873e785da7322d26ef7487d9a66a2bcf50046613/ Commit: 873e785da7322d26ef7487d9a66a2bcf50046613 Author: Florent Rougon Committer: Florent Rougon AuthorDate: Wed Apr 22 15:03:15 2026 +0200 Command line parsing in dedicated function --- release_builder/create_shared_models_manifest.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/release_builder/create_shared_models_manifest.py b/release_builder/create_shared_models_manifest.py index fbd0a41..3254538 100755 --- a/release_builder/create_shared_models_manifest.py +++ b/release_builder/create_shared_models_manifest.py @@ -51,9 +51,7 @@ def collect_model_files(base_dir): return files -def main(): - locale.setlocale(locale.LC_ALL, '') - +def parse_command_line(): parser = argparse.ArgumentParser( description="Create SharedModelsManifest.json for FlightGear" ) @@ -64,7 +62,12 @@ def main(): default=None, help="Optional path to the TerraSync directory", ) - args = parser.parse_args() + return parser.parse_args() + + +def main(): + locale.setlocale(locale.LC_ALL, '') + args = parse_command_line() fgdata_dir = os.path.abspath(args.fgdata_dir) if not os.path.isdir(fgdata_dir): |
|
From: <fli...@li...> - 2026-04-23 21:31:51
|
unknown user pushed a commit to branch release/2024.1
in repository simgear.
The following commit(s) were added to refs/heads/release/2024.1 by this push:
new 02118eb4 Add missing <cstdint> header
02118eb4 is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/02118eb46220144b408efab7af381443cd85c311/
Commit: 02118eb46220144b408efab7af381443cd85c311
Author: Florent Rougon
Committer: Florent Rougon
AuthorDate: Thu Apr 23 23:12:31 2026 +0200
Add missing <cstdint> header
---
simgear/io/iostreams/sgstream.hxx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/simgear/io/iostreams/sgstream.hxx b/simgear/io/iostreams/sgstream.hxx
index fc441e65..69dfb077 100644
--- a/simgear/io/iostreams/sgstream.hxx
+++ b/simgear/io/iostreams/sgstream.hxx
@@ -28,10 +28,10 @@
#include <simgear/compiler.h>
+#include <cstdint>
+#include <fstream>
#include <istream>
#include <ostream>
-#include <fstream>
-
#include <string>
#include <vector>
|
|
From: <fli...@li...> - 2026-04-23 15:01:29
|
unknown user pushed a commit to branch release/2024.1 in repository fgmeta. SF URL: http://sourceforge.net/p/flightgear/fgmeta/ci/f3327c505d1ee8add28e09dbbcebb4acfdca2e76/ Commit: f3327c505d1ee8add28e09dbbcebb4acfdca2e76 Author: James Turner Committer: James Turner AuthorDate: Thu Apr 23 11:44:53 2026 +0100 Improvments suggested by Florent - add a schema to the JSON - add a trailing newline Co-authored-by: Copilot <co...@gi...> --- release_builder/create_shared_models_manifest.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/release_builder/create_shared_models_manifest.py b/release_builder/create_shared_models_manifest.py index 065d18a..32e810f 100755 --- a/release_builder/create_shared_models_manifest.py +++ b/release_builder/create_shared_models_manifest.py @@ -91,11 +91,15 @@ def main(): # Deduplicate and sort for a stable, diff-friendly output files = sorted(frozenset(files)) - manifest = {"files": files} + manifest = {"schemaVersion": 1, "files": files} output_path = os.path.join(fgdata_dir, "SharedModelsManifest.json") with open(output_path, "w", encoding="utf-8") as f: + # note we keep the default value (True) of ensure_ascii + # file-names in FGData and TerraSync should be ASCII only, + # no extended UTF-8 characters, for now. json.dump(manifest, f, indent=2) + f.write("\n") print(f"Wrote {len(files)} file entries to {output_path!r}") |
|
From: <fli...@li...> - 2026-04-23 13:38:44
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new ef249c4ce CI: harmonize naming of inputs and reduce verbosity
ef249c4ce is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/ef249c4ce78d8802ade62f769e59901f3f09171c/
Commit: ef249c4ce78d8802ade62f769e59901f3f09171c
Author: Florent Rougon
Committer: Florent Rougon
AuthorDate: Thu Apr 23 15:16:33 2026 +0200
CI: harmonize naming of inputs and reduce verbosity
'string' is the default type for CI inputs; use this fact to make the
YAML header shorter in case we add more inputs in the future.
---
.gitlab-ci.yml | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 897305f98..ac0334050 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,15 +8,14 @@ spec:
default: false
description: "Clear the 'ccache' cache before starting the builds"
- simgear_ref:
- type: string
+ simgear-ref:
default: next
description: "Git ref of the 'simgear' artifacts to fetch"
- fgdata_ref:
- type: string
+ fgdata-ref:
default: next
- description: "Git ref of the 'fgdata' artifacts to fetch"
+ description: >
+ Git ref of the 'fgdata' artifacts to fetch for running the test suite
---
variables:
@@ -142,7 +141,7 @@ linux-build:
- project: flightgear/simgear
job: linux-build
artifacts: true
- ref: $[[ inputs.simgear_ref ]]
+ ref: $[[ inputs.simgear-ref ]]
- project: flightgear/openscenegraph
job: linux-build
ref: $OSG_REF
@@ -177,7 +176,7 @@ linux-qt5-build:
- project: flightgear/simgear
job: linux-qt5-build
artifacts: true
- ref: $[[ inputs.simgear_ref ]]
+ ref: $[[ inputs.simgear-ref ]]
- project: flightgear/openscenegraph
job: linux-build
ref: $OSG_REF
@@ -255,7 +254,7 @@ windows-build:
needs:
- project: flightgear/simgear
job: windows-build
- ref: $[[ inputs.simgear_ref ]]
+ ref: $[[ inputs.simgear-ref ]]
artifacts: true
- project: flightgear/openscenegraph
job: windows_build
@@ -304,7 +303,7 @@ macos-build:
needs:
- project: flightgear/simgear
job: macos-build
- ref: $[[ inputs.simgear_ref ]]
+ ref: $[[ inputs.simgear-ref ]]
artifacts: true
- project: flightgear/openscenegraph
job: macos-build
@@ -334,7 +333,7 @@ test:
artifacts: true
- project: flightgear/fgdata
job: create-test-data
- ref: $[[ inputs.fgdata_ref ]]
+ ref: $[[ inputs.fgdata-ref ]]
artifacts: true
- project: flightgear/openscenegraph
job: linux-build
|
|
From: <fli...@li...> - 2026-04-23 12:17:42
|
unknown user pushed a commit to branch release/2024.1
in repository simgear.
The following commit(s) were added to refs/heads/release/2024.1 by this push:
new fdad83d7 Add sg_gzifstream::read_all
fdad83d7 is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/fdad83d7c11ab2cc15dd2ec1e2f0a79714c971ad/
Commit: fdad83d7c11ab2cc15dd2ec1e2f0a79714c971ad
Author: James Turner
Committer: James Turner
AuthorDate: Thu Apr 23 13:16:14 2026 +0100
Add sg_gzifstream::read_all
---
simgear/io/iostreams/sgstream.cxx | 24 ++++++++++++++++++++++++
simgear/io/iostreams/sgstream.hxx | 20 +++++++++++---------
simgear/io/iostreams/sgstream_test.cxx | 4 ++++
3 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/simgear/io/iostreams/sgstream.cxx b/simgear/io/iostreams/sgstream.cxx
index 70e1e793..2316362f 100755
--- a/simgear/io/iostreams/sgstream.cxx
+++ b/simgear/io/iostreams/sgstream.cxx
@@ -107,6 +107,30 @@ sg_gzifstream::approxOffset() {
return gzbuf.approxOffset();
}
+simgear::UInt8Vector sg_gzifstream::read_all()
+{
+ // seek to end doesn't work for gz API, so read
+ // in a loop until EOF.
+
+ simgear::UInt8Vector result;
+ size_t readCount = 0;
+ const size_t blockSize = 65536;
+ while (gzbuf.is_open() && !eof()) {
+ result.resize(readCount + blockSize);
+ // readsome() seems to fail using gzfilebuf :(
+ read(reinterpret_cast<char*>(result.data()) + readCount, blockSize);
+ const size_t actual = gcount();
+ readCount += actual;
+ if (actual < blockSize) {
+ result.resize(readCount); // trim to actual size read
+ break;
+ }
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
//
// Manipulators
//
diff --git a/simgear/io/iostreams/sgstream.hxx b/simgear/io/iostreams/sgstream.hxx
index 067a3830..fc441e65 100644
--- a/simgear/io/iostreams/sgstream.hxx
+++ b/simgear/io/iostreams/sgstream.hxx
@@ -24,12 +24,7 @@
// $Id$
-#ifndef _SGSTREAM_HXX
-#define _SGSTREAM_HXX
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
+#pragma once
#include <simgear/compiler.h>
@@ -38,10 +33,15 @@
#include <fstream>
#include <string>
+#include <vector>
#include <zlib.h>
#include <simgear/io/iostreams/gzfstream.hxx>
+namespace simgear {
+using UInt8Vector = std::vector<uint8_t>;
+}
+
class SGPath;
/**
@@ -106,6 +106,10 @@ public:
*/
z_off_t approxOffset();
+ /// read the entire stream into a buffer. Use on files, etc - not recommended on streams
+ /// which never EOF, will bvlock forever.
+ simgear::UInt8Vector read_all();
+
private:
// Not defined!
sg_gzifstream( const sg_gzifstream& );
@@ -196,7 +200,7 @@ public:
void open( const SGPath& name,
ios_openmode io_mode = ios_in|ios_binary );
-
+
/// read the entire stream into a buffer. Use on files, etc - not recommended on streams
/// which never EOF, will bvlock forever.
std::string read_all();
@@ -211,5 +215,3 @@ public:
void open( const SGPath& name,
ios_openmode io_mode = ios_out|ios_binary );
};
-
-#endif /* _SGSTREAM_HXX */
diff --git a/simgear/io/iostreams/sgstream_test.cxx b/simgear/io/iostreams/sgstream_test.cxx
index 47a45a6f..dc7edb39 100644
--- a/simgear/io/iostreams/sgstream_test.cxx
+++ b/simgear/io/iostreams/sgstream_test.cxx
@@ -52,5 +52,9 @@ int main()
SG_CHECK_EQUAL(stuff, "end");
cout << "Detection of 2 following CR/LF lines works." << endl;
+ sg_gzifstream sg2(p);
+ auto allBytes = sg2.read_all();
+ SG_CHECK_EQUAL(allBytes.size(), 158);
+
return EXIT_SUCCESS;
}
|
|
From: <fli...@li...> - 2026-04-22 18:49:49
|
unknown user pushed a commit to branch release/2024.1
in repository simgear.
The following commit(s) were added to refs/heads/release/2024.1 by this push:
new 3825fb0c Reduce log spam when one shader fails
3825fb0c is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/3825fb0ce4cf7f43afab43bb905560ab7d8374a7/
Commit: 3825fb0ce4cf7f43afab43bb905560ab7d8374a7
Author: James Turner
Committer: James Turner
AuthorDate: Wed Apr 22 14:01:59 2026 +0100
Reduce log spam when one shader fails
---
simgear/scene/util/SGProgram.cxx | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/simgear/scene/util/SGProgram.cxx b/simgear/scene/util/SGProgram.cxx
index b65dbba0..faa606ea 100644
--- a/simgear/scene/util/SGProgram.cxx
+++ b/simgear/scene/util/SGProgram.cxx
@@ -69,6 +69,12 @@ void SGProgram::apply(osg::State& state) const
for (unsigned int i = 0; i < getNumShaders(); ++i) {
const auto shader = getShader(i);
auto pcs = shader->getPCS(state);
+ // don't warn on shaders that compiled successfully
+ // some drivers return a non-empty info log in this case,
+ // which fills up our logs.
+ if (pcs->isCompiled()) {
+ continue;
+ }
std::string shaderLog;
pcs->getInfoLog(shaderLog);
|
|
From: <fli...@li...> - 2026-04-22 15:48:02
|
unknown user pushed a commit to branch release/2024.1 in repository fgmeta. SF URL: http://sourceforge.net/p/flightgear/fgmeta/ci/ff89dfb555db53a276f076a64b1d703269b4b1dd/ Commit: ff89dfb555db53a276f076a64b1d703269b4b1dd Author: Florent Rougon Committer: Florent Rougon AuthorDate: Wed Apr 22 15:00:55 2026 +0200 Initialize locale --- release_builder/create_shared_models_manifest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release_builder/create_shared_models_manifest.py b/release_builder/create_shared_models_manifest.py index d3c6f97..fbd0a41 100755 --- a/release_builder/create_shared_models_manifest.py +++ b/release_builder/create_shared_models_manifest.py @@ -16,6 +16,7 @@ Example: import argparse import json +import locale import os import sys @@ -51,6 +52,8 @@ def collect_model_files(base_dir): def main(): + locale.setlocale(locale.LC_ALL, '') + parser = argparse.ArgumentParser( description="Create SharedModelsManifest.json for FlightGear" ) |
|
From: <fli...@li...> - 2026-04-22 15:47:56
|
unknown user pushed a commit to branch release/2024.1 in repository fgmeta. SF URL: http://sourceforge.net/p/flightgear/fgmeta/ci/3c27cce10483c825d703e7763540be40a58d415d/ Commit: 3c27cce10483c825d703e7763540be40a58d415d Author: Florent Rougon Committer: Florent Rougon AuthorDate: Wed Apr 22 14:25:30 2026 +0200 Script exit status from main() return value --- release_builder/create_shared_models_manifest.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/release_builder/create_shared_models_manifest.py b/release_builder/create_shared_models_manifest.py index baf2de7..8e7b6d5 100755 --- a/release_builder/create_shared_models_manifest.py +++ b/release_builder/create_shared_models_manifest.py @@ -61,7 +61,7 @@ def main(): if not os.path.isdir(fgdata_dir): print(f"Error: FGData directory not found: {fgdata_dir}", file=sys.stderr) - sys.exit(1) + return 1 files = collect_model_files(fgdata_dir) @@ -86,6 +86,8 @@ def main(): print(f"Written {len(files)} file entries to {output_path}") + return 0 + if __name__ == "__main__": - main() + sys.exit(main()) |
|
From: <fli...@li...> - 2026-04-22 15:47:50
|
unknown user pushed a change to branch release/2024.1
in repository fgmeta.
from eac7724 Apply 3 suggestion(s) to 1 file(s)
new 2147a69 Add script to create shared models list
new c271b63 Executable bit
new c01b398 Line widths and docstring
new 3c27cce Script exit status from main() return value
new ae935ce Small things
new f71fa0e frozenset() might be more efficient
new 9445135 Make sure os.walk() does not silently ignore errors
new ff89dfb Initialize locale
new 873e785 Command line parsing in dedicated function
new ee06bf7 Make Git ignores more specific
new 8953308 Fixes suggested by Florent
The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.gitignore | 24 ++---
release_builder/create_shared_models_manifest.py | 106 +++++++++++++++++++++++
2 files changed, 114 insertions(+), 16 deletions(-)
create mode 100755 release_builder/create_shared_models_manifest.py
|
|
From: <fli...@li...> - 2026-04-22 10:58:25
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new 3857ceda Make AlignFlag public again
3857ceda is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/3857ceda474bab10a5cd9a75e77feccb57e4b45c/
Commit: 3857ceda474bab10a5cd9a75e77feccb57e4b45c
Author: James Turner
Committer: James Turner
AuthorDate: Wed Apr 22 11:26:41 2026 +0100
Make AlignFlag public again
---
simgear/canvas/layout/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/simgear/canvas/layout/CMakeLists.txt b/simgear/canvas/layout/CMakeLists.txt
index 814c3e44..e9f29424 100644
--- a/simgear/canvas/layout/CMakeLists.txt
+++ b/simgear/canvas/layout/CMakeLists.txt
@@ -9,6 +9,7 @@ set(HEADERS
LayoutItem.hxx
NasalWidget.hxx
SpacerItem.hxx
+ AlignFlag_values.hxx
)
if (TARGET SimGearScene)
@@ -20,7 +21,6 @@ if (TARGET SimGearScene)
LayoutItem.cxx
NasalWidget.cxx
SpacerItem.cxx
- AlignFlag_values.hxx
${HEADERS})
install(FILES ${HEADERS} DESTINATION include/simgear/canvas/layout)
endif()
|
|
From: <fli...@li...> - 2026-04-22 09:37:48
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new ff1cdad6 Make CanvasEventTypes public again
ff1cdad6 is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/ff1cdad6dfd807598007f6abbee905606259f286/
Commit: ff1cdad6dfd807598007f6abbee905606259f286
Author: James Turner
Committer: James Turner
AuthorDate: Wed Apr 22 10:21:33 2026 +0100
Make CanvasEventTypes public again
---
simgear/canvas/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/simgear/canvas/CMakeLists.txt b/simgear/canvas/CMakeLists.txt
index ac5daef2..4d09fac7 100644
--- a/simgear/canvas/CMakeLists.txt
+++ b/simgear/canvas/CMakeLists.txt
@@ -12,6 +12,7 @@ set(HEADERS
CanvasWindow.hxx
ODGauge.hxx
VGInitOperation.hxx
+ CanvasEventTypes.hxx
)
add_subdirectory(ShaderVG/src)
@@ -32,7 +33,6 @@ if (TARGET SimGearScene)
ODGauge.cxx
VGInitOperation.cxx
CanvasEventManager.hxx
- CanvasEventTypes.hxx
CanvasEventVisitor.hxx
${HEADERS})
install(FILES ${HEADERS} DESTINATION include/simgear/canvas)
|
|
From: <fli...@li...> - 2026-04-20 21:49:49
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new 6a601a6ac Remove HLA support
6a601a6ac is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/6a601a6aca65e6b5d720d905e3446524fc578f25/
Commit: 6a601a6aca65e6b5d720d905e3446524fc578f25
Author: James Turner
Committer: James Turner
AuthorDate: Sun Apr 19 20:43:15 2026 +0100
Remove HLA support
---
CMakeLists.txt | 6 -
CMakeModules/SetupFGFSLibraries.cmake | 7 -
src/Include/config_cmake.h.in | 1 -
src/Main/fg_io.cxx | 28 +-
src/Main/options.cxx | 5 -
src/Network/CMakeLists.txt | 7 +-
src/Network/HLA/CMakeLists.txt | 7 -
src/Network/HLA/hla.cxx | 1326 -------------------------
src/Network/HLA/hla.hxx | 56 --
utils/CMakeLists.txt | 6 +-
utils/fgai/AIBVHPager.cxx | 153 ---
utils/fgai/AIBVHPager.hxx | 49 -
utils/fgai/AIEnvironment.cxx | 37 -
utils/fgai/AIEnvironment.hxx | 48 -
utils/fgai/AIManager.cxx | 228 -----
utils/fgai/AIManager.hxx | 77 --
utils/fgai/AIObject.cxx | 103 --
utils/fgai/AIObject.hxx | 92 --
utils/fgai/AIPhysics.cxx | 104 --
utils/fgai/AIPhysics.hxx | 108 --
utils/fgai/AISubsystem.hxx | 60 --
utils/fgai/CMakeLists.txt | 27 -
utils/fgai/HLAAirVehicle.cxx | 49 -
utils/fgai/HLAAirVehicle.hxx | 54 -
utils/fgai/HLAAirVehicleClass.cxx | 54 -
utils/fgai/HLAAirVehicleClass.hxx | 52 -
utils/fgai/HLAAircraft.cxx | 50 -
utils/fgai/HLAAircraft.hxx | 46 -
utils/fgai/HLAAircraftClass.cxx | 52 -
utils/fgai/HLAAircraftClass.hxx | 46 -
utils/fgai/HLABaloon.cxx | 50 -
utils/fgai/HLABaloon.hxx | 41 -
utils/fgai/HLABaloonClass.cxx | 52 -
utils/fgai/HLABaloonClass.hxx | 46 -
utils/fgai/HLAMPAircraft.cxx | 50 -
utils/fgai/HLAMPAircraft.hxx | 62 --
utils/fgai/HLAMPAircraftClass.cxx | 56 --
utils/fgai/HLAMPAircraftClass.hxx | 59 --
utils/fgai/HLASceneObject.cxx | 67 --
utils/fgai/HLASceneObject.hxx | 45 -
utils/fgai/HLASceneObjectClass.cxx | 58 --
utils/fgai/HLASceneObjectClass.hxx | 67 --
utils/fgai/fgai.cxx | 592 -----------
utils/fgviewer/CMakeLists.txt | 41 +-
utils/fgviewer/HLACamera.cxx | 55 -
utils/fgviewer/HLACamera.hxx | 81 --
utils/fgviewer/HLACameraClass.cxx | 62 --
utils/fgviewer/HLACameraClass.hxx | 77 --
utils/fgviewer/HLACameraManipulator.cxx | 248 -----
utils/fgviewer/HLACameraManipulator.hxx | 64 --
utils/fgviewer/HLADrawable.cxx | 52 -
utils/fgviewer/HLADrawable.hxx | 60 --
utils/fgviewer/HLADrawableClass.cxx | 56 --
utils/fgviewer/HLADrawableClass.hxx | 59 --
utils/fgviewer/HLAEyeTracker.cxx | 51 -
utils/fgviewer/HLAEyeTracker.hxx | 52 -
utils/fgviewer/HLAEyeTrackerClass.cxx | 54 -
utils/fgviewer/HLAEyeTrackerClass.hxx | 53 -
utils/fgviewer/HLAMPAircraft.cxx | 82 --
utils/fgviewer/HLAMPAircraft.hxx | 45 -
utils/fgviewer/HLAMPAircraftClass.cxx | 55 -
utils/fgviewer/HLAMPAircraftClass.hxx | 52 -
utils/fgviewer/HLAObjectReferenceData.hxx | 176 ----
utils/fgviewer/HLAOrthographicCamera.cxx | 51 -
utils/fgviewer/HLAOrthographicCamera.hxx | 64 --
utils/fgviewer/HLAOrthographicCameraClass.cxx | 57 --
utils/fgviewer/HLAOrthographicCameraClass.hxx | 64 --
utils/fgviewer/HLAPerspectiveCamera.cxx | 82 --
utils/fgviewer/HLAPerspectiveCamera.hxx | 77 --
utils/fgviewer/HLAPerspectiveCameraClass.cxx | 59 --
utils/fgviewer/HLAPerspectiveCameraClass.hxx | 70 --
utils/fgviewer/HLAPerspectiveViewer.cxx | 118 ---
utils/fgviewer/HLAPerspectiveViewer.hxx | 75 --
utils/fgviewer/HLAPerspectiveViewerClass.cxx | 60 --
utils/fgviewer/HLAPerspectiveViewerClass.hxx | 70 --
utils/fgviewer/HLAProxyDataElement.hxx | 90 --
utils/fgviewer/HLARenderer.cxx | 50 -
utils/fgviewer/HLARenderer.hxx | 41 -
utils/fgviewer/HLARendererClass.cxx | 52 -
utils/fgviewer/HLARendererClass.hxx | 47 -
utils/fgviewer/HLASceneObject.cxx | 314 ------
utils/fgviewer/HLASceneObject.hxx | 86 --
utils/fgviewer/HLASceneObjectClass.cxx | 59 --
utils/fgviewer/HLASceneObjectClass.hxx | 76 --
utils/fgviewer/HLAView.cxx | 135 ---
utils/fgviewer/HLAView.hxx | 76 --
utils/fgviewer/HLAViewClass.cxx | 58 --
utils/fgviewer/HLAViewClass.hxx | 65 --
utils/fgviewer/HLAViewer.cxx | 49 -
utils/fgviewer/HLAViewer.hxx | 41 -
utils/fgviewer/HLAViewerClass.cxx | 52 -
utils/fgviewer/HLAViewerClass.hxx | 47 -
utils/fgviewer/HLAViewerFederate.cxx | 253 -----
utils/fgviewer/HLAViewerFederate.hxx | 98 --
utils/fgviewer/HLAWindowDrawable.cxx | 50 -
utils/fgviewer/HLAWindowDrawable.hxx | 58 --
utils/fgviewer/HLAWindowDrawableClass.cxx | 55 -
utils/fgviewer/HLAWindowDrawableClass.hxx | 58 --
utils/fgviewer/SlaveCamera.cxx | 98 +-
utils/fgviewer/SlaveCamera.hxx | 32 +-
utils/fgviewer/Viewer.cxx | 80 +-
utils/fgviewer/Viewer.hxx | 35 +-
utils/fgviewer/fgviewer.cxx | 47 +-
103 files changed, 55 insertions(+), 8652 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1e7239a85..1ee493db9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,7 +182,6 @@ option(SP_FDMS "Set to ON to build FlightGear with special-purpose FDM
option(ENABLE_YASIM "Set to ON to build FlightGear with YASIM FDM (default)" ON)
option(ENABLE_JSBSIM "Set to ON to build FlightGear with JSBSim FDM (default)" ON)
option(EVENT_INPUT "Set to ON to build FlightGear with event-based Input support" ${EVENT_INPUT_DEFAULT})
-option(ENABLE_RTI "Set to ON to build FlightGear with RTI support" OFF)
option(SYSTEM_SQLITE "Set to ON to build FlightGear with the system's SQLite3 library" OFF)
option(ENABLE_IAX "Set to ON to build FlightGear with IAXClient/fgcom built-in (default)" ON)
option(USE_DBUS "Set to ON to build FlightGear with DBus screensaver interaction (default on Linux)" ${USE_DBUS_DEFAULT})
@@ -451,11 +450,6 @@ else()
message(STATUS "Data Distribution Service support: DISABLED")
endif()
-if(ENABLE_RTI)
- message(STATUS "RTI: ENABLED")
- set(FG_HAVE_HLA 1)
-endif(ENABLE_RTI)
-
if (ENABLE_SIMD)
message(STATUS "SSE/SSE2 support: ENABLED")
endif()
diff --git a/CMakeModules/SetupFGFSLibraries.cmake b/CMakeModules/SetupFGFSLibraries.cmake
index d0abba15e..d0165d556 100644
--- a/CMakeModules/SetupFGFSLibraries.cmake
+++ b/CMakeModules/SetupFGFSLibraries.cmake
@@ -1,12 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: James Turner <ja...@fl...>
function(setup_fgfs_libraries target)
- if(RTI_FOUND)
- set(HLA_LIBRARIES ${RTI_LDFLAGS})
- else()
- set(HLA_LIBRARIES "")
- endif()
-
if(ENABLE_JSBSIM)
target_link_libraries(${target} PRIVATE JSBSim)
endif()
@@ -34,7 +28,6 @@ function(setup_fgfs_libraries target)
SimGearScene
Boost::boost
${EVENT_INPUT_LIBRARIES}
- ${HLA_LIBRARIES}
${OPENGL_LIBRARIES}
${OPENSCENEGRAPH_LIBRARIES}
${PLATFORM_LIBS}
diff --git a/src/Include/config_cmake.h.in b/src/Include/config_cmake.h.in
index 98700906f..b56454fe6 100644
--- a/src/Include/config_cmake.h.in
+++ b/src/Include/config_cmake.h.in
@@ -42,7 +42,6 @@
#define WEB_BROWSER "@WEB_BROWSER@"
// Ensure FG_HAVE_xxx always have a value
-#define FG_HAVE_HLA (@FG_HAVE_HLA@ + 0)
#define FG_HAVE_DDS (@FG_HAVE_DDS@ + 0)
#define FG_HAVE_GPERFTOOLS (@FG_HAVE_GPERFTOOLS@ + 0)
diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx
index 932828c44..4b74c2790 100644
--- a/src/Main/fg_io.cxx
+++ b/src/Main/fg_io.cxx
@@ -52,10 +52,6 @@
#include <simgear/io/SGDataDistributionService.hxx>
#include <Network/dds_props.hxx>
#endif
-#if FG_HAVE_HLA
-#include <Network/HLA/hla.hxx>
-#endif
-
#include "globals.hxx"
#include "fg_io.hxx"
@@ -194,29 +190,7 @@ FGIO::parse_port_config( const string_list& tokens, bool& o_ok )
}
o_ok = true;
return NULL;
- }
-#if FG_HAVE_HLA
- else if ( protocol == "hla" ) {
- o_ok = true;
- return new FGHLA(tokens);
- }
- else if ( protocol == "hla-local" ) {
- // This is just about to bring up some defaults
- if (tokens.size() != 2) {
- SG_LOG( SG_IO, SG_ALERT, "Ignoring invalid --hla-local option "
- "(one argument expected: --hla-local=<federationname>" );
- return NULL;
- }
- std::vector<std::string> HLA_tokens (tokens);
- HLA_tokens.insert(HLA_tokens.begin(), "");
- HLA_tokens.insert(HLA_tokens.begin(), "60");
- HLA_tokens.insert(HLA_tokens.begin(), "bi");
- HLA_tokens.push_back("fg-local.xml");
- o_ok = true;
- return new FGHLA(HLA_tokens);
- }
-#endif
- else {
+ } else {
return NULL;
}
}
diff --git a/src/Main/options.cxx b/src/Main/options.cxx
index 06d6e9a4b..8c35fd24d 100644
--- a/src/Main/options.cxx
+++ b/src/Main/options.cxx
@@ -249,7 +249,6 @@ void fgSetDefaults ()
v->setValueReadOnly("openscenegraph", osgGetVersion());
v->setValueReadOnly("revision", REVISION);
v->setValueReadOnly("build-date", BUILD_DATE);
- v->setValueReadOnly("hla-support", bool(FG_HAVE_HLA));
v->setValueReadOnly("build-type", FG_BUILD_TYPE);
char* envp = ::getenv( "http_proxy" );
@@ -1936,10 +1935,6 @@ const std::initializer_list<OptionDesc> fgOptionArray = {
{"proxy", ParamType::REGULAR, OptionType::OPT_FUNC, "", false, "", fgSetupProxy },
{"callsign", ParamType::REGULAR, OptionType::OPT_FUNC, "", false, "", fgOptCallSign},
{"multiplay", ParamType::REGULAR, OptionType::OPT_CHANNEL | OPTION_MULTI, "", false, "", 0 },
-#if FG_HAVE_HLA
- {"hla", ParamType::REGULAR, OptionType::OPT_CHANNEL, "", false, "", 0 },
- {"hla-local", ParamType::REGULAR, OptionType::OPT_CHANNEL, "", false, "", 0 },
-#endif
{"trace-read", ParamType::REGULAR, OptionType::OPT_FUNC | OPTION_MULTI, "", false, "", fgOptTraceRead },
{"trace-write", ParamType::REGULAR, OptionType::OPT_FUNC | OPTION_MULTI, "", false, "", fgOptTraceWrite },
{"log-level", ParamType::REGULAR, OptionType::OPT_FUNC, "", false, "", fgOptLogLevel },
diff --git a/src/Network/CMakeLists.txt b/src/Network/CMakeLists.txt
index 2c11fcb26..38b76551c 100644
--- a/src/Network/CMakeLists.txt
+++ b/src/Network/CMakeLists.txt
@@ -1,3 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2010 James Turner <ja...@fl...>
+
include(FlightGearComponent)
set(SOURCES
@@ -83,10 +86,6 @@ if (CycloneDDS_FOUND)
add_subdirectory(DDS)
endif()
-if(RTI_FOUND)
- add_subdirectory(HLA)
-endif()
-
add_subdirectory(http)
if(ENABLE_SWIFT)
diff --git a/src/Network/HLA/CMakeLists.txt b/src/Network/HLA/CMakeLists.txt
deleted file mode 100644
index aeed0529d..000000000
--- a/src/Network/HLA/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-include(FlightGearComponent)
-
-set(SOURCES
- hla.cxx
- )
-
-flightgear_component(HLA "${SOURCES}")
diff --git a/src/Network/HLA/hla.cxx b/src/Network/HLA/hla.cxx
deleted file mode 100644
index 8761c7615..000000000
--- a/src/Network/HLA/hla.cxx
+++ /dev/null
@@ -1,1326 +0,0 @@
-//
-// Copyright (C) 2009 - 2012 Mathias Fröhlich <Mat...@we...>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "hla.hxx"
-
-#include <simgear/compiler.h>
-
-#include <algorithm>
-#include <list>
-#include <map>
-#include <string>
-#include <stack>
-
-#include <simgear/debug/logstream.hxx>
-#include <simgear/math/SGMath.hxx>
-#include <simgear/misc/sg_path.hxx>
-#include <simgear/props/props.hxx>
-#include <simgear/structure/exception.hxx>
-#include <simgear/xml/easyxml.hxx>
-
-#include <simgear/hla/HLAFederate.hxx>
-#include <simgear/hla/HLAArrayDataElement.hxx>
-#include <simgear/hla/HLADataElement.hxx>
-#include <simgear/hla/HLADataType.hxx>
-#include <simgear/hla/HLALocation.hxx>
-#include <simgear/hla/HLAObjectClass.hxx>
-#include <simgear/hla/HLAObjectInstance.hxx>
-#include <simgear/hla/HLAPropertyDataElement.hxx>
-#include <simgear/hla/HLAVariantRecordDataElement.hxx>
-
-#include <AIModel/AIMultiplayer.hxx>
-#include <AIModel/AIManager.hxx>
-
-#include <FDM/flightProperties.hxx>
-
-#include <Main/fg_props.hxx>
-#include <Main/globals.hxx>
-
-// FIXME rename HLAMP
-// FIXME make classes here private ...
-
-namespace sg = simgear;
-
-enum HLAVersion {
- RTI13,
- RTI1516,
- RTI1516E
-};
-
-class FGHLA::XMLConfigReader : public XMLVisitor {
-public:
- XMLConfigReader() :
- _rtiVersion(RTI13)
- { }
-
- const std::string& getFederateObjectModel() const
- { return _federateObjectModel; }
-
- HLAVersion getRTIVersion() const
- { return _rtiVersion; }
- const std::list<std::string>& getRTIArguments() const
- { return _rtiArguments; }
-
- struct DataElement {
- std::string _type;
- std::string _name;
- std::string _inProperty;
- std::string _outProperty;
- };
- typedef std::list<DataElement> DataElementList;
- struct ModelConfig {
- std::string _type;
- DataElementList _dataElementList;
- std::list<std::pair<std::string, std::string> > _modelMap;
- };
- struct SimTimeConfig {
- std::string _type;
- DataElementList _dataElementList;
- };
- struct PositionConfig {
- std::string _type;
- DataElementList _dataElementList;
- };
- struct MPPropertiesConfig {
- std::string _name;
- };
- struct ObjectClassConfig {
- std::string _name;
- std::string _type;
- ModelConfig _modelConfig;
- SimTimeConfig _simTimeConfig;
- PositionConfig _positionConfig;
- MPPropertiesConfig _mpPropertiesConfig;
- DataElementList _dataElementList;
- };
- typedef std::list<ObjectClassConfig> ObjectClassConfigList;
-
- const ObjectClassConfigList& getObjectClassConfigList() const
- { return _objectClassConfigList; }
-
-protected:
- virtual void startXML()
- {
- _modeStack.push(TopLevelMode);
- }
- virtual void endXML()
- {
- _modeStack.pop();
- }
- virtual void startElement(const char* name, const XMLAttributes& atts)
- {
- if (strcmp(name, "hlaConfiguration") == 0) {
- if (!isModeStackTop(TopLevelMode))
- throw sg_exception("hlaConfiguration tag not at top level");
-
- _modeStack.push(HLAConfigurationMode);
- }
-
- else if (strcmp(name, "rti") == 0) {
- if (!isModeStackTop(HLAConfigurationMode))
- throw sg_exception("rti tag not at top level");
-
- std::string rtiVersion = getAttribute("version", atts);
- if (rtiVersion == "RTI13")
- _rtiVersion = RTI13;
- else if (rtiVersion == "RTI1516")
- _rtiVersion = RTI1516;
- else if (rtiVersion == "RTI1516E")
- _rtiVersion = RTI1516E;
- else
- throw sg_exception("invalid version attribute in rti tag");
-
- _modeStack.push(RTIMode);
- }
- else if (strcmp(name, "argument") == 0) {
- if (!isModeStackTop(RTIMode))
- throw sg_exception("argument tag not inside an rti tag");
-
- _modeStack.push(RTIArgumentMode);
- _rtiArguments.push_back(std::string());
- }
-
- else if (strcmp(name, "objects") == 0) {
- if (!isModeStackTop(HLAConfigurationMode))
- throw sg_exception("objects tag not at top level");
-
- _modeStack.push(ObjectsMode);
- }
- else if (strcmp(name, "objectClass") == 0) {
- // Currently this is flat and only allows one class to be configured
- if (!isModeStackTop(ObjectsMode))
- throw sg_exception("objects tag not inside an objects tag");
- if (!_objectClassConfigList.empty())
- throw sg_exception("currently only one objectClass is allowed");
- // if (!isModeStackTop(ObjectsMode) && !isModeStackTop(ObjectClassMode))
- // throw sg_exception("objects tag not inside an objects or objectClass tag");
-
- ObjectClassConfig objectClassConfig;
- objectClassConfig._type = getAttribute("type", atts);
- objectClassConfig._name = getAttribute("name", atts);
- _objectClassConfigList.push_back(objectClassConfig);
-
- _modeStack.push(ObjectClassMode);
- }
- else if (strcmp(name, "model") == 0) {
- if (!isModeStackTop(ObjectClassMode))
- throw sg_exception("position tag not inside an objectClass tag");
-
- _objectClassConfigList.back()._modelConfig._type = getAttribute("type", atts);
-
- _modeStack.push(ModelMode);
- }
- else if (strcmp(name, "key") == 0) {
- if (!isModeStackTop(ModelMode))
- throw sg_exception("key tag not inside an model tag");
-
- std::pair<std::string,std::string> p;
- p.first = getAttribute("external", atts);
- p.second = getAttribute("modelPath", atts);
- _objectClassConfigList.back()._modelConfig._modelMap.push_back(p);
-
- _modeStack.push(KeyMode);
- }
- else if (strcmp(name, "simTime") == 0) {
- if (!isModeStackTop(ObjectClassMode))
- throw sg_exception("simTime tag not inside an objectClass tag");
-
- _objectClassConfigList.back()._simTimeConfig._type = getAttribute("type", atts);
-
- _modeStack.push(SimTimeMode);
- }
- else if (strcmp(name, "position") == 0) {
- if (!isModeStackTop(ObjectClassMode))
- throw sg_exception("position tag not inside an objectClass tag");
-
- _objectClassConfigList.back()._positionConfig._type = getAttribute("type", atts);
-
- _modeStack.push(PositionMode);
- }
- else if (strcmp(name, "mpProperties") == 0) {
- if (!isModeStackTop(ObjectClassMode))
- throw sg_exception("mpProperties tag not inside an objectClass tag");
-
- _objectClassConfigList.back()._mpPropertiesConfig._name = getAttribute("name", atts);
-
- _modeStack.push(MPPropertiesMode);
- }
- else if (strcmp(name, "dataElement") == 0) {
-
- DataElement dataElement;
- dataElement._type = getAttribute("type", atts);
- dataElement._name = getAttribute("name", atts);
- if (isModeStackTop(ModelMode)) {
- _objectClassConfigList.back()._modelConfig._dataElementList.push_back(dataElement);
- } else if (isModeStackTop(SimTimeMode)) {
- _objectClassConfigList.back()._simTimeConfig._dataElementList.push_back(dataElement);
- } else if (isModeStackTop(PositionMode)) {
- _objectClassConfigList.back()._positionConfig._dataElementList.push_back(dataElement);
- } else if (isModeStackTop(ObjectClassMode)) {
- std::string io = getAttribute("io", atts);
- dataElement._inProperty = getAttribute("in", atts);
- if (dataElement._inProperty.empty())
- dataElement._inProperty = io;
- dataElement._outProperty = getAttribute("out", atts);
- if (dataElement._outProperty.empty())
- dataElement._outProperty = io;
- _objectClassConfigList.back()._dataElementList.push_back(dataElement);
- } else {
- throw sg_exception("dataElement tag not inside a position, model or objectClass tag");
- }
-
- _modeStack.push(DataElementMode);
- }
-
- else if (strcmp(name, "federateObjectModel") == 0) {
- if (!isModeStackTop(HLAConfigurationMode))
- throw sg_exception("federateObjectModel tag not at top level");
-
- _federateObjectModel = getAttribute("name", atts);
- _modeStack.push(FederateObjectModelMode);
- }
-
- else {
- throw sg_exception(std::string("Unknown tag ") + name);
- }
- }
-
- virtual void data(const char * s, int length)
- {
- if (isModeStackTop(RTIArgumentMode)) {
- _rtiArguments.back().append(s, length);
- }
- }
-
- virtual void endElement(const char* name)
- {
- _modeStack.pop();
- }
-
- std::string getAttribute(const char* name, const XMLAttributes& atts)
- {
- int index = atts.findAttribute(name);
- if (index < 0 || atts.size() <= index)
- return std::string();
- return std::string(atts.getValue(index));
- }
- std::string getAttribute(const std::string& name, const XMLAttributes& atts)
- {
- int index = atts.findAttribute(name.c_str());
- if (index < 0 || atts.size() <= index)
- return std::string();
- return std::string(atts.getValue(index));
- }
-
-private:
- // poor peoples xml validation ...
- enum Mode {
- TopLevelMode,
- HLAConfigurationMode,
- RTIMode,
- RTIArgumentMode,
- ObjectsMode,
- ObjectClassMode,
- ModelMode,
- KeyMode,
- SimTimeMode,
- PositionMode,
- MPPropertiesMode,
- DataElementMode,
- FederateObjectModelMode
- };
- bool isModeStackTop(Mode mode)
- {
- if (_modeStack.empty())
- return false;
- return _modeStack.top() == mode;
- }
- std::stack<Mode> _modeStack;
-
- std::string _federateObjectModel;
- HLAVersion _rtiVersion;
- std::list<std::string> _rtiArguments;
-
- ObjectClassConfigList _objectClassConfigList;
-};
-
-class PropertyReferenceSet : public SGReferenced {
-public:
- void insert(const std::string& relativePath, const SGSharedPtr<sg::HLAPropertyDataElement>& dataElement)
- {
- if (_rootNode.valid())
- dataElement->setPropertyNode(_rootNode->getNode(relativePath, true));
- _pathDataElementPairList.push_back(PathDataElementPair(relativePath, dataElement));
- }
-
- void setRootNode(SGPropertyNode* rootNode)
- {
- _rootNode = rootNode;
- for (PathDataElementPairList::iterator i = _pathDataElementPairList.begin();
- i != _pathDataElementPairList.end(); ++i) {
- i->second->setPropertyNode(_rootNode->getNode(i->first, true));
- }
- }
- SGPropertyNode* getRootNode()
- { return _rootNode.get(); }
-
-private:
- SGSharedPtr<SGPropertyNode> _rootNode;
-
- typedef std::pair<std::string, SGSharedPtr<sg::HLAPropertyDataElement> > PathDataElementPair;
- typedef std::list<PathDataElementPair> PathDataElementPairList;
- PathDataElementPairList _pathDataElementPairList;
-};
-
-class AbstractSimTime : public SGReferenced {
-public:
- virtual ~AbstractSimTime() {}
-
- virtual double getTimeStamp() const = 0;
- virtual void setTimeStamp(double) = 0;
-};
-
-class AbstractModel : public SGReferenced {
-public:
- virtual ~AbstractModel() {}
-
- virtual std::string getModelPath() const = 0;
- virtual void setModelPath(const std::string&) = 0;
-};
-
-// Factory class that is used to create an apternative data element for the multiplayer property attribute
-class MPPropertyVariantRecordDataElementFactory :
- public sg::HLAVariantArrayDataElement::AlternativeDataElementFactory {
-public:
- MPPropertyVariantRecordDataElementFactory(PropertyReferenceSet* propertyReferenceSet) :
- _propertyReferenceSet(propertyReferenceSet)
- { }
-
- virtual sg::HLADataElement* createElement(const sg::HLAVariantRecordDataElement& variantRecordDataElement, unsigned index)
- {
- const sg::HLAVariantRecordDataType* dataType = variantRecordDataElement.getDataType();
- if (!dataType)
- return 0;
- const sg::HLAEnumeratedDataType* enumDataType = dataType->getEnumeratedDataType();
- if (!enumDataType)
- return 0;
- const sg::HLADataType* alternativeDataType = dataType->getAlternativeDataType(index);
- if (!alternativeDataType)
- return 0;
-
- // The relative property path should be in the semantics field name
- std::string relativePath = dataType->getAlternativeSemantics(index);
- sg::HLAPropertyDataElement* dataElement = new sg::HLAPropertyDataElement(alternativeDataType, (SGPropertyNode*)0);
- _propertyReferenceSet->insert(relativePath, dataElement);
- return dataElement;
- }
-
-private:
- SGSharedPtr<PropertyReferenceSet> _propertyReferenceSet;
-};
-
-class FGHLA::MultiplayerObjectInstance : public sg::HLAObjectInstance {
-public:
- MultiplayerObjectInstance(sg::HLAObjectClass* objectClass) :
- sg::HLAObjectInstance(objectClass),
- _propertyReferenceSet(new PropertyReferenceSet),
- _mpProperties(new sg::HLAVariantArrayDataElement)
- {
- _mpProperties->setAlternativeDataElementFactory(new MPPropertyVariantRecordDataElementFactory(_propertyReferenceSet.get()));
- }
- virtual ~MultiplayerObjectInstance()
- { }
-
- SGSharedPtr<PropertyReferenceSet> _propertyReferenceSet;
- SGSharedPtr<sg::HLAAbstractLocation> _location;
- SGSharedPtr<AbstractSimTime> _simTime;
- SGSharedPtr<AbstractModel> _model;
- SGSharedPtr<sg::HLAVariantArrayDataElement> _mpProperties;
-};
-
-class FGHLA::MPUpdateCallback : public sg::HLAObjectInstance::UpdateCallback {
-public:
- virtual void updateAttributeValues(sg::HLAObjectInstance& objectInstance, const sg::RTIData& tag)
- {
- updateAttributeValues(static_cast<MultiplayerObjectInstance&>(objectInstance));
- objectInstance.encodeAttributeValues();
- objectInstance.sendAttributeValues(tag);
- }
-
- virtual void updateAttributeValues(sg::HLAObjectInstance& objectInstance, const SGTimeStamp& timeStamp, const sg::RTIData& tag)
- {
- updateAttributeValues(static_cast<MultiplayerObjectInstance&>(objectInstance));
- objectInstance.encodeAttributeValues();
- objectInstance.sendAttributeValues(timeStamp, tag);
- }
-
- void updateAttributeValues(MultiplayerObjectInstance& objectInstance)
- {
- objectInstance._simTime->setTimeStamp(globals->get_sim_time_sec());
-
- SGGeod position = _ifce.getPosition();
- // The quaternion rotating from the earth centered frame to the
- // horizontal local frame
- SGQuatd qEc2Hl = SGQuatd::fromLonLat(position);
- SGQuatd hlOr = SGQuatd::fromYawPitchRoll(_ifce.get_Psi(), _ifce.get_Theta(), _ifce.get_Phi());
- objectInstance._location->setCartPosition(SGVec3d::fromGeod(position));
- objectInstance._location->setCartOrientation(qEc2Hl*hlOr);
- // The angular velocitied in the body frame
- double p = _ifce.get_P_body();
- double q = _ifce.get_Q_body();
- double r = _ifce.get_R_body();
- objectInstance._location->setAngularBodyVelocity(SGVec3d(p, q, r));
- // The body uvw velocities in the interface are wrt the wind instead
- // of wrt the ec frame
- double n = _ifce.get_V_north()*SG_FEET_TO_METER;
- double e = _ifce.get_V_east()*SG_FEET_TO_METER;
- double d = _ifce.get_V_down()*SG_FEET_TO_METER;
- objectInstance._location->setLinearBodyVelocity(hlOr.transform(SGVec3d(n, e, d)));
-
- if (objectInstance._mpProperties.valid() && objectInstance._mpProperties->getNumElements() == 0) {
- if (objectInstance._propertyReferenceSet.valid() && objectInstance._propertyReferenceSet->getRootNode()) {
- const sg::HLADataType* elementDataType = objectInstance._mpProperties->getElementDataType();
- const sg::HLAVariantRecordDataType* variantRecordDataType = elementDataType->toVariantRecordDataType();
- for (unsigned i = 0, count = 0; i < variantRecordDataType->getNumAlternatives(); ++i) {
- std::string name = variantRecordDataType->getAlternativeSemantics(i);
- SGPropertyNode* node = objectInstance._propertyReferenceSet->getRootNode()->getNode(name);
- if (!node)
- continue;
- objectInstance._mpProperties->getOrCreateElement(count++)->setAlternativeIndex(i);
- }
- }
- }
- }
-
- FlightProperties _ifce;
-};
-
-class FGHLA::MPReflectCallback : public sg::HLAObjectInstance::ReflectCallback {
-public:
- virtual void reflectAttributeValues(sg::HLAObjectInstance& objectInstance,
- const sg::HLAIndexList& indexList, const sg::RTIData& tag)
- {
- objectInstance.reflectAttributeValues(indexList, tag);
- reflectAttributeValues(static_cast<MultiplayerObjectInstance&>(objectInstance));
- }
- virtual void reflectAttributeValues(sg::HLAObjectInstance& objectInstance, const sg::HLAIndexList& indexList,
- const SGTimeStamp& timeStamp, const sg::RTIData& tag)
- {
- objectInstance.reflectAttributeValues(indexList, timeStamp, tag);
- reflectAttributeValues(static_cast<MultiplayerObjectInstance&>(objectInstance));
- }
-
- void reflectAttributeValues(MultiplayerObjectInstance& objectInstance)
- {
- // Puh, damn ordering problems with properties startup and so on
- if (_aiMultiplayer.valid()) {
- FGExternalMotionData motionInfo;
- motionInfo.time = objectInstance._simTime->getTimeStamp();
- motionInfo.lag = 0;
-
- motionInfo.position = objectInstance._location->getCartPosition();
- motionInfo.orientation = toQuatf(objectInstance._location->getCartOrientation());
- motionInfo.linearVel = toVec3f(objectInstance._location->getLinearBodyVelocity());
- motionInfo.angularVel = toVec3f(objectInstance._location->getAngularBodyVelocity());
- motionInfo.linearAccel = SGVec3f::zeros();
- motionInfo.angularAccel = SGVec3f::zeros();
-
- _aiMultiplayer->addMotionInfo(motionInfo, SGTimeStamp::now().getSeconds());
-
- } else {
- std::string modelPath = objectInstance._model->getModelPath();
- if (modelPath.empty())
- return;
- auto aiMgr = globals->get_subsystem<FGAIManager>();
- if (!aiMgr)
- return;
-
- _aiMultiplayer = new FGAIMultiplayer;
- _aiMultiplayer->setPath(modelPath.c_str());
- aiMgr->attach(_aiMultiplayer.get());
-
- objectInstance._propertyReferenceSet->setRootNode(_aiMultiplayer->getPropertyRoot());
- }
- }
-
- void setDie()
- {
- if (!_aiMultiplayer.valid())
- return;
- _aiMultiplayer->setDie(true);
- _aiMultiplayer = 0;
- }
-
- SGSharedPtr<FGAIMultiplayer> _aiMultiplayer;
-};
-
-class SimTimeFactory : public SGReferenced {
-public:
- virtual ~SimTimeFactory() {}
- virtual AbstractSimTime* createSimTime(sg::HLAObjectInstance&) const = 0;
-};
-
-// A SimTime implementation that works with the simulation
-// time in an attribute. Used when we cannot do real time management.
-class AttributeSimTimeFactory : public SimTimeFactory {
-public:
- class SimTime : public AbstractSimTime {
- public:
- virtual double getTimeStamp() const
- { return _simTime; }
- virtual void setTimeStamp(double simTime)
- { _simTime = simTime; }
-
- sg::HLADataElement* getDataElement()
- { return _simTime.getDataElement(); }
-
- private:
- sg::HLADoubleData _simTime;
- };
-
- virtual AbstractSimTime* createSimTime(sg::HLAObjectInstance& objectInstance) const
- {
- SimTime* simTime = new SimTime;
- objectInstance.setAttributeDataElement(_simTimeIndex, simTime->getDataElement());
- return simTime;
- }
- void setSimTimeIndex(const sg::HLADataElementIndex& simTimeIndex)
- { _simTimeIndex = simTimeIndex; }
-
-private:
- sg::HLADataElementIndex _simTimeIndex;
-};
-
-// A SimTime implementation that works with the simulation
-// time in two attributes like the avation sim net fom works
-class MSecAttributeSimTimeFactory : public SimTimeFactory {
-public:
- class SimTime : public AbstractSimTime {
- public:
- virtual double getTimeStamp() const
- {
- return _secSimTime + 1e-3*_msecSimTime;
- }
- virtual void setTimeStamp(double simTime)
- {
- double sec = floor(simTime);
- _secSimTime = sec;
- _msecSimTime = 1e3*(simTime - sec);
- }
-
- sg::HLADataElement* getSecDataElement()
- { return _secSimTime.getDataElement(); }
- sg::HLADataElement* getMSecDataElement()
- { return _msecSimTime.getDataElement(); }
-
- private:
- sg::HLADoubleData _secSimTime;
- sg::HLADoubleData _msecSimTime;
- };
-
- virtual AbstractSimTime* createSimTime(sg::HLAObjectInstance& objectInstance) const
- {
- SimTime* simTime = new SimTime;
- objectInstance.setAttributeDataElement(_secIndex, simTime->getSecDataElement());
- objectInstance.setAttributeDataElement(_msecIndex, simTime->getMSecDataElement());
- return simTime;
- }
- void setSecIndex(const sg::HLADataElementIndex& secIndex)
- { _secIndex = secIndex; }
- void setMSecIndex(const sg::HLADataElementIndex& msecIndex)
- { _msecIndex = msecIndex; }
-
-private:
- sg::HLADataElementIndex _secIndex;
- sg::HLADataElementIndex _msecIndex;
-};
-
-class ModelFactory : public SGReferenced {
-public:
- virtual ~ModelFactory() {}
- virtual AbstractModel* createModel(sg::HLAObjectInstance& objectInstance) const = 0;
-};
-
-class AttributeModelFactory : public ModelFactory {
-public:
- class Model : public AbstractModel {
- public:
- virtual std::string getModelPath() const
- { return _modelPath; }
- virtual void setModelPath(const std::string& modelPath)
- { _modelPath = modelPath; }
-
- sg::HLADataElement* getDataElement()
- { return _modelPath.getDataElement(); }
-
- private:
- sg::HLAStringData _modelPath;
- };
-
- virtual AbstractModel* createModel(sg::HLAObjectInstance& objectInstance) const
- {
- Model* model = new Model;
- objectInstance.setAttributeDataElement(_modelIndex, model->getDataElement());
- return model;
- }
- void setModelIndex(const sg::HLADataElementIndex& modelIndex)
- { _modelIndex = modelIndex; }
-
-private:
- sg::HLADataElementIndex _modelIndex;
-};
-
-class AttributeMapModelFactory : public ModelFactory {
-public:
- class Model : public AbstractModel {
- public:
- Model(const AttributeMapModelFactory* mapModelFactory) :
- _mapModelFactory(mapModelFactory)
- { }
-
- virtual std::string getModelPath() const
- {
- if (_modelPath.getValue().empty())
- return _modelPath.getValue();
- return _mapModelFactory->mapToFlightgear(_modelPath);
- }
- virtual void setModelPath(const std::string& modelPath)
- { _modelPath = _mapModelFactory->mapToExternal(modelPath); }
-
- sg::HLADataElement* getDataElement()
- { return _modelPath.getDataElement(); }
-
- private:
- sg::HLAStringData _modelPath;
- SGSharedPtr<const AttributeMapModelFactory> _mapModelFactory;
- };
-
- virtual AbstractModel* createModel(sg::HLAObjectInstance& objectInstance) const
- {
- Model* model = new Model(this);
- objectInstance.setAttributeDataElement(_modelIndex, model->getDataElement());
- return model;
- }
- void setModelIndex(const sg::HLADataElementIndex& modelIndex)
- { _modelIndex = modelIndex; }
-
- std::string mapToFlightgear(const std::string& externalModel) const
- {
- std::map<std::string,std::string>::const_iterator i;
- i = _externalToModelPathMap.find(externalModel);
- if (i != _externalToModelPathMap.end())
- return i->second;
- return "default";
- }
- std::string mapToExternal(const std::string& modelPath) const
- {
- std::map<std::string,std::string>::const_iterator i;
- i = _modelPathToExternalMap.find(modelPath);
- if (i != _modelPathToExternalMap.end())
- return i->second;
- return _externalDefault;
- }
-
- void setExternalDefault(const std::string& externalDefault)
- { _externalDefault = externalDefault; }
- void addExternalModelPathPair(const std::string& external, const std::string& modelPath)
- {
- _externalToModelPathMap[external] = modelPath;
- _modelPathToExternalMap[modelPath] = external;
- }
-
-private:
- sg::HLADataElementIndex _modelIndex;
-
- std::map<std::string,std::string> _externalToModelPathMap;
- std::map<std::string,std::string> _modelPathToExternalMap;
- std::string _externalDefault;
-};
-
-class FGHLA::MultiplayerObjectClass : public sg::HLAObjectClass {
-public:
- MultiplayerObjectClass(const std::string& name, sg::HLAFederate* federate) :
- HLAObjectClass(name, federate)
- { }
- virtual ~MultiplayerObjectClass()
- { }
-
- virtual MultiplayerObjectInstance* createObjectInstance(const std::string& name)
- { return new MultiplayerObjectInstance(this); }
-
- virtual void discoverInstance(sg::HLAObjectInstance& objectInstance, const sg::RTIData& tag)
- {
- HLAObjectClass::discoverInstance(objectInstance, tag);
- MPReflectCallback* reflectCallback = new MPReflectCallback;
- objectInstance.setReflectCallback(reflectCallback);
- attachDataElements(static_cast<MultiplayerObjectInstance&>(objectInstance), false);
- }
- virtual void removeInstance(sg::HLAObjectInstance& objectInstance, const sg::RTIData& tag)
- {
- HLAObjectClass::removeInstance(objectInstance, tag);
- MPReflectCallback* reflectCallback;
- reflectCallback = dynamic_cast<MPReflectCallback*>(objectInstance.getReflectCallback().get());
- if (!reflectCallback) {
- SG_LOG(SG_IO, SG_WARN, "HLA: expected to have a different attribute callback in remove instance.");
- return;
- }
- reflectCallback->setDie();
- }
- virtual void registerInstance(sg::HLAObjectInstance& objectInstance)
- {
- HLAObjectClass::registerInstance(objectInstance);
- MPUpdateCallback* updateCallback = new MPUpdateCallback;
- objectInstance.setUpdateCallback(updateCallback);
- MultiplayerObjectInstance& mpObjectInstance = static_cast<MultiplayerObjectInstance&>(objectInstance);
- attachDataElements(mpObjectInstance, true);
- mpObjectInstance._model->setModelPath(fgGetString("/sim/model/path", "default"));
- mpObjectInstance._propertyReferenceSet->setRootNode(fgGetNode("/", true));
- }
- virtual void deleteInstance(sg::HLAObjectInstance& objectInstance)
- {
- HLAObjectClass::deleteInstance(objectInstance);
- }
-
- virtual void createAttributeDataElements(sg::HLAObjectInstance& objectInstance)
- {
- sg::HLAObjectClass::createAttributeDataElements(objectInstance);
- }
-
- void setLocationFactory(sg::HLALocationFactory* locationFactory)
- { _locationFactory = locationFactory; }
- sg::HLALocationFactory* getLocationFactory()
- { return _locationFactory.get(); }
-
- void setSimTimeFactory(SimTimeFactory* simTimeFactory)
- { _simTimeFactory = simTimeFactory; }
- SimTimeFactory* getSimTimeFactory()
- { return _simTimeFactory.get(); }
-
- void setModelFactory(ModelFactory* modelFactory)
- { _modelFactory = modelFactory; }
- ModelFactory* getModelFactory()
- { return _modelFactory.get(); }
-
- void setMPPropertiesIndex(const sg::HLADataElementIndex& index)
- { _mpPropertiesIndex = index; }
- const sg::HLADataElementIndex& getMPPropertiesIndex() const
- { return _mpPropertiesIndex; }
-
- void setInputProperty(const sg::HLADataElementIndex& index, const std::string& property)
- {
- _inputProperties[index] = property;
- }
- void setOutputProperty(const sg::HLADataElementIndex& index, const std::string& property)
- {
- _outputProperties[index] = property;
- }
-
-private:
- void attachDataElements(MultiplayerObjectInstance& objectInstance, bool outgoing)
- {
- objectInstance.setAttributeDataElement(_mpPropertiesIndex, objectInstance._mpProperties.get());
-
- if (_locationFactory.valid())
- objectInstance._location = _locationFactory->createLocation(objectInstance);
- if (_modelFactory.valid())
- objectInstance._model = _modelFactory->createModel(objectInstance);
- if (_simTimeFactory.valid())
- objectInstance._simTime = _simTimeFactory->createSimTime(objectInstance);
-
- if (outgoing)
- attachPropertyDataElements(*objectInstance._propertyReferenceSet,
- objectInstance, _outputProperties);
- else
- attachPropertyDataElements(*objectInstance._propertyReferenceSet,
- objectInstance, _inputProperties);
- }
- typedef std::map<sg::HLADataElementIndex, std::string> IndexPropertyMap;
-
- void attachPropertyDataElements(PropertyReferenceSet& propertyReferenceSet,
- sg::HLAObjectInstance& objectInstance,
- const IndexPropertyMap& attributePathPropertyMap)
- {
- for (IndexPropertyMap::const_iterator i = attributePathPropertyMap.begin();
- i != attributePathPropertyMap.end(); ++i) {
- sg::HLAPropertyDataElement* dataElement = new sg::HLAPropertyDataElement;
- propertyReferenceSet.insert(i->second, dataElement);
- objectInstance.setAttributeDataElement(i->first, dataElement);
- }
- }
-
- IndexPropertyMap _inputProperties;
- IndexPropertyMap _outputProperties;
-
- SGSharedPtr<sg::HLALocationFactory> _locationFactory;
- SGSharedPtr<SimTimeFactory> _simTimeFactory;
- SGSharedPtr<ModelFactory> _modelFactory;
-
- sg::HLADataElementIndex _mpPropertiesIndex;
-};
-
-class FGHLA::Federate : public sg::HLAFederate {
-public:
- virtual ~Federate()
- { }
- virtual bool readObjectModel()
- { return readRTI1516ObjectModelTemplate(getFederationObjectModel()); }
-
- virtual sg::HLAObjectClass* createObjectClass(const std::string& name)
- {
- if (std::find(_multiplayerObjectClassNames.begin(), _multiplayerObjectClassNames.end(), name)
- != _multiplayerObjectClassNames.end()) {
- if (_localAircraftClass.valid()) {
- return new MultiplayerObjectClass(name, this);
- } else {
- _localAircraftClass = new MultiplayerObjectClass(name, this);
- return _localAircraftClass.get();
- }
- } else {
- return 0;
- }
- }
-
- void updateLocalAircraftInstance()
- {
- // First push our own data so that others can recieve ...
- if (!_localAircraftClass.valid())
- return;
- if (!_localAircraftInstance.valid()) {
- _localAircraftInstance = new MultiplayerObjectInstance(_localAircraftClass.get());
- _localAircraftInstance->registerInstance();
- }
- _localAircraftInstance->updateAttributeValues(sg::RTIData("MPAircraft"));
- }
-
- virtual bool shutdown()
- {
- if (_localAircraftInstance.valid()) {
- // Remove the local object from the rti
- _localAircraftInstance->deleteInstance(simgear::RTIData("gone"));
- _localAircraftInstance = 0;
- }
- return HLAFederate::shutdown();
- }
-
- std::list<std::string> _multiplayerObjectClassNames;
- /// This class is used to register the local instance and to subscribe for others
- SGSharedPtr<MultiplayerObjectClass> _localAircraftClass;
- /// The local aircraft instance
- SGSharedPtr<MultiplayerObjectInstance> _localAircraftInstance;
-};
-
-FGHLA::FGHLA(const std::vector<std::string>& tokens) :
- _hlaFederate(new Federate)
-{
- if (1 < tokens.size() && !tokens[1].empty())
- set_direction(tokens[1]);
- else
- set_direction("bi");
-
- int rate = 60;
- if (2 < tokens.size() && !tokens[2].empty()) {
- std::stringstream ss(tokens[2]);
- ss >> rate;
- }
- set_hz(rate);
-
- if (3 < tokens.size() && !tokens[3].empty())
- _federate = tokens[3];
- else
- _federate = fgGetString("/sim/user/callsign");
-
- if (4 < tokens.size() && !tokens[4].empty())
- _federation = tokens[4];
- else
- _federation = "FlightGear";
-
- if (5 < tokens.size() && !tokens[5].empty())
- _objectModelConfig = tokens[5];
- else
- _objectModelConfig = "mp-aircraft.xml";
-}
-
-FGHLA::~FGHLA()
-{
-}
-
-bool
-FGHLA::open()
-{
- if (is_enabled()) {
- SG_LOG(SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
- "is already in use, ignoring");
- return false;
- }
-
- if (_federation.empty()) {
- SG_LOG(SG_IO, SG_ALERT, "No federation to join given to "
- "the HLA module");
- return false;
- }
-
- if (_federate.empty()) {
- SG_LOG(SG_IO, SG_ALERT, "No federate name given to the HLA module");
- return false;
- }
-
- if (!SGPath(_objectModelConfig).exists()) {
- SGPath path(globals->get_fg_root());
- path.append("HLA");
- path.append(_objectModelConfig);
- if (path.exists())
- _objectModelConfig = path.str();
- else {
- SG_LOG(SG_IO, SG_ALERT, "Federate object model configuration \""
- << _objectModelConfig << "\" does not exist.");
- return false;
- }
- }
-
- XMLConfigReader configReader;
- try {
- readXML(_objectModelConfig, configReader);
- } catch (const sg_throwable& e) {
- SG_LOG(SG_IO, SG_ALERT, "Could not open HLA configuration file: "
- << e.getMessage());
- return false;
- } catch (...) {
- SG_LOG(SG_IO, SG_ALERT, "Could not open HLA configuration file");
- return false;
- }
-
- // Flightgears hla configuration
- std::string objectModel = configReader.getFederateObjectModel();
- if (objectModel.empty()) {
- SG_LOG(SG_IO, SG_ALERT, "No federate object model given to "
- "the HLA module");
- return false;
- }
- if (!SGPath(objectModel).exists()) {
- SGPath path(SGPath(_objectModelConfig).dir());
- path.append(objectModel);
- if (path.exists())
- objectModel = path.str();
- else {
- SG_LOG(SG_IO, SG_ALERT, "Federate object model file \""
- << objectModel << "\" does not exist.");
- return false;
- }
- }
-
- // We need that to communicate to the rti
- switch (configReader.getRTIVersion()) {
- case RTI13:
- _hlaFederate->setVersion(simgear::HLAFederate::RTI13);
- break;
- case RTI1516:
- _hlaFederate->setVersion(simgear::HLAFederate::RTI1516);
- break;
- case RTI1516E:
- _hlaFederate->setVersion(simgear::HLAFederate::RTI1516E);
- break;
- }
- _hlaFederate->setConnectArguments(configReader.getRTIArguments());
- _hlaFederate->setFederationExecutionName(_federation);
- _hlaFederate->setFederationObjectModel(objectModel);
- _hlaFederate->setFederateType(_federate);
-
- // Store the multiplayer class name in the federate
- XMLConfigReader::ObjectClassConfigList::const_iterator i;
- for (i = configReader.getObjectClassConfigList().begin();
- i != configReader.getObjectClassConfigList().end(); ++i) {
-
- if (i->_type != "Multiplayer") {
- SG_LOG(SG_IO, SG_ALERT, "Ignoring unknown object class type \"" << i->_type << "\"!");
- continue;
- }
-
- // Register the object class that we need for this simple hla implementation
- _hlaFederate->_multiplayerObjectClassNames.push_back(i->_name);
- }
-
-
- // Now that it is paramtrized, connect/join
- if (!_hlaFederate->init()) {
- SG_LOG(SG_IO, SG_ALERT, "Could not init the hla/rti connect.");
- return false;
- }
-
- // bool publish = get_direction() & SG_IO_OUT;
- // bool subscribe = get_direction() & SG_IO_IN;
-
- // Interpret the configuration file
- for (i = configReader.getObjectClassConfigList().begin();
- i != configReader.getObjectClassConfigList().end(); ++i) {
-
- /// already warned about this above
- if (i->_type != "Multiplayer")
- continue;
-
- /// The object class for HLA aircraft
- SGSharedPtr<MultiplayerObjectClass> objectClass;
-
- // Register the object class that we need for this simple hla implementation
- std::string aircraftClassName = i->_name;
- objectClass = dynamic_cast<MultiplayerObjectClass*>(_hlaFederate->getObjectClass(aircraftClassName));
- if (!objectClass.valid()) {
- SG_LOG(SG_IO, SG_ALERT, "Could not find " << aircraftClassName << " object class!");
- continue;
- }
-
- SGSharedPtr<MultiplayerObjectClass> mpClassCallback = objectClass;
-
- if (i->_positionConfig._type == "cartesian") {
- SGSharedPtr<sg::HLACartesianLocationFactory> locationFactory;
- locationFactory = new sg::HLACartesianLocationFactory;
- XMLConfigReader::DataElementList::const_iterator j;
- for (j = i->_positionConfig._dataElementList.begin();
- j != i->_positionConfig._dataElementList.end(); ++j) {
-
- if (j->_type == "position-x")
- locationFactory->setPositionIndex(0, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "position-y")
- locationFactory->setPositionIndex(1, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "position-z")
- locationFactory->setPositionIndex(2, objectClass->getDataElementIndex(j->_name));
-
- else if (j->_type == "orientation-sin-angle-axis-x")
- locationFactory->setOrientationIndex(0, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "orientation-sin-angle-axis-y")
- locationFactory->setOrientationIndex(1, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "orientation-sin-angle-axis-z")
- locationFactory->setOrientationIndex(2, objectClass->getDataElementIndex(j->_name));
-
- else if (j->_type == "angular-velocity-x")
- locationFactory->setAngularVelocityIndex(0, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "angular-velocity-y")
- locationFactory->setAngularVelocityIndex(1, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "angular-velocity-z")
- locationFactory->setAngularVelocityIndex(2, objectClass->getDataElementIndex(j->_name));
-
- else if (j->_type == "linear-velocity-x")
- locationFactory->setLinearVelocityIndex(0, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "linear-velocity-y")
- locationFactory->setLinearVelocityIndex(1, objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "linear-velocity-z")
- locationFactory->setLinearVelocityIndex(2, objectClass->getDataElementIndex(j->_name));
-
- else {
- SG_LOG(SG_IO, SG_ALERT, "HLA: Unknown position configuration type \""
- << j->_type << "\"for object class \"" << aircraftClassName << "\". Ignoring!");
- }
- }
-
- mpClassCallback->setLocationFactory(locationFactory.get());
- } else if (i->_positionConfig._type == "geodetic") {
- SGSharedPtr<sg::HLAGeodeticLocationFactory> locationFactory;
- locationFactory = new sg::HLAGeodeticLocationFactory;
-
- XMLConfigReader::DataElementList::const_iterator j;
- for (j = i->_positionConfig._dataElementList.begin();
- j != i->_positionConfig._dataElementList.end(); ++j) {
-
- if (j->_type == "latitude-deg")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::LatitudeDeg,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "latitude-rad")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::LatitudeRad,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "longitude-deg")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::LongitudeDeg,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "longitude-rad")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::LongitudeRad,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "elevation-m")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::ElevationM,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "elevation-m")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::ElevationFt,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "heading-deg")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::HeadingDeg,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "heading-rad")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::HeadingRad,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "pitch-deg")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::PitchDeg,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "pitch-rad")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::PitchRad,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "roll-deg")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::RollDeg,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "roll-rad")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::RollRad,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "ground-track-deg")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::GroundTrackDeg,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "ground-track-rad")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::GroundTrackRad,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "ground-speed-kt")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::GroundSpeedKnots,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "ground-speed-ft-per-sec")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::GroundSpeedFtPerSec,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "ground-speed-m-per-sec")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::GroundSpeedMPerSec,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "vertical-speed-ft-per-sec")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::VerticalSpeedFtPerSec,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "vertical-speed-ft-per-min")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::VerticalSpeedFtPerMin,
- objectClass->getDataElementIndex(j->_name));
- else if (j->_type == "vertical-speed-m-per-sec")
- locationFactory->setIndex(sg::HLAGeodeticLocationFactory::VerticalSpeedMPerSec,
- objectClass->getDataElementIndex(j->_name));
- else {
- SG_LOG(SG_IO, SG_ALERT, "HLA: Unknown position configuration type \""
- << j->_type << "\" for object class \"" << aircraftClassName << "\". Ignoring!");
- }
- }
-
- mpClassCallback->setLocationFactory(locationFactory.get());
- }
-
- if (i->_modelConfig._type == "native") {
- SGSharedPtr<AttributeModelFactory> attributeModelFactory;
- attributeModelFactory = new AttributeModelFactory;
-
- XMLConfigReader::DataElementList::const_iterator j;
- for (j = i->_modelConfig._dataElementList.begin();
- j ...
[truncated message content] |
|
From: <fli...@li...> - 2026-04-20 08:17:39
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new bb4b56c7 Remove HLA support
bb4b56c7 is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/bb4b56c78e5928511e41c9613ea9680a90d9021c/
Commit: bb4b56c78e5928511e41c9613ea9680a90d9021c
Author: James Turner
Committer: James Turner
AuthorDate: Sun Apr 19 20:42:32 2026 +0100
Remove HLA support
---
CMakeLists.txt | 15 -
SimGearConfig.cmake.in | 9 -
simgear/CMakeLists.txt | 9 -
simgear/hla/CMakeLists.txt | 95 --
simgear/hla/HLAArrayDataElement.cxx | 437 -------
simgear/hla/HLAArrayDataElement.hxx | 693 -----------
simgear/hla/HLAArrayDataType.cxx | 200 ----
simgear/hla/HLAArrayDataType.hxx | 106 --
simgear/hla/HLABasicDataElement.cxx | 153 ---
simgear/hla/HLABasicDataElement.hxx | 116 --
simgear/hla/HLABasicDataType.cxx | 176 ---
simgear/hla/HLABasicDataType.hxx | 155 ---
simgear/hla/HLADataElement.cxx | 121 --
simgear/hla/HLADataElement.hxx | 126 --
simgear/hla/HLADataElementVisitor.hxx | 57 -
simgear/hla/HLADataType.cxx | 275 -----
simgear/hla/HLADataType.hxx | 85 --
simgear/hla/HLADataTypeVisitor.cxx | 194 ---
simgear/hla/HLADataTypeVisitor.hxx | 661 ----------
simgear/hla/HLAEnumeratedDataElement.cxx | 148 ---
simgear/hla/HLAEnumeratedDataElement.hxx | 67 --
simgear/hla/HLAEnumeratedDataType.cxx | 195 ---
simgear/hla/HLAEnumeratedDataType.hxx | 98 --
simgear/hla/HLAFederate.cxx | 1220 -------------------
simgear/hla/HLAFederate.hxx | 295 -----
simgear/hla/HLAFixedRecordDataElement.cxx | 281 -----
simgear/hla/HLAFixedRecordDataElement.hxx | 89 --
simgear/hla/HLAFixedRecordDataType.cxx | 100 --
simgear/hla/HLAFixedRecordDataType.hxx | 98 --
simgear/hla/HLAInteractionClass.cxx | 270 -----
simgear/hla/HLAInteractionClass.hxx | 112 --
simgear/hla/HLALocation.cxx | 578 ---------
simgear/hla/HLALocation.hxx | 174 ---
simgear/hla/HLAOMTXmlVisitor.cxx | 872 --------------
simgear/hla/HLAOMTXmlVisitor.hxx | 334 ------
simgear/hla/HLAObjectClass.cxx | 504 --------
simgear/hla/HLAObjectClass.hxx | 186 ---
simgear/hla/HLAObjectInstance.cxx | 543 ---------
simgear/hla/HLAObjectInstance.hxx | 216 ----
simgear/hla/HLAPropertyDataElement.cxx | 568 ---------
simgear/hla/HLAPropertyDataElement.hxx | 66 -
simgear/hla/HLARawDataElement.cxx | 66 -
simgear/hla/HLARawDataElement.hxx | 52 -
simgear/hla/HLATypes.hxx | 50 -
simgear/hla/HLAVariantRecordDataElement.cxx | 243 ----
simgear/hla/HLAVariantRecordDataElement.hxx | 92 --
simgear/hla/HLAVariantRecordDataType.cxx | 127 --
simgear/hla/HLAVariantRecordDataType.hxx | 107 --
simgear/hla/RTI13Ambassador.hxx | 446 -------
simgear/hla/RTI13Federate.cxx | 1731 ---------------------------
simgear/hla/RTI13Federate.hxx | 109 --
simgear/hla/RTI13FederateFactory.cxx | 55 -
simgear/hla/RTI13FederateFactory.hxx | 39 -
simgear/hla/RTI13InteractionClass.cxx | 245 ----
simgear/hla/RTI13InteractionClass.hxx | 64 -
simgear/hla/RTI13ObjectClass.cxx | 319 -----
simgear/hla/RTI13ObjectClass.hxx | 85 --
simgear/hla/RTI13ObjectInstance.cxx | 530 --------
simgear/hla/RTI13ObjectInstance.hxx | 109 --
simgear/hla/RTIData.hxx | 574 ---------
simgear/hla/RTIFederate.cxx | 36 -
simgear/hla/RTIFederate.hxx | 100 --
simgear/hla/RTIFederateFactory.cxx | 43 -
simgear/hla/RTIFederateFactory.hxx | 40 -
simgear/hla/RTIFederateFactoryRegistry.cxx | 68 --
simgear/hla/RTIFederateFactoryRegistry.hxx | 54 -
simgear/hla/RTIInteractionClass.cxx | 38 -
simgear/hla/RTIInteractionClass.hxx | 52 -
simgear/hla/RTIObjectClass.cxx | 70 --
simgear/hla/RTIObjectClass.hxx | 64 -
simgear/hla/RTIObjectInstance.cxx | 70 --
simgear/hla/RTIObjectInstance.hxx | 153 ---
72 files changed, 16528 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8dd63038..90bdabf7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -99,7 +99,6 @@ endif()
option(SIMGEAR_HEADLESS "Set to ON to build SimGear without GUI/graphics support" OFF)
option(ENABLE_CYCLONE "Set to ON to build SimGear with Cyclone Data Distribution Service support" ON)
-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)
@@ -262,20 +261,6 @@ else()
message(STATUS "Using built-in expat code")
endif(SYSTEM_EXPAT)
-if(ENABLE_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 IMPORTED_TARGET 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_CYCLONE)
find_package(CycloneDDS QUIET)
diff --git a/SimGearConfig.cmake.in b/SimGearConfig.cmake.in
index bb79b368..909771c7 100644
--- a/SimGearConfig.cmake.in
+++ b/SimGearConfig.cmake.in
@@ -65,15 +65,6 @@ if (SIMGEAR_USE_FFMPEG)
include(${CMAKE_CURRENT_LIST_DIR}/CreateFFmpegImportedTargets.cmake)
endif()
-# OpenRTI support
-set(ENABLE_RTI @ENABLE_RTI@)
-if(ENABLE_RTI)
- find_dependency(PkgConfig)
- if(PKG_CONFIG_FOUND)
- pkg_check_modules(RTI IMPORTED_TARGET hla-rti13)
- endif(PKG_CONFIG_FOUND)
-endif(ENABLE_RTI)
-
# Alternative terrain engine based on pagedLOD
set(ENABLE_GDAL @ENABLE_GDAL@)
diff --git a/simgear/CMakeLists.txt b/simgear/CMakeLists.txt
index 0f00bfe8..c24938f3 100644
--- a/simgear/CMakeLists.txt
+++ b/simgear/CMakeLists.txt
@@ -57,10 +57,6 @@ foreach( mylibfolder
add_subdirectory(${mylibfolder})
endforeach( mylibfolder )
-if(ENABLE_RTI)
- add_subdirectory(hla)
-endif(ENABLE_RTI)
-
set(HEADERS compiler.h constants.h sg_inlines.h ${PROJECT_BINARY_DIR}/simgear/version.h)
install (FILES ${HEADERS} DESTINATION include/simgear/)
@@ -100,11 +96,6 @@ if (SG_HAVE_DDS)
target_link_libraries(SimGearCore PRIVATE CycloneDDS::ddsc)
endif()
-if (ENABLE_RTI)
- target_sources(SimGearCore PRIVATE $<TARGET_OBJECTS:rti> $<TARGET_OBJECTS:rti13>)
- target_link_libraries(SimGearCore PRIVATE PkgConfig::RTI)
-endif()
-
if (APPLE)
# PCH doesn't work for Objective-C++
diff --git a/simgear/hla/CMakeLists.txt b/simgear/hla/CMakeLists.txt
deleted file mode 100644
index eb29e1e1..00000000
--- a/simgear/hla/CMakeLists.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-include (SimGearComponent)
-
-set(HLA_HEADERS
- RTIData.hxx
- HLAArrayDataElement.hxx
- HLAArrayDataType.hxx
- HLABasicDataElement.hxx
- HLABasicDataType.hxx
- HLADataElement.hxx
- HLADataElementVisitor.hxx
- HLADataType.hxx
- HLADataTypeVisitor.hxx
- HLAEnumeratedDataElement.hxx
- HLAEnumeratedDataType.hxx
- HLAFixedRecordDataElement.hxx
- HLAFixedRecordDataType.hxx
- HLAFederate.hxx
- HLAInteractionClass.hxx
- HLALocation.hxx
- HLAObjectClass.hxx
- HLAObjectInstance.hxx
- HLAOMTXmlVisitor.hxx
- HLAPropertyDataElement.hxx
- HLARawDataElement.hxx
- HLATypes.hxx
- HLAVariantRecordDataElement.hxx
- HLAVariantRecordDataType.hxx
- )
-
-set(HLA_SOURCES
- HLAArrayDataElement.cxx
- HLAArrayDataType.cxx
- HLABasicDataElement.cxx
- HLABasicDataType.cxx
- HLADataElement.cxx
- HLADataType.cxx
- HLADataTypeVisitor.cxx
- HLAEnumeratedDataElement.cxx
- HLAEnumeratedDataType.cxx
- HLAFederate.cxx
- HLAInteractionClass.cxx
- HLAFixedRecordDataElement.cxx
- HLAFixedRecordDataType.cxx
- HLALocation.cxx
- HLAObjectClass.cxx
- HLAObjectInstance.cxx
- HLAOMTXmlVisitor.cxx
- HLAPropertyDataElement.cxx
- HLARawDataElement.cxx
- HLAVariantRecordDataElement.cxx
- HLAVariantRecordDataType.cxx
- )
-
-simgear_component(hla hla "${HLA_SOURCES}" "${HLA_HEADERS}")
-
-if(RTI_FOUND)
- set(RTI13_SOURCES
- RTI13InteractionClass.cxx
- RTI13ObjectClass.cxx
- RTI13ObjectInstance.cxx
- RTI13Federate.cxx
- RTI13FederateFactory.cxx
- )
-
- add_library(rti13 OBJECT ${RTI13_SOURCES})
-
- target_include_directories(rti13 PUBLIC ${PROJECT_SOURCE_DIR})
- target_include_directories(rti13 PUBLIC ${PROJECT_BINARY_DIR})
- target_link_libraries(rti13 PRIVATE PkgConfig::RTI)
- # for simgear_config.h
- target_include_directories(rti13 PRIVATE ${PROJECT_BINARY_DIR}/simgear)
-
- set_property(TARGET rti13 PROPERTY CXX_STANDARD 11)
- #simgear_component(rti13 hla "${RTI13_SOURCES}" "")
-endif()
-
-set(RTI_SOURCES
- RTIInteractionClass.cxx
- RTIObjectClass.cxx
- RTIObjectInstance.cxx
- RTIFederate.cxx
- RTIFederateFactory.cxx
- RTIFederateFactoryRegistry.cxx
- )
-
- add_library(rti OBJECT ${RTI_SOURCES})
- target_include_directories(rti PUBLIC ${PROJECT_SOURCE_DIR})
- target_include_directories(rti PUBLIC ${PROJECT_BINARY_DIR})
- target_include_directories(rti PRIVATE ${PROJECT_BINARY_DIR}/simgear)
-
- target_link_libraries(rti PRIVATE PkgConfig::RTI)
-
- set_property(TARGET rti PROPERTY CXX_STANDARD 11)
-
-#simgear_component(rti hla "${RTI_SOURCES}" "")
diff --git a/simgear/hla/HLAArrayDataElement.cxx b/simgear/hla/HLAArrayDataElement.cxx
deleted file mode 100644
index 1d7f40d5..00000000
--- a/simgear/hla/HLAArrayDataElement.cxx
+++ /dev/null
@@ -1,437 +0,0 @@
-// Copyright (C) 2009 - 2012 Mathias Froehlich - Mat...@we...
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Library General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Library General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#include <simgear/compiler.h>
-
-#include "HLAArrayDataElement.hxx"
-
-#include <simgear/debug/logstream.hxx>
-
-#include "HLADataElementVisitor.hxx"
-
-namespace simgear {
-
-HLAAbstractArrayDataElement::HLAAbstractArrayDataElement(const HLAArrayDataType* dataType) :
- _dataType(dataType)
-{
-}
-
-HLAAbstractArrayDataElement::~HLAAbstractArrayDataElement()
-{
-}
-
-void
-HLAAbstractArrayDataElement::accept(HLADataElementVisitor& visitor)
-{
- visitor.apply(*this);
-}
-
-void
-HLAAbstractArrayDataElement::accept(HLAConstDataElementVisitor& visitor) const
-{
- visitor.apply(*this);
-}
-
-bool
-HLAAbstractArrayDataElement::decode(HLADecodeStream& stream)
-{
- if (!_dataType.valid())
- return false;
- return _dataType->decode(stream, *this);
-}
-
-bool
-HLAAbstractArrayDataElement::encode(HLAEncodeStream& stream) const
-{
- if (!_dataType.valid())
- return false;
- return _dataType->encode(stream, *this);
-}
-
-const HLAArrayDataType*
-HLAAbstractArrayDataElement::getDataType() const
-{
- return _dataType.get();
-}
-
-bool
-HLAAbstractArrayDataElement::setDataType(const HLADataType* dataType)
-{
- const HLAArrayDataType* arrayDataType = dynamic_cast<const HLAArrayDataType*>(dataType);
- if (!arrayDataType) {
- SG_LOG(SG_NETWORK, SG_WARN, "HLAArrayDataType: unable to set data type!");
- return false;
- }
- _dataType = arrayDataType;
- return true;
-}
-
-const HLADataType*
-HLAAbstractArrayDataElement::getElementDataType() const
-{
- if (!_dataType.valid())
- return 0;
- return _dataType->getElementDataType();
-}
-
-////////////////////////////////////////////////////////////////////////
-
-HLAArrayDataElement::DataElementFactory::~DataElementFactory()
-{
-}
-
-HLAArrayDataElement::HLAArrayDataElement(const HLAArrayDataType* dataType) :
- HLAAbstractArrayDataElement(dataType)
-{
-}
-
-HLAArrayDataElement::~HLAArrayDataElement()
-{
- clearStamp();
-}
-
-bool
-HLAArrayDataElement::setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement)
-{
- // Must have happened in the parent
- if (begin == end)
- return false;
- unsigned index = *begin;
- if (++begin != end) {
- if (getNumElements() <= index && !setNumElements(index + 1))
- return false;
- if (!getElement(index) && getElementDataType()) {
- HLADataElementFactoryVisitor visitor;
- getElementDataType()->accept(visitor);
- setElement(index, visitor.getDataElement());
- }
- if (!getElement(index))
- return false;
- return getElement(index)->setDataElement(begin, end, dataElement);
- } else {
- if (!dataElement->setDataType(getElementDataType()))
- return false;
- setElement(index, dataElement);
- return true;
- }
-}
-
-HLADataElement*
-HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end)
-{
- if (begin == end)
- return this;
- HLADataElement* dataElement = getElement(*begin);
- if (!dataElement)
- return 0;
- return dataElement->getDataElement(++begin, end);
-}
-
-const HLADataElement*
-HLAArrayDataElement::getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const
-{
- if (begin == end)
- return this;
- const HLADataElement* dataElement = getElement(*begin);
- if (!dataElement)
- return 0;
- return dataElement->getDataElement(++begin, end);
-}
-
-bool
-HLAArrayDataElement::setDataType(const HLADataType* dataType)
-{
- if (!HLAAbstractArrayDataElement::setDataType(dataType))
- return false;
- for (unsigned i = 0; i < getNumElements(); ++i) {
- HLADataElement* dataElement = getElement(i);
- if (!dataElement)
- continue;
- if (!dataElement->setDataType(getElementDataType()))
- return false;
- }
- return true;
-}
-
-bool
-HLAArrayDataElement::setNumElements(unsigned size)
-{
- unsigned oldSize = _elementVector.size();
- if (size == oldSize)
- return true;
- _elementVector.resize(size);
- for (unsigned i = oldSize; i < size; ++i)
- _elementVector[i] = newElement(i);
- setDirty(true);
- return true;
-}
-
-bool
-HLAArrayDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
-{
- HLADataElement* dataElement = getElement(i);
- if (!dataElement)
- return false;
- return dataElement->decode(stream);
-}
-
-unsigned
-HLAArrayDataElement::getNumElements() const
-{
- return _elementVector.size();
-}
-
-bool
-HLAArrayDataElement::encodeElement(HLAEncodeStream& stream, unsigned i) const
-{
- const HLADataElement* dataElement = getElement(i);
- if (!dataElement)
- return false;
- return dataElement->encode(stream);
-}
-
-const HLADataElement*
-HLAArrayDataElement::getElement(unsigned index) const
-{
- if (_elementVector.size() <= index)
- return 0;
- return _elementVector[index].get();
-}
-
-HLADataElement*
-HLAArrayDataElement::getElement(unsigned index)
-{
- if (_elementVector.size() <= index)
- return 0;
- return _elementVector[index].get();
-}
-
-HLADataElement*
-HLAArrayDataElement::getOrCreateElement(unsigned index)
-{
- if (_elementVector.size() <= index)
- if (!setNumElements(index + 1))
- return 0;
- return _elementVector[index].get();
-}
-
-void
-HLAArrayDataElement::setElement(unsigned index, HLADataElement* value)
-{
- unsigned oldSize = _elementVector.size();
- if (oldSize <= index) {
- _elementVector.resize(index + 1);
- for (unsigned j = oldSize; j < index; ++j)
- _elementVector[j] = newElement(j);
- }
- if (_elementVector[index].valid())
- _elementVector[index]->clearStamp();
- _elementVector[index] = value;
- if (value)
- value->attachStamp(*this);
- setDirty(true);
-}
-
-void
-HLAArrayDataElement::setDataElementFactory(HLAArrayDataElement::DataElementFactory* dataElementFactory)
-{
- _dataElementFactory = dataElementFactory;
-}
-
-HLAArrayDataElement::DataElementFactory*
-HLAArrayDataElement::getDataElementFactory()
-{
- return _dataElementFactory.get();
-}
-
-void
-HLAArrayDataElement::_setStamp(Stamp* stamp)
-{
- HLAAbstractArrayDataElement::_setStamp(stamp);
- for (ElementVector::iterator i = _elementVector.begin(); i != _elementVector.end(); ++i) {
- if (!i->valid())
- continue;
- (*i)->attachStamp(*this);
- }
-}
-
-HLADataElement*
-HLAArrayDataElement::newElement(unsigned index)
-{
- if (!_dataElementFactory.valid())
- return 0;
- HLADataElement* dataElement = _dataElementFactory->createElement(*this, index);
- if (!dataElement)
- return 0;
- dataElement->attachStamp(*this);
- return dataElement;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-HLAVariantArrayDataElement::HLAVariantArrayDataElement() :
- HLAAbstractArrayDataElement(0)
-{
-}
-
-HLAVariantArrayDataElement::~HLAVariantArrayDataElement()
-{
- clearStamp();
-}
-
-bool
-HLAVariantArrayDataElement::setDataType(const HLADataType* dataType)
-{
- const HLAArrayDataType* arrayDataType = dataType->toArrayDataType();
- if (!arrayDataType) {
- SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantArrayDataType: unable to set data type, dataType is not an array data type!");
- return false;
- }
- const HLAVariantRecordDataType* variantRecordDataType = arrayDataType->getElementDataType()->toVariantRecordDataType();
- if (!variantRecordDataType) {
- SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantArrayDataType: unable to set data type: arrayDataTypes element data type is no a variant data type!");
- return false;
- }
- _dataType = arrayDataType;
- return true;
-}
-
-bool
-HLAVariantArrayDataElement::setNumElements(unsigned size)
-{
- unsigned oldSize = _elementVector.size();
- if (size == oldSize)
- return true;
- _elementVector.resize(size);
- for (unsigned i = oldSize; i < size; ++i)
- _elementVector[i] = newElement();
- setDirty(true);
- return true;
-}
-
-bool
-HLAVariantArrayDataElement::decodeElement(HLADecodeStream& stream, unsigned i)
-{
- HLAVariantRecordDataElement* dataElement = getElement(i);
- if (!dataElement)
- return false;
- return dataElement->decode(stream);
-}
-
-unsigned
-HLAVariantArrayDataElement::getNumElements() const
-{
- return _elementVector.size();
-}
-
-bool
-HLAVariantArrayDataElement::encodeElement(HLAEncodeStream& stream, unsigned i) const
-{
- const HLADataElement* dataElement = getElement(i);
- if (!dataElement)
- return false;
- return dataElement->encode(stream);
-}
-
-const HLAVariantRecordDataElement*
-HLAVariantArrayDataElement::getElement(unsigned index) const
-{
- if (_elementVector.size() <= index)
- return 0;
- return _elementVector[index].get();
-}
-
-HLAVariantRecordDataElement*
-HLAVariantArrayDataElement::getElement(unsigned index)
-{
- if (_elementVector.size() <= index)
- return 0;
- return _elementVector[index].get();
-}
-
-HLAVariantRecordDataElement*
-HLAVariantArrayDataElement::getOrCreateElement(unsigned index)
-{
- if (_elementVector.size() <= index)
- if (!setNumElements(index + 1))
- return 0;
- return _elementVector[index].get();
-}
-
-void
-HLAVariantArrayDataElement::setElement(unsigned index, HLAVariantRecordDataElement* value)
-{
- unsigned oldSize = _elementVector.size();
- if (oldSize <= index) {
- _elementVector.resize(index + 1);
- for (unsigned j = oldSize; j < index; ++j)
- _elementVector[j] = newElement();
- }
- if (_elementVector[index].valid())
- _elementVector[index]->clearStamp();
- _elementVector[index] = value;
- if (value)
- value->attachStamp(*this);
- setDirty(true);
-}
-
-void
-HLAVariantArrayDataElement::setAlternativeDataElementFactory(HLAVariantArrayDataElement::AlternativeDataElementFactory* alternativeDataElementFactory)
-{
- _alternativeDataElementFactory = alternativeDataElementFactory;
-}
-
-HLAVariantArrayDataElement::AlternativeDataElementFactory*
-HLAVariantArrayDataElement::getAlternativeDataElementFactory()
-{
- return _alternativeDataElementFactory.get();
-}
-
-void
-HLAVariantArrayDataElement::_setStamp(Stamp* stamp)
-{
- HLAAbstractArrayDataElement::_setStamp(stamp);
- for (ElementVector::iterator i = _elementVector.begin(); i != _elementVector.end(); ++i) {
- if (!i->valid())
- continue;
- (*i)->attachStamp(*this);
- }
-}
-
-HLAVariantRecordDataElement*
-HLAVariantArrayDataElement::newElement()
-{
- const HLAArrayDataType* arrayDataType = getDataType();
- if (!arrayDataType)
- return 0;
- const HLADataType* elementDataType = arrayDataType->getElementDataType();
- if (!elementDataType)
- return 0;
- const HLAVariantRecordDataType* variantRecordDataType = elementDataType->toVariantRecordDataType();
- if (!variantRecordDataType)
- return 0;
- HLAVariantRecordDataElement* variantRecordDataElement = new HLAVariantRecordDataElement(variantRecordDataType);
- variantRecordDataElement->setDataElementFactory(_alternativeDataElementFactory.get());
- variantRecordDataElement->attachStamp(*this);
- return variantRecordDataElement;
-}
-
-}
diff --git a/simgear/hla/HLAArrayDataElement.hxx b/simgear/hla/HLAArrayDataElement.hxx
deleted file mode 100644
index c6a83aea..00000000
--- a/simgear/hla/HLAArrayDataElement.hxx
+++ /dev/null
@@ -1,693 +0,0 @@
-// Copyright (C) 2009 - 2012 Mathias Froehlich - Mat...@we...
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Library General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Library General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-
-#ifndef HLAArrayDataElement_hxx
-#define HLAArrayDataElement_hxx
-
-#include <string>
-#include <vector>
-#include <simgear/math/SGMath.hxx>
-#include "HLAArrayDataType.hxx"
-#include "HLADataElement.hxx"
-#include "HLAVariantRecordDataElement.hxx"
-#include "HLADataTypeVisitor.hxx"
-
-namespace simgear {
-
-class HLAAbstractArrayDataElement : public HLADataElement {
-public:
- HLAAbstractArrayDataElement(const HLAArrayDataType* dataType);
- virtual ~HLAAbstractArrayDataElement();
-
- virtual void accept(HLADataElementVisitor& visitor);
- virtual void accept(HLAConstDataElementVisitor& visitor) const;
-
- virtual bool decode(HLADecodeStream& stream);
- virtual bool encode(HLAEncodeStream& stream) const;
-
- virtual const HLAArrayDataType* getDataType() const;
- virtual bool setDataType(const HLADataType* dataType);
-
- const HLADataType* getElementDataType() const;
-
- virtual bool setNumElements(unsigned count) = 0;
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i) = 0;
-
- virtual unsigned getNumElements() const = 0;
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const = 0;
-
-protected:
- SGSharedPtr<const HLAArrayDataType> _dataType;
-};
-
-class HLAArrayDataElement : public HLAAbstractArrayDataElement {
-public:
- HLAArrayDataElement(const HLAArrayDataType* dataType = 0);
- virtual ~HLAArrayDataElement();
-
- virtual bool setDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end, HLADataElement* dataElement);
- virtual HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end);
- virtual const HLADataElement* getDataElement(HLADataElementIndex::const_iterator begin, HLADataElementIndex::const_iterator end) const;
-
- virtual bool setDataType(const HLADataType* dataType);
-
- virtual bool setNumElements(unsigned size);
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
- virtual unsigned getNumElements() const;
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const;
-
- const HLADataElement* getElement(unsigned index) const;
- HLADataElement* getElement(unsigned index);
- HLADataElement* getOrCreateElement(unsigned index);
- void setElement(unsigned i, HLADataElement* value);
-
- class DataElementFactory : public SGReferenced {
- public:
- virtual ~DataElementFactory();
- virtual HLADataElement* createElement(const HLAArrayDataElement&, unsigned) = 0;
- };
-
- void setDataElementFactory(DataElementFactory* dataElementFactory);
- DataElementFactory* getDataElementFactory();
-
-protected:
- virtual void _setStamp(Stamp* stamp);
-
-private:
- HLADataElement* newElement(unsigned index);
-
- typedef std::vector<SGSharedPtr<HLADataElement> > ElementVector;
- ElementVector _elementVector;
-
- SGSharedPtr<DataElementFactory> _dataElementFactory;
-};
-
-// Holds an array of variants.
-// Factors out common code for that use case.
-class HLAVariantArrayDataElement : public HLAAbstractArrayDataElement {
-public:
- HLAVariantArrayDataElement();
- virtual ~HLAVariantArrayDataElement();
-
- // Overwrite this from the abstract class, need some more checks here
- virtual bool setDataType(const HLADataType* dataType);
-
- virtual bool setNumElements(unsigned size);
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i);
- virtual unsigned getNumElements() const;
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const;
-
- const HLAVariantRecordDataElement* getElement(unsigned index) const;
- HLAVariantRecordDataElement* getElement(unsigned index);
- HLAVariantRecordDataElement* getOrCreateElement(unsigned index);
- void setElement(unsigned index, HLAVariantRecordDataElement* value);
-
- typedef HLAVariantRecordDataElement::DataElementFactory AlternativeDataElementFactory;
-
- void setAlternativeDataElementFactory(AlternativeDataElementFactory* alternativeDataElementFactory);
- AlternativeDataElementFactory* getAlternativeDataElementFactory();
-
-protected:
- virtual void _setStamp(Stamp* stamp);
-
-private:
- HLAVariantRecordDataElement* newElement();
-
- typedef std::vector<SGSharedPtr<HLAVariantRecordDataElement> > ElementVector;
- ElementVector _elementVector;
-
- SGSharedPtr<AlternativeDataElementFactory> _alternativeDataElementFactory;
-};
-
-class HLAStringDataElement : public HLAAbstractArrayDataElement {
-public:
- HLAStringDataElement(const HLAArrayDataType* dataType = 0) :
- HLAAbstractArrayDataElement(dataType)
- {}
- HLAStringDataElement(const HLAArrayDataType* dataType, const std::string& value) :
- HLAAbstractArrayDataElement(dataType),
- _value(value)
- {}
- const std::string& getValue() const
- { return _value; }
- void setValue(const std::string& value)
- { _value = value; setDirty(true); }
-
- virtual bool setNumElements(unsigned count)
- {
- _value.resize(count);
- return true;
- }
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
- {
- HLATemplateDecodeVisitor<std::string::value_type> visitor(stream);
- getElementDataType()->accept(visitor);
- _value[i] = visitor.getValue();
- return true;
- }
-
- virtual unsigned getNumElements() const
- {
- return _value.size();
- }
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
- {
- HLATemplateEncodeVisitor<std::string::value_type> visitor(stream, _value[i]);
- getElementDataType()->accept(visitor);
- return true;
- }
-
-private:
- std::string _value;
-};
-
-class HLAStringData {
-public:
- HLAStringData() :
- _value(new HLAStringDataElement(0))
- { }
- HLAStringData(const std::string& value) :
- _value(new HLAStringDataElement(0))
- { _value->setValue(value); }
-
- operator const std::string&() const
- { return _value->getValue(); }
- HLAStringData& operator=(const std::string& value)
- { _value->setValue(value); return *this; }
-
- const std::string& getValue() const
- { return _value->getValue(); }
- void setValue(const std::string& value)
- { _value->setValue(value); }
-
- const HLAStringDataElement* getDataElement() const
- { return _value.get(); }
- HLAStringDataElement* getDataElement()
- { return _value.get(); }
-
- const HLAArrayDataType* getDataType() const
- { return _value->getDataType(); }
- void setDataType(const HLAArrayDataType* dataType)
- { _value->setDataType(dataType); }
-
-private:
- SGSharedPtr<HLAStringDataElement> _value;
-};
-
-template<typename T>
-class HLAVec2DataElement : public HLAAbstractArrayDataElement {
-public:
- HLAVec2DataElement(const HLAArrayDataType* dataType = 0) :
- HLAAbstractArrayDataElement(dataType),
- _value(SGVec2<T>::zeros())
- {}
- HLAVec2DataElement(const HLAArrayDataType* dataType, const SGVec2<T>& value) :
- HLAAbstractArrayDataElement(dataType),
- _value(value)
- {}
- const SGVec2<T>& getValue() const
- { return _value; }
- void setValue(const SGVec2<T>& value)
- { _value = value; setDirty(true); }
-
- virtual bool setNumElements(unsigned count)
- {
- for (unsigned i = count; i < 2; ++i)
- _value[i] = 0;
- return true;
- }
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
- {
- if (i < 2) {
- HLATemplateDecodeVisitor<typename SGVec2<T>::value_type> visitor(stream);
- getElementDataType()->accept(visitor);
- _value[i] = visitor.getValue();
- } else {
- HLADataTypeDecodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
- virtual unsigned getNumElements() const
- {
- return 2;
- }
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
- {
- if (i < 2) {
- HLATemplateEncodeVisitor<typename SGVec2<T>::value_type> visitor(stream, _value[i]);
- getElementDataType()->accept(visitor);
- } else {
- HLADataTypeEncodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
-private:
- SGVec2<T> _value;
-};
-
-template<typename T>
-class HLAVec2Data {
-public:
- HLAVec2Data() :
- _value(new HLAVec2DataElement<T>(0))
- { }
- HLAVec2Data(const SGVec2<T>& value) :
- _value(new HLAVec2DataElement<T>(0, value))
- { }
-
- operator const SGVec2<T>&() const
- { return _value->getValue(); }
- HLAVec2Data& operator=(const SGVec2<T>& value)
- { _value->setValue(value); return *this; }
-
- const SGVec2<T>& getValue() const
- { return _value->getValue(); }
- void setValue(const SGVec2<T>& value)
- { _value->setValue(value); }
-
- const HLAVec2DataElement<T>* getDataElement() const
- { return _value.get(); }
- HLAVec2DataElement<T>* getDataElement()
- { return _value.get(); }
-
- const HLAArrayDataType* getDataType() const
- { return _value->getDataType(); }
- void setDataType(const HLAArrayDataType* dataType)
- { _value->setDataType(dataType); }
-
-private:
- SGSharedPtr<HLAVec2DataElement<T> > _value;
-};
-
-typedef HLAVec2Data<float> HLAVec2fData;
-typedef HLAVec2Data<double> HLAVec2dData;
-typedef HLAVec2Data<int> HLAVec2iData;
-
-template<typename T>
-class HLAVec3DataElement : public HLAAbstractArrayDataElement {
-public:
- HLAVec3DataElement(const HLAArrayDataType* dataType = 0) :
- HLAAbstractArrayDataElement(dataType),
- _value(SGVec3<T>::zeros())
- {}
- HLAVec3DataElement(const HLAArrayDataType* dataType, const SGVec3<T>& value) :
- HLAAbstractArrayDataElement(dataType),
- _value(value)
- {}
- const SGVec3<T>& getValue() const
- { return _value; }
- void setValue(const SGVec3<T>& value)
- { _value = value; setDirty(true); }
-
- virtual bool setNumElements(unsigned count)
- {
- for (unsigned i = count; i < 3; ++i)
- _value[i] = 0;
- return true;
- }
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
- {
- if (i < 3) {
- HLATemplateDecodeVisitor<typename SGVec3<T>::value_type> visitor(stream);
- getElementDataType()->accept(visitor);
- _value[i] = visitor.getValue();
- } else {
- HLADataTypeDecodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
- virtual unsigned getNumElements() const
- {
- return 3;
- }
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
- {
- if (i < 3) {
- HLATemplateEncodeVisitor<typename SGVec3<T>::value_type> visitor(stream, _value[i]);
- getElementDataType()->accept(visitor);
- } else {
- HLADataTypeEncodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
-private:
- SGVec3<T> _value;
-};
-
-template<typename T>
-class HLAVec3Data {
-public:
- HLAVec3Data() :
- _value(new HLAVec3DataElement<T>(0))
- { }
- HLAVec3Data(const SGVec3<T>& value) :
- _value(new HLAVec3DataElement<T>(0, value))
- { }
-
- operator const SGVec3<T>&() const
- { return _value->getValue(); }
- HLAVec3Data& operator=(const SGVec3<T>& value)
- { _value->setValue(value); return *this; }
-
- const SGVec3<T>& getValue() const
- { return _value->getValue(); }
- void setValue(const SGVec3<T>& value)
- { _value->setValue(value); }
-
- const HLAVec3DataElement<T>* getDataElement() const
- { return _value.get(); }
- HLAVec3DataElement<T>* getDataElement()
- { return _value.get(); }
-
- const HLAArrayDataType* getDataType() const
- { return _value->getDataType(); }
- void setDataType(const HLAArrayDataType* dataType)
- { _value->setDataType(dataType); }
-
-private:
- SGSharedPtr<HLAVec3DataElement<T> > _value;
-};
-
-typedef HLAVec3Data<float> HLAVec3fData;
-typedef HLAVec3Data<double> HLAVec3dData;
-typedef HLAVec3Data<int> HLAVec3iData;
-
-template<typename T>
-class HLAVec4DataElement : public HLAAbstractArrayDataElement {
-public:
- HLAVec4DataElement(const HLAArrayDataType* dataType = 0) :
- HLAAbstractArrayDataElement(dataType),
- _value(SGVec4<T>::zeros())
- {}
- HLAVec4DataElement(const HLAArrayDataType* dataType, const SGVec4<T>& value) :
- HLAAbstractArrayDataElement(dataType),
- _value(value)
- {}
- const SGVec4<T>& getValue() const
- { return _value; }
- void setValue(const SGVec4<T>& value)
- { _value = value; setDirty(true); }
-
- virtual bool setNumElements(unsigned count)
- {
- for (unsigned i = count; i < 4; ++i)
- _value[i] = 0;
- return true;
- }
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
- {
- if (i < 4) {
- HLATemplateDecodeVisitor<typename SGVec4<T>::value_type> visitor(stream);
- getElementDataType()->accept(visitor);
- _value[i] = visitor.getValue();
- } else {
- HLADataTypeDecodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
- virtual unsigned getNumElements() const
- {
- return 4;
- }
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
- {
- if (i < 4) {
- HLATemplateEncodeVisitor<typename SGVec4<T>::value_type> visitor(stream, _value[i]);
- getElementDataType()->accept(visitor);
- } else {
- HLADataTypeEncodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
-private:
- SGVec4<T> _value;
-};
-
-template<typename T>
-class HLAVec4Data {
-public:
- HLAVec4Data() :
- _value(new HLAVec4DataElement<T>(0))
- { }
- HLAVec4Data(const SGVec4<T>& value) :
- _value(new HLAVec4DataElement<T>(0, value))
- { }
-
- operator const SGVec4<T>&() const
- { return _value->getValue(); }
- HLAVec4Data& operator=(const SGVec4<T>& value)
- { _value->setValue(value); return *this; }
-
- const SGVec4<T>& getValue() const
- { return _value->getValue(); }
- void setValue(const SGVec4<T>& value)
- { _value->setValue(value); }
-
- const HLAVec4DataElement<T>* getDataElement() const
- { return _value.get(); }
- HLAVec4DataElement<T>* getDataElement()
- { return _value.get(); }
-
- const HLAArrayDataType* getDataType() const
- { return _value->getDataType(); }
- void setDataType(const HLAArrayDataType* dataType)
- { _value->setDataType(dataType); }
-
-private:
- SGSharedPtr<HLAVec4DataElement<T> > _value;
-};
-
-typedef HLAVec4Data<float> HLAVec4fData;
-typedef HLAVec4Data<double> HLAVec4dData;
-typedef HLAVec4Data<int> HLAVec4iData;
-
-template<typename T>
-class HLAQuatDataElement : public HLAAbstractArrayDataElement {
-public:
- HLAQuatDataElement(const HLAArrayDataType* dataType = 0) :
- HLAAbstractArrayDataElement(dataType),
- _value(SGQuat<T>::unit())
- {}
- HLAQuatDataElement(const HLAArrayDataType* dataType, const SGQuat<T>& value) :
- HLAAbstractArrayDataElement(dataType),
- _value(value)
- {}
-
- const SGQuat<T>& getValue() const
- { return _value; }
- void setValue(const SGQuat<T>& value)
- { _value = value; setDirty(true); }
-
- virtual bool setNumElements(unsigned count)
- {
- for (unsigned i = count; i < 4; ++i)
- _value[i] = 0;
- return true;
- }
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
- {
- if (i < 4) {
- HLATemplateDecodeVisitor<typename SGQuat<T>::value_type> visitor(stream);
- getElementDataType()->accept(visitor);
- _value[i] = visitor.getValue();
- } else {
- HLADataTypeDecodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
- virtual unsigned getNumElements() const
- {
- return 4;
- }
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
- {
- if (i < 4) {
- HLATemplateEncodeVisitor<typename SGQuat<T>::value_type> visitor(stream, _value[i]);
- getElementDataType()->accept(visitor);
- } else {
- HLADataTypeEncodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
-private:
- SGQuat<T> _value;
-};
-
-template<typename T>
-class HLAQuatData {
-public:
- HLAQuatData() :
- _value(new HLAQuatDataElement<T>(0))
- { }
- HLAQuatData(const SGQuat<T>& value) :
- _value(new HLAQuatDataElement<T>(0, value))
- { }
-
- operator const SGQuat<T>&() const
- { return _value->getValue(); }
- HLAQuatData& operator=(const SGQuat<T>& value)
- { _value->setValue(value); return *this; }
-
- const SGQuat<T>& getValue() const
- { return _value->getValue(); }
- void setValue(const SGQuat<T>& value)
- { _value->setValue(value); }
-
- const HLAQuatDataElement<T>* getDataElement() const
- { return _value.get(); }
- HLAQuatDataElement<T>* getDataElement()
- { return _value.get(); }
-
- const HLAArrayDataType* getDataType() const
- { return _value->getDataType(); }
- void setDataType(const HLAArrayDataType* dataType)
- { _value->setDataType(dataType); }
-
-private:
- SGSharedPtr<HLAQuatDataElement<T> > _value;
-};
-
-typedef HLAQuatData<float> HLAQuatfData;
-typedef HLAQuatData<double> HLAQuatdData;
-
-template<typename T>
-class HLAQuat3DataElement : public HLAAbstractArrayDataElement {
-public:
- HLAQuat3DataElement(const HLAArrayDataType* dataType = 0) :
- HLAAbstractArrayDataElement(dataType),
- _value(SGQuat<T>::unit()),
- _imag(SGQuat<T>::unit().getPositiveRealImag())
- {}
- HLAQuat3DataElement(const HLAArrayDataType* dataType, const SGQuat<T>& value) :
- HLAAbstractArrayDataElement(dataType),
- _value(value),
- _imag(value.getPositiveRealImag())
- {}
-
- const SGQuat<T>& getValue() const
- { return _value; }
- void setValue(const SGQuat<T>& value)
- { _value = value; _imag = _value.getPositiveRealImag(); setDirty(true); }
-
- virtual bool encode(HLAEncodeStream& stream) const
- {
- return HLAAbstractArrayDataElement::encode(stream);
- }
- virtual bool decode(HLADecodeStream& stream)
- {
- if (!HLAAbstractArrayDataElement::decode(stream))
- return false;
- _value = SGQuat<T>::fromPositiveRealImag(_imag);
- return true;
- }
-
- virtual bool setNumElements(unsigned count)
- {
- for (unsigned i = count; i < 3; ++i)
- _imag[i] = 0;
- return true;
- }
- virtual bool decodeElement(HLADecodeStream& stream, unsigned i)
- {
- if (i < 3) {
- HLATemplateDecodeVisitor<typename SGQuat<T>::value_type> visitor(stream);
- getElementDataType()->accept(visitor);
- _imag[i] = visitor.getValue();
- } else {
- HLADataTypeDecodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
- virtual unsigned getNumElements() const
- {
- return 3;
- }
- virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const
- {
- if (i < 3) {
- HLATemplateEncodeVisitor<typename SGQuat<T>::value_type> visitor(stream, _imag[i]);
- getElementDataType()->accept(visitor);
- } else {
- HLADataTypeEncodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
- }
-
-private:
- SGQuat<T> _value;
- SGVec3<T> _imag;
-};
-
-template<typename T>
-class HLAQuat3Data {
-public:
- HLAQuat3Data() :
- _value(new HLAQuat3DataElement<T>(0))
- { }
- HLAQuat3Data(const SGQuat<T>& value) :
- _value(new HLAQuat3DataElement<T>(0, value))
- { }
-
- operator const SGQuat<T>&() const
- { return _value->getValue(); }
- HLAQuat3Data& operator=(const SGQuat<T>& value)
- { _value->setValue(value); return *this; }
-
- const SGQuat<T>& getValue() const
- { return _value->getValue(); }
- void setValue(const SGQuat<T>& value)
- { _value->setValue(value); }
-
- const HLAQuat3DataElement<T>* getDataElement() const
- { return _value.get(); }
- HLAQuat3DataElement<T>* getDataElement()
- { return _value.get(); }
-
- const HLAArrayDataType* getDataType() const
- { return _value->getDataType(); }
- void setDataType(const HLAArrayDataType* dataType)
- { _value->setDataType(dataType); }
-
-private:
- SGSharedPtr<HLAQuat3DataElement<T> > _value;
-};
-
-typedef HLAQuat3Data<float> HLAQuat3fData;
-typedef HLAQuat3Data<double> HLAQuat3dData;
-
-}
-
-#endif
diff --git a/simgear/hla/HLAArrayDataType.cxx b/simgear/hla/HLAArrayDataType.cxx
deleted file mode 100644
index 4037b81e..00000000
--- a/simgear/hla/HLAArrayDataType.cxx
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright (C) 2009 - 2012 Mathias Froehlich - Mat...@we...
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Library General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Library General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#include <algorithm>
-
-#include <simgear/compiler.h>
-
-#include "HLAArrayDataType.hxx"
-
-#include "HLAArrayDataElement.hxx"
-
-namespace simgear {
-
-HLAArrayDataType::HLAArrayDataType(const std::string& name) :
- HLADataType(name),
- _isOpaque(false),
- _isString(false)
-{
-}
-
-HLAArrayDataType::~HLAArrayDataType()
-{
-}
-
-void
-HLAArrayDataType::accept(HLADataTypeVisitor& visitor) const
-{
- visitor.apply(*this);
-}
-
-const HLAArrayDataType*
-HLAArrayDataType::toArrayDataType() const
-{
- return this;
-}
-
-void
-HLAArrayDataType::releaseDataTypeReferences()
-{
- _elementDataType = 0;
- HLADataType::releaseDataTypeReferences();
-}
-
-void
-HLAArrayDataType::setElementDataType(const HLADataType* elementDataType)
-{
- _elementDataType = elementDataType;
-}
-
-void
-HLAArrayDataType::setIsOpaque(bool isOpaque)
-{
- _isOpaque = isOpaque;
-}
-
-void
-HLAArrayDataType::setIsString(bool isString)
-{
- _isString = isString;
-}
-
-void
-HLAArrayDataType::_recomputeAlignmentImplementation()
-{
- unsigned alignment = 1;
- if (const HLADataType* dataType = getElementDataType())
- alignment = std::max(alignment, dataType->getAlignment());
- setAlignment(alignment);
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-
-HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) :
- HLAArrayDataType(name)
-{
-}
-
-HLAFixedArrayDataType::~HLAFixedArrayDataType()
-{
-}
-
-void
-HLAFixedArrayDataType::accept(HLADataTypeVisitor& visitor) const
-{
- visitor.apply(*this);
-}
-
-bool
-HLAFixedArrayDataType::decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const
-{
- stream.alignOffsetForSize(getAlignment());
- unsigned numElements = getNumElements();
- if (!value.setNumElements(numElements))
- return false;
- for (unsigned i = 0; i < numElements; ++i)
- if (!value.decodeElement(stream, i))
- return false;
- return true;
-}
-
-bool
-HLAFixedArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const
-{
- stream.alignOffsetForSize(getAlignment());
- unsigned numElementsType = getNumElements();
- unsigned numElementsValue = value.getNumElements();
- unsigned numElements = SGMisc<unsigned>::min(numElementsType, numElementsValue);
- unsigned i = 0;
- for (; i < numElements; ++i)
- if (!value.encodeElement(stream, i))
- return false;
- for (; i < numElementsType; ++i) {
- HLADataTypeEncodeVisitor visitor(stream);
- getElementDataType()->accept(visitor);
- }
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-
-HLAVariableArrayDataType::HLAVariableArrayDataType(const std::string& name) :
- HLAArrayDataType(name)
-{
- setSizeDataType(new HLAUInt32BEDataType);
-}
-
-HLAVariableArrayDataType::~HLAVariableArrayDataType()
-{
-}
-
-void
-HLAVariableArrayDataType::accept(HLADataTypeVisitor& visitor) const
-{
- visitor.apply(*this);
-}
-
-bool
-HLAVariableArrayDataType::decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const
-{
- stream.alignOffsetForSize(getAlignment());
- HLATemplateDecodeVisitor<unsigned> numElementsVisitor(stream);
- getSizeDataType()->accept(numElementsVisitor);
- unsigned numElements = numElementsVisitor.getValue();
- if (!value.setNumElements(numElements))
- return false;
- for (unsigned i = 0; i < numElements; ++i)
- if (!value.decodeElement(stream, i))
- return false;
- return true;
-}
-
-bool
-HLAVariableArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const
-{
- stream.alignOffsetForSize(getAlignment());
- unsigned numElements = value.getNumElements();
- HLATemplateEncodeVisitor<unsigned> numElementsVisitor(stream, numElements);
- getSizeDataType()->accept(numElementsVisitor);
- for (unsigned i = 0; i < numElements; ++i)
- if (!value.encodeElement(stream, i))
- return false;
- return true;
-}
-
-void
-HLAVariableArrayDataType::setSizeDataType(const HLABasicDataType* sizeDataType)
-{
- _sizeDataType = sizeDataType;
-}
-
-void
-HLAVariableArrayDataType::_recomputeAlignmentImplementation()
-{
- unsigned alignment = 1;
- if (const HLADataType* dataType = getElementDataType())
- alignment = std::max(alignment, dataType->getAlignment());
- if (const HLADataType* dataType = getSizeDataType())
- alignment = std::max(alignment, dataType->getAlignment());
- setAlignment(alignment);
-}
-
-} // namespace simgear
diff --git a/simgear/hla/HLAArrayDataType.hxx b/simgear/hla/HLAArrayDataType.hxx
deleted file mode 100644
index 87be3851..00000000
--- a/simgear/hla/HLAArrayDataType.hxx
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (C) 2009 - 2012 Mathias Froehlich - Mat...@we...
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Library General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Library General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-
-#ifndef HLAArrayDataType_hxx
-#define HLAArrayDataType_hxx
-
-#include <string>
-#include <simgear/structure/SGSharedPtr.hxx>
-#include "HLADataType.hxx"
-
-namespace simgear {
-
-class HLAAbstractArrayDataElement;
-
-class HLAArrayDataType : public HLADataType {
-public:
- HLAArrayDataType(const std::string& name = "HLAArrayDataType");
- virtual ~HLAArrayDataType();
-
- virtual void accept(HLADataTypeVisitor& visitor) const;
-
- virtual const HLAArrayDataType* toArrayDataType() const;
-
- virtual void releaseDataTypeReferences();
-
- virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const = 0;
- virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const = 0;
-
- void setElementDataType(const HLADataType* elementDataType);
- const HLADataType* getElementDataType() const
- { return _elementDataType.get(); }
-
- void setIsOpaque(bool isOpaque);
- bool getIsOpaque() const
- { return _isOpaque; }
-
- void setIsString(bool isString);
- bool getIsString() const
- { return _isString; }
-
-protected:
- virtual void _recomputeAlignmentImplementation();
-
-private:
- SGSharedPtr<const HLADataType> _elementDataType;
- bool _isOpaque;
- bool _isString;
-};
-
-class HLAFixedArrayDataType : public HLAArrayDataType {
-public:
- HLAFixedArrayDataType(const std::string& name = "HLAFixedArrayDataType");
- virtual ~HLAFixedArrayDataType();
-
- virtual void accept(HLADataTypeVisitor& visitor) const;
-
- virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const;
- virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const;
-
- void setNumElements(unsigned numElements)
- { _numElements = numElements; }
- unsigned getNumElements() const
- { return _numElements; }
-
-private:
- unsigned _numElements;
-};
-
-class HLAVariableArrayDataType : public HLAArrayDataType {
-public:
- HLAVariableArrayDataType(const std::string& name = "HLAVariableArrayDataType");
- virtual ~HLAVariableArrayDataType();
-
- virtual void accept(HLADataTypeVisitor& visitor) const;
-
- virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const;
- virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const;
-
- void setSizeDataType(const HLABasicDataType* sizeDataType);
- const HLABasicDataType* getSizeDataType() const
- { return _sizeDataType.get(); }
-
-protected:
- virtual void _recomputeAlignmentImplementation();
-
-private:
- SGSharedPtr<const HLABasicDataType> _sizeDataType;
-};
-
-} // namespace simgear
-
-#endif
diff --git a/simgear/hla/HLABasicDataElement.cxx b/simgear/hla/HLABasicDataElement.cxx
deleted file mode 100644
index 4930f57e..00000000
--- a/simgear/hla/HLABasicDataElement.cxx
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (C) 2009 - 2010 Mathias Froehlich - Mat...@we...
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Library General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Library General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
-
-#include <simgear/compiler.h>
-
-#include "HLABasicDataElement.hxx"
-
-#include "HLADataElementVisitor.hxx"
-#include "HLADataTypeVisitor.hxx"
-
-namespace simgear {
-
-HLABasicDataElement::HLABasicDataElement(const HLABasicDataType* dataType) :
- _dataType(dataType)
-{
-}
-
-HLABasicDataElement::~HLABasicDataElement()
-{
-}
-
-void
-HLABasicDataElement::accept(HLADataElementVisitor& visitor)
-{
- visitor.apply(*this);
-}
-
-void
-HLABasicDataElement::accept(HLAConstDataElementVisitor& visitor) const
-{
- visitor.apply(*this);
-}
-
-const HLABasicDataType*
-HLABasicDataElement::getDataType() const
-{
- return _dataType.get();
-}
-
-bool
-HLABasicDataElement::setDataType(const HLADataType* dataType)
-{
- const HLABasicDataType* scalarDataType = dynamic_cast<const HLABasicDataType*>(dataType);
- if (!scalarDataType) {
- SG_LOG(SG_NETWORK, SG_WARN, "HLABasicDataType: unable to set data type!");
- return false;
- }
- setDataType(scalarDataType);
- return true;
-}
-
-void
-HLABasicDataElement::setDataType(const HLABasicDataType* dataType)
-{
- _dataType = dataType;
-}
-
-#define IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(type, ctype) \
-HLAAbstract##type##DataElement::HLAAbstract##type##DataElement(const HLABasicDataType* dataType) :\
- HLABasicDataElement(dataType) \
-{ \
-} \
- \
-HLAAbstract##type##DataElement::~HLAAbstract##type##DataElement() \
-{ \
-} \
- \
-bool \
-HLAAbstract##type##DataElement::encode(HLAEncodeStream& stream) const \
-{ \
- if (!_dataType.valid()) \
- return false; \
- HLATemplateEncodeVisitor<ctype> visitor(stream, getValue()); \
- _dataType->accept(visitor); \
- return true; \
-} \
- \
-bool \
-HLAAbstract##type##DataElement::decode(HLADecodeStream& stream) \
-{ \
- if (!_dataType.valid()) \
- return false; \
- HLATemplateDecodeVisitor<ctype> visitor(stream); \
- _dataType->accept(visitor); \
- setValue(visitor.getValue()); \
- return true; \
-} \
- \
-HLA##type##DataElement::HLA##type##DataElement(const HLABasicDataType* dataType) : \
- HLAAbstract##type##DataElement(dataType), \
- _value(0) \
-{ \
-} \
- \
-HLA##type##DataElement::HLA##type##DataElement(const HLABasicDataType* dataType, ...
[truncated message content] |
|
From: <fli...@li...> - 2026-04-19 22:49:49
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new b3d5012a5 Add missing include
b3d5012a5 is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/b3d5012a55ea868911a5c1898639e2e98ce9d619/
Commit: b3d5012a55ea868911a5c1898639e2e98ce9d619
Author: James Turner
Committer: James Turner
AuthorDate: Thu Apr 16 14:09:09 2026 +0100
Add missing include
---
src/Input/FGMouseInput.cxx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Input/FGMouseInput.cxx b/src/Input/FGMouseInput.cxx
index fd8dab2af..11d91de2f 100644
--- a/src/Input/FGMouseInput.cxx
+++ b/src/Input/FGMouseInput.cxx
@@ -19,6 +19,7 @@
#include <simgear/scene/util/SGPickCallback.hxx>
#include <simgear/structure/commands.hxx>
#include <simgear/timing/timestamp.hxx>
+#include <simgear/structure/commands.hxx>
#include "FGButton.hxx"
#include <GUI/MouseCursor.hxx>
|
|
From: <fli...@li...> - 2026-04-19 16:49:49
|
unknown user pushed a commit to branch next
in repository fgmeta.
The following commit(s) were added to refs/heads/next by this push:
new 7055e9c download_and_compile.sh: add option --enable-ccache
7055e9c is described below
SF URL: http://sourceforge.net/p/flightgear/fgmeta/ci/7055e9c26449cdd88445fffdd44fffc9e26a75e4/
Commit: 7055e9c26449cdd88445fffdd44fffc9e26a75e4
Author: Florent Rougon
Committer: Florent Rougon
AuthorDate: Sun Apr 19 10:54:38 2026 +0200
download_and_compile.sh: add option --enable-ccache
This enables the 'ccache' compiler cache for components that support it
by means of CMake option -DENABLE_CCACHE=ON.
---
download_and_compile.sh | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/download_and_compile.sh b/download_and_compile.sh
index 3a27ee2..d7f692d 100755
--- a/download_and_compile.sh
+++ b/download_and_compile.sh
@@ -572,6 +572,20 @@ function _installOrUpdateDistroPackages(){
"assuming you have installed the relevant packages." ;;
esac
+ # Install 'ccache' if there are good reasons to think it will be required.
+ if _elementIn '-DENABLE_CCACHE=ON' "${ALL_CMAKE_ARGS[@]}"; then
+ PKG+=(ccache)
+ else
+ for component in "${WHATTOBUILD[@]}"; do
+ if _elementIn "$component" "${CMAKE_BASED_COMPONENTS[@]}" && \
+ eval \
+ _elementIn -DENABLE_CCACHE=ON \"\${${component}_CMAKE_ARGS[@]}\"; then
+ PKG+=(ccache)
+ break
+ fi
+ done
+ fi
+
# TerraGear
if _elementIn "TERRAGEAR" "${WHATTOBUILD[@]}"; then
PKG+=(libboost-dev libcgal-dev libgdal-dev libtiff5-dev zlib1g-dev)
@@ -1071,6 +1085,11 @@ Available options:
select GEN as the CMake build system generator (see cmake-generators(7)
for the possibilities; 'Ninja' is a popular alternative to the default).
When switching between build system generators, use the --cleanup option.
+ --enable-ccache
+ Enable the 'ccache' compiler cache for components that react to
+ CMake option -DENABLE_CCACHE=ON. After the first compilation,
+ this considerably speeds up subsequent builds. The cache can be
+ cleared at any time using 'ccache --clear'.
-b RELEASE_TYPE default=RelWithDebInfo
set build type to RELEASE_TYPE (Release|RelWithDebInfo|Debug)
-j X pass -jX to the Make program (X is the number of jobs to run
@@ -2172,7 +2191,8 @@ TEMP=$($getopt -o '+shc:p:a:d:r:G:Ij:O:ib:' \
--longoptions cleanup,git-clone-default-proto:,git-clone-site-params: \
--longoptions package-manager:,sudo:,ignore-intercomponent-deps,compositor \
--longoptions component-branch:,cmake-arg:,sg-cmake-arg:,fg-cmake-arg: \
- --longoptions cmake-args:,build-system-generator:,lts,old-lts,override-repo: \
+ --longoptions cmake-args:,build-system-generator:,enable-ccache \
+ --longoptions lts,old-lts,override-repo: \
--longoptions reset-origin-url,non-interactive,git-info,help,version,verbose \
-n "$PROGNAME" -- "$@")
@@ -2282,6 +2302,8 @@ Allowed components are:\n\n" "$verbatim_component" >&2
FGFS_CMAKE_ARGS+=("$2"); shift 2 ;;
--build-system-generator|-G)
BUILD_SYSTEM_GENERATOR="$2"; shift 2 ;;
+ --enable-ccache)
+ ALL_CMAKE_ARGS+=("-DENABLE_CCACHE=ON"); shift ;;
-a) APT_GET_UPDATE="$2"; shift 2 ;;
-c) COMPILE="$2"; shift 2 ;;
-p) DOWNLOAD_PACKAGES="$2"; shift 2 ;;
|
|
From: <fli...@li...> - 2026-04-19 14:49:50
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new 5db5428f Add file+line to cppbind errors
5db5428f is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/5db5428f6daa67cd359282161037190f285c283d/
Commit: 5db5428f6daa67cd359282161037190f285c283d
Author: James Turner
Committer: James Turner
AuthorDate: Fri Apr 17 10:27:58 2026 +0100
Add file+line to cppbind errors
---
simgear/nasal/code.h | 8 +++++---
simgear/nasal/cppbind/Ghost.hxx | 5 ++++-
simgear/nasal/cppbind/NasalContext.cxx | 7 +++++--
3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/simgear/nasal/code.h b/simgear/nasal/code.h
index 95757fa3..c559a6ab 100644
--- a/simgear/nasal/code.h
+++ b/simgear/nasal/code.h
@@ -21,7 +21,8 @@
// collector synchronization.
#define OBJ_CACHE_SZ 1
-enum {
+// clang-format off
+enum {
OP_NOT, OP_MUL, OP_PLUS, OP_MINUS, OP_DIV, OP_NEG, OP_CAT, OP_LT, OP_LTE,
OP_GT, OP_GTE, OP_EQ, OP_NEQ, OP_EACH, OP_JMP, OP_JMPLOOP, OP_JIFNOTPOP,
OP_JIFEND, OP_FCALL, OP_MCALL, OP_RETURN, OP_PUSHCONST, OP_PUSHONE,
@@ -32,6 +33,7 @@ enum {
OP_MCALLH, OP_XCHG2, OP_UNPACK, OP_SLICE, OP_SLICE2, OP_BIT_AND, OP_BIT_OR,
OP_BIT_XOR, OP_BIT_NEG
};
+// clang-format on
struct Frame {
naRef func; // naFunc object
@@ -49,7 +51,7 @@ struct Globals {
void** deadBlocks;
int deadsz;
int ndead;
-
+
// Threading stuff
int nThreads;
int waitCount;
@@ -99,7 +101,7 @@ struct Context {
// Error handling
jmp_buf jumpHandle;
- char error[128];
+ char error[1024];
naRef dieArg;
// Sub-call lists
diff --git a/simgear/nasal/cppbind/Ghost.hxx b/simgear/nasal/cppbind/Ghost.hxx
index a2a6accd..2303c483 100644
--- a/simgear/nasal/cppbind/Ghost.hxx
+++ b/simgear/nasal/cppbind/Ghost.hxx
@@ -302,7 +302,10 @@ namespace nasal
}
catch(const std::exception& ex)
{
- naRuntimeError(c, "Fatal error in method call: %s", ex.what());
+ naRuntimeError(c, "Fatal error in method call: %s (at %s:%d)",
+ ex.what(),
+ naStr_data(naGetSourceFile(c, 0)),
+ naGetLine(c, 0));
}
catch(...)
{
diff --git a/simgear/nasal/cppbind/NasalContext.cxx b/simgear/nasal/cppbind/NasalContext.cxx
index 6b6e2ae8..71569309 100644
--- a/simgear/nasal/cppbind/NasalContext.cxx
+++ b/simgear/nasal/cppbind/NasalContext.cxx
@@ -59,8 +59,11 @@ namespace nasal
naNil() // locals
);
- if( const char* error = naGetError(_ctx) )
- throw std::runtime_error(error);
+ if (const char* error = naGetError(_ctx)) {
+ int line = naGetLine(_ctx, 0);
+ char* file = naStr_data(naGetSourceFile(_ctx, 0));
+ throw std::runtime_error(std::string{error} + " (at " + file + ":" + std::to_string(line) + ")");
+ }
return ret;
}
|
|
From: <fli...@li...> - 2026-04-19 08:49:49
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new 1bb90334f Dynamic menu contents
1bb90334f is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/1bb90334fd04a5dd95dcfd8d6db90839d1515176/
Commit: 1bb90334fd04a5dd95dcfd8d6db90839d1515176
Author: James Turner
Committer: James Turner
AuthorDate: Thu Apr 16 11:57:04 2026 +0100
Dynamic menu contents
---
src/GUI/FGNasalMenuBar.cxx | 190 +++++++++++++++--
src/Input/FGMouseInput.cxx | 1 +
src/Main/fg_scene_commands.cxx | 7 +-
src/Scripting/NasalSys.cxx | 8 +-
src/Scripting/NasalSys.hxx | 7 +-
test_suite/FGTestApi/testGlobals.cxx | 8 +-
test_suite/FGTestApi/testGlobals.hxx | 16 +-
test_suite/fgJunitOutputter.cxx | 4 +-
test_suite/unit_tests/GUI/CMakeLists.txt | 7 +-
test_suite/unit_tests/GUI/TestSuite.cxx | 2 +
test_suite/unit_tests/GUI/test_nasalMenu.cxx | 301 +++++++++++++++++++++++++++
test_suite/unit_tests/GUI/test_nasalMenu.hxx | 30 +++
12 files changed, 545 insertions(+), 36 deletions(-)
diff --git a/src/GUI/FGNasalMenuBar.cxx b/src/GUI/FGNasalMenuBar.cxx
index 34409e677..edfd31ef6 100644
--- a/src/GUI/FGNasalMenuBar.cxx
+++ b/src/GUI/FGNasalMenuBar.cxx
@@ -38,6 +38,12 @@ enum class VisibilityMode {
HideIfOverlapsWindow
};
+enum class MenuChangeKind {
+ ChildAdded = 0,
+ ChildRemoved = 1,
+ Updated = 2
+};
+
///////////////////////////////////////////////////////////////////////////////
class NasalMenuItem : public SGReferenced,
@@ -88,23 +94,30 @@ public:
return _submenu;
}
+ SGPropertyNode_ptr configNode() const
+ {
+ return _config;
+ }
+
void initFromNode(SGPropertyNode_ptr config);
- using NasalCallback = std::function<void()>;
+ using NasalCallback = std::function<void(int, int)>;
void addCallback(NasalCallback cb)
{
- _callbacks.push_back(cb);
+ _changedCallbacks.push_back(cb);
}
protected:
void valueChanged(SGPropertyNode* prop) override;
private:
- void runCallbacks()
+ SGPropertyNode_ptr _config;
+ void runChangedCallbacks(MenuChangeKind kind, int index)
{
- std::for_each(_callbacks.begin(), _callbacks.end(), [](NasalCallback& cb) {
- cb();
+ const int kindInt = static_cast<int>(kind);
+ std::for_each(_changedCallbacks.begin(), _changedCallbacks.end(), [kindInt, index](NasalCallback& cb) {
+ cb(kindInt, index);
});
}
@@ -120,7 +133,7 @@ private:
_checkedNode, _labelNode;
NasalMenuPtr _submenu;
SGBindingList _bindings;
- std::vector<NasalCallback> _callbacks;
+ std::vector<NasalCallback> _changedCallbacks;
};
class NasalMenu : public SGReferenced,
@@ -128,6 +141,7 @@ class NasalMenu : public SGReferenced,
{
public:
using ItemsVec = std::vector<NasalMenuItemPtr>;
+ using NasalCallback = std::function<void(int, int)>;
std::string label() const
{
@@ -149,19 +163,40 @@ public:
return _items;
}
+ SGPropertyNode_ptr configNode() const
+ {
+ return _config;
+ }
+
+ void addCallback(NasalCallback cb)
+ {
+ _changedCallbacks.push_back(cb);
+ }
+
void aboutToShow();
void initFromNode(SGPropertyNode_ptr config);
protected:
void valueChanged(SGPropertyNode* prop) override;
+ void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override;
+ void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override;
private:
std::string _name;
std::string _label;
bool _enabled = true;
- SGPropertyNode_ptr _enabledNode, _labelNode;
+ SGPropertyNode_ptr _enabledNode, _labelNode, _config;
ItemsVec _items;
+ std::vector<NasalCallback> _changedCallbacks;
+
+ void runChangedCallbacks(MenuChangeKind kind, int index)
+ {
+ const int kindInt = static_cast<int>(kind);
+ std::for_each(_changedCallbacks.begin(), _changedCallbacks.end(), [kindInt, index](NasalCallback& cb) {
+ cb(kindInt, index);
+ });
+ }
};
@@ -169,6 +204,7 @@ private:
void NasalMenuItem::initFromNode(SGPropertyNode_ptr config)
{
+ _config = config;
auto n = config->getChild("name");
if (!n) {
SG_LOG(SG_GUI, SG_DEV_WARN, "menu item without <name> element:" << config->getLocation());
@@ -226,8 +262,8 @@ void NasalMenuItem::initFromNode(SGPropertyNode_ptr config)
void NasalMenuItem::valueChanged(SGPropertyNode* n)
{
- // sort this by likelyhood these changing, to avoid
- // unnecessary string comaprisons
+ // sort this by likelihood these changing, to avoid
+ // unnecessary string comparisons
if (n == _enabledNode) {
_enabled = _enabledNode->getBoolValue();
} else if (n == _checkedNode) {
@@ -238,8 +274,8 @@ void NasalMenuItem::valueChanged(SGPropertyNode* n)
_name = n->getStringValue();
}
- // allow Nasal to response to changes
- runCallbacks();
+ // allow Nasal to respond to changes
+ runChangedCallbacks(MenuChangeKind::Updated, -1);
}
void NasalMenuItem::fire()
@@ -265,6 +301,9 @@ void NasalMenuItem::aboutToShow()
void NasalMenu::initFromNode(SGPropertyNode_ptr config)
{
+ _config = config;
+ config->addChangeListener(this);
+
const auto name = config->getStringValue("name");
_name = name;
@@ -304,21 +343,115 @@ void NasalMenu::valueChanged(SGPropertyNode* n)
} else if (n == _labelNode) {
_label = FGMenuBar::getLocalizedLabel(n->getParent());
}
+ runChangedCallbacks(MenuChangeKind::Updated, -1);
+}
+
+void NasalMenu::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
+{
+ if (parent != _config) return;
+ if (child->getNameString() != "item") return;
+
+ auto newItem = new NasalMenuItem;
+ newItem->initFromNode(child);
+
+ // Insert in index order; indices may be non-contiguous so compare directly
+ const int newIndex = child->getIndex();
+ auto insertPos = std::find_if(_items.begin(), _items.end(), [newIndex](const NasalMenuItemPtr& item) {
+ return item->configNode()->getIndex() > newIndex;
+ });
+ _items.insert(insertPos, newItem);
+ runChangedCallbacks(MenuChangeKind::ChildAdded, newIndex);
+}
+
+void NasalMenu::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
+{
+ if (parent != _config) return;
+ if (child->getNameString() != "item") return;
+
+ const int removedIndex = child->getIndex();
+ auto it = std::find_if(_items.begin(), _items.end(), [child](const NasalMenuItemPtr& item) {
+ return item->configNode() == child;
+ });
+ if (it != _items.end()) {
+ runChangedCallbacks(MenuChangeKind::ChildRemoved, removedIndex);
+ _items.erase(it);
+ }
}
///////////////////////////////////////////////////////////////////////////////
-class FGNasalMenuBar::NasalMenuBarPrivate
+class FGNasalMenuBar::NasalMenuBarPrivate : public SGPropertyChangeListener
{
public:
+ using NasalCallback = std::function<void(int, int)>;
+
std::vector<NasalMenuPtr> getMenus() const
{
return menus;
}
+ void addCallback(NasalCallback cb)
+ {
+ _changedCallbacks.push_back(cb);
+ }
+
VisibilityMode visibilityMode = VisibilityMode::Visible;
bool computedVisibility = true;
std::vector<NasalMenuPtr> menus;
+ SGPropertyNode_ptr config;
+
+protected:
+ void childAdded(SGPropertyNode* parent, SGPropertyNode* child) override
+ {
+ if (parent != config) return;
+ if (child->getNameString() != "menu") return;
+
+ auto newMenu = new NasalMenu;
+ newMenu->initFromNode(child);
+
+ // Insert in index order; indices may be non-contiguous so compare directly
+ const int newIndex = child->getIndex();
+ auto insertPos = std::find_if(menus.begin(), menus.end(), [newIndex](const NasalMenuPtr& m) {
+ return m->configNode()->getIndex() > newIndex;
+ });
+ menus.insert(insertPos, newMenu);
+ runChangedCallbacks(MenuChangeKind::ChildAdded, newIndex);
+ }
+
+ void childRemoved(SGPropertyNode* parent, SGPropertyNode* child) override
+ {
+ if (parent != config) return;
+ if (child->getNameString() != "menu") return;
+
+ const int removedIndex = child->getIndex();
+ auto it = std::find_if(menus.begin(), menus.end(), [child](const NasalMenuPtr& m) {
+ return m->configNode() == child;
+ });
+ if (it != menus.end()) {
+ runChangedCallbacks(MenuChangeKind::ChildRemoved, removedIndex);
+ menus.erase(it);
+ }
+ }
+
+private:
+ friend class FGNasalMenuBar;
+
+ static naRef addChangedCallback(NasalMenuBarPrivate& bar, const nasal::CallContext& ctx)
+ {
+ auto cb = ctx.requireArg<NasalCallback>(0);
+ bar.addCallback(cb);
+ return naNil();
+ }
+
+ std::vector<NasalCallback> _changedCallbacks;
+
+ void runChangedCallbacks(MenuChangeKind kind, int index)
+ {
+ const int kindInt = static_cast<int>(kind);
+ std::for_each(_changedCallbacks.begin(), _changedCallbacks.end(), [kindInt, index](NasalCallback& cb) {
+ cb(kindInt, index);
+ });
+ }
};
///////////////////////////////////////////////////////////////////////////////
@@ -364,6 +497,9 @@ void FGNasalMenuBar::hide()
void FGNasalMenuBar::configure(SGPropertyNode_ptr config)
{
+ _d->config = config;
+ config->addChangeListener(_d.get());
+
_d->menus.clear();
for (auto i : config->getChildren("menu")) {
auto m = new NasalMenu;
@@ -399,6 +535,13 @@ static naRef f_itemAddCallback(NasalMenuItem& item, const nasal::CallContext& ct
return naNil();
}
+static naRef f_menuAddCallback(NasalMenu& menu, const nasal::CallContext& ctx)
+{
+ auto cb = ctx.requireArg<NasalMenu::NasalCallback>(0);
+ menu.addCallback(cb);
+ return naNil();
+}
+
void FGNasalMenuBar::setupGhosts(nasal::Hash& compatModule)
{
using MenuItemGhost = nasal::Ghost<NasalMenuItemPtr>;
@@ -415,14 +558,29 @@ void FGNasalMenuBar::setupGhosts(nasal::Hash& compatModule)
.method("addChangedCallback", &f_itemAddCallback);
using MenuGhost = nasal::Ghost<NasalMenuPtr>;
- MenuGhost::init("gui.xml.Menu")
+ MenuGhost::init("gui.xml.MenuImpl")
.member("label", &NasalMenu::label)
.member("name", &NasalMenu::name)
.member("enabled", &NasalMenu::isEnabled)
- .member("items", &NasalMenu::items);
+ .member("items", &NasalMenu::items)
+ .method("addChangedCallback", &f_menuAddCallback);
- using MenuBarGhost = nasal::Ghost<std::shared_ptr<NasalMenuBarPrivate>>;
+ using MenuBarRef = std::shared_ptr<NasalMenuBarPrivate>;
+ using MenuBarGhost = nasal::Ghost<MenuBarRef>;
MenuBarGhost::init("gui.xml.MenuBar")
- .member("menus", &NasalMenuBarPrivate::getMenus);
+ .member("menus", &NasalMenuBarPrivate::getMenus)
+ .method("addChangedCallback", &NasalMenuBarPrivate::addChangedCallback);
+
+ // Expose MenuChangeKind constants on gui.Menu so Nasal callers can compare
+ // against symbolic names rather than raw integers.
+ auto nas = globals->get_subsystem<FGNasalSys>();
+ nasal::Context nasCtx;
+ nasal::Hash guiModule{nas->getModule("gui"), nasCtx};
+ nasal::Hash xmlHash{guiModule.get("xml"), nasCtx};
+ nasal::Hash menuHash = xmlHash.createHash("Menu");
+
+ menuHash.set("ChildAdded", naNum(static_cast<int>(MenuChangeKind::ChildAdded)));
+ menuHash.set("ChildRemoved", naNum(static_cast<int>(MenuChangeKind::ChildRemoved)));
+ menuHash.set("Updated", naNum(static_cast<int>(MenuChangeKind::Updated)));
}
diff --git a/src/Input/FGMouseInput.cxx b/src/Input/FGMouseInput.cxx
index e68a3cd3e..fd8dab2af 100644
--- a/src/Input/FGMouseInput.cxx
+++ b/src/Input/FGMouseInput.cxx
@@ -17,6 +17,7 @@
#include <simgear/scene/model/SGPickAnimation.hxx>
#include <simgear/scene/util/SGPickCallback.hxx>
+#include <simgear/structure/commands.hxx>
#include <simgear/timing/timestamp.hxx>
#include "FGButton.hxx"
diff --git a/src/Main/fg_scene_commands.cxx b/src/Main/fg_scene_commands.cxx
index 694d4c5b5..d0aed5ef3 100644
--- a/src/Main/fg_scene_commands.cxx
+++ b/src/Main/fg_scene_commands.cxx
@@ -426,14 +426,13 @@ do_dialog_apply (const SGPropertyNode * arg, SGPropertyNode * root)
/**
- * Redraw GUI (applying new widget colors). Doesn't reload the dialogs,
- * unlike reinit().
+ * Deprecated: gui-redraw is not needed with Canvas GUI.
+ * Dynamic menu changes are handled via property-change listeners.
*/
static bool
do_gui_redraw (const SGPropertyNode * arg, SGPropertyNode * root)
{
- auto gui = globals->get_subsystem<NewGUI>();
- gui->redraw();
+ SG_LOG(SG_GUI, SG_DEV_ALERT, "gui-redraw command is deprecated and has no effect with Canvas GUI");
return true;
}
diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx
index 0184f87f9..ab4fa7b33 100644
--- a/src/Scripting/NasalSys.cxx
+++ b/src/Scripting/NasalSys.cxx
@@ -353,11 +353,11 @@ FGNasalSys::~FGNasalSys()
nasalSys = nullptr;
}
-bool FGNasalSys::parseAndRunWithOutput(const std::string& source, std::string& output, std::string& errors)
+bool FGNasalSys::parseAndRunWithOutput(const std::string& source, std::string& output, std::string& errors, int lineOffset)
{
naContext ctx = naNewContext();
naRef code = parse(ctx, "FGNasalSys::parseAndRun()", source.c_str(),
- source.size(), errors);
+ source.size(), errors, lineOffset);
if(naIsNil(code)) {
naFreeContext(ctx);
return false;
@@ -1631,12 +1631,12 @@ naRef FGNasalSys::getModule(const std::string& moduleName, bool create) const
naRef FGNasalSys::parse(naContext ctx, const char* filename,
const char* buf, int len,
- std::string& errors)
+ std::string& errors, int lineOffset)
{
int errLine = -1;
naRef srcfile = naNewString(ctx);
naStr_fromdata(srcfile, (char*)filename, strlen(filename));
- naRef code = naParseCode(ctx, srcfile, 1, (char*)buf, len, &errLine);
+ naRef code = naParseCode(ctx, srcfile, lineOffset, (char*)buf, len, &errLine);
if(naIsNil(code)) {
std::ostringstream errorMessageStream;
errorMessageStream << "Nasal parse error: " << naGetError(ctx) <<
diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx
index 775fede24..d4faf6331 100644
--- a/src/Scripting/NasalSys.hxx
+++ b/src/Scripting/NasalSys.hxx
@@ -57,8 +57,9 @@ public:
bool parseAndRun(const std::string& source);
bool parseAndRunWithOutput(const std::string& source,
- std::string& output,
- std::string& errors);
+ std::string& output,
+ std::string& errors,
+ int lineOffset = 1);
// Implementation of the settimer extension function
void setTimer(naContext c, int argc, naRef* args);
@@ -190,7 +191,7 @@ private:
void addModule(std::string moduleName, simgear::PathList scripts);
static void logError(naContext);
naRef parse(naContext ctx, const char* filename, const char* buf, int len,
- std::string& errors);
+ std::string& errors, int lineOffset = 1);
naRef genPropsModule();
friend TimerObj;
diff --git a/test_suite/FGTestApi/testGlobals.cxx b/test_suite/FGTestApi/testGlobals.cxx
index ff1e7520a..baa8675d9 100644
--- a/test_suite/FGTestApi/testGlobals.cxx
+++ b/test_suite/FGTestApi/testGlobals.cxx
@@ -446,9 +446,9 @@ void writePointToKML(const std::string& ident, const SGGeod& pos)
global_kmlStream << "</Placemark>\n";
}
-bool executeNasal(const std::string& code)
+bool executeNasal(const std::string& code, int lineOffset)
{
- auto runtimeErrors = executeNasalExpectRuntimeErrors(code);
+ auto runtimeErrors = executeNasalExpectRuntimeErrors(code, lineOffset);
if (!runtimeErrors) {
// parse error
@@ -481,7 +481,7 @@ std::string parseNasalExpectError(const std::string& code)
return parseErrors;
}
-std::optional<string_list> executeNasalExpectRuntimeErrors(const std::string& code)
+std::optional<string_list> executeNasalExpectRuntimeErrors(const std::string& code, int lineOffset)
{
auto nasal = globals->get_subsystem<FGNasalSys>();
if (!nasal) {
@@ -490,7 +490,7 @@ std::optional<string_list> executeNasalExpectRuntimeErrors(const std::string& co
nasal->getAndClearErrorList();
std::string output, parseErrors;
- bool ok = nasal->parseAndRunWithOutput(code, output, parseErrors);
+ bool ok = nasal->parseAndRunWithOutput(code, output, parseErrors, lineOffset);
if (!ok) {
SG_LOG(SG_NASAL, SG_ALERT, "Nasal parse errors:" << parseErrors);
return {};
diff --git a/test_suite/FGTestApi/testGlobals.hxx b/test_suite/FGTestApi/testGlobals.hxx
index 476525a1a..69f53712c 100644
--- a/test_suite/FGTestApi/testGlobals.hxx
+++ b/test_suite/FGTestApi/testGlobals.hxx
@@ -74,15 +74,27 @@ void writePointToKML(const std::string& ident, const SGGeod& pos);
/** Run nasal code.
*
* Return false in case of parse or runtime error.
+ * lineOffset is passed to the Nasal parser so that line numbers in error
+ * messages refer to actual source lines in the calling file.
*/
-bool executeNasal(const std::string& code);
+bool executeNasal(const std::string& code, int lineOffset = 1);
/** Run nasal code and return runtime errors.
*
* In case of parse error, return empty optional.
* Otherwise, return the list of runtime errors.
*/
-std::optional<string_list> executeNasalExpectRuntimeErrors(const std::string& code);
+std::optional<string_list> executeNasalExpectRuntimeErrors(const std::string& code, int lineOffset = 1);
+
+/**
+ * Convenience macros that automatically pass the current source line so that
+ * Nasal error messages show the correct location in the C++ test file.
+ */
+#define FGTESTAPI_EXECUTE_NASAL(code) \
+ FGTestApi::executeNasal((code), __LINE__)
+
+#define FGTESTAPI_EXECUTE_NASAL_EXPECT_ERRORS(code) \
+ FGTestApi::executeNasalExpectRuntimeErrors((code), __LINE__)
/**
* @brief parse some Nasal expecting a parser error.
diff --git a/test_suite/fgJunitOutputter.cxx b/test_suite/fgJunitOutputter.cxx
index c64251bf4..dc1c2f111 100644
--- a/test_suite/fgJunitOutputter.cxx
+++ b/test_suite/fgJunitOutputter.cxx
@@ -171,13 +171,13 @@ void fgJunitOutputter::writeJunit()
[&localType, &localtest_data_records, &localjunitReportFile](string testClass) {
time_t classTiming = 0;
std::for_each(localtest_data_records->begin(), localtest_data_records->end(),
- [&localjunitReportFile, &classTiming, &testClass](TestDataCapt test_data) {
+ [&classTiming, &testClass](TestDataCapt test_data) {
if (test_data.name.rfind(testClass, 0) == 0) {
classTiming += test_data.timing;
}
});
std::for_each(localtest_data_records->begin(), localtest_data_records->end(),
- [&localType, &localjunitReportFile, &classTiming, &testClass](TestDataCapt test_data) {
+ [&localType, &localjunitReportFile, &testClass](TestDataCapt test_data) {
if (test_data.name.rfind(testClass, 0) == 0) {
auto methodName = test_data.name.substr(test_data.name.find("::") + 2, test_data.name.length());
localjunitReportFile << "<testcase suite_name=\"" << localType << "\" classname=\"" << testClass << "\" name=\"" << methodName << "\" time=\"" << ((double)test_data.timing / 1000000) << "\" file=\""
diff --git a/test_suite/unit_tests/GUI/CMakeLists.txt b/test_suite/unit_tests/GUI/CMakeLists.txt
index 649a371a6..b4b40a4eb 100644
--- a/test_suite/unit_tests/GUI/CMakeLists.txt
+++ b/test_suite/unit_tests/GUI/CMakeLists.txt
@@ -1,6 +1,11 @@
# SPDX-FileCopyrightText: 2010 James Turner
# SPDX-License-Identifier: GPL-2.0-or-later
-target_sources(fgfs_test_suite PRIVATE TestSuite.cxx test_xmlDialog.cxx test_xmlDialog.hxx)
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ test_xmlDialog.cxx test_xmlDialog.hxx
+ test_nasalMenu.cxx test_nasalMenu.hxx
+)
fg_add_test_suite(XMLDialogTests u)
+fg_add_test_suite(NasalMenuTests u)
diff --git a/test_suite/unit_tests/GUI/TestSuite.cxx b/test_suite/unit_tests/GUI/TestSuite.cxx
index 25dd5db78..d7b4e0d81 100644
--- a/test_suite/unit_tests/GUI/TestSuite.cxx
+++ b/test_suite/unit_tests/GUI/TestSuite.cxx
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2025 James Turner <ja...@fl...>
+#include "test_nasalMenu.hxx"
#include "test_xmlDialog.hxx"
// Set up the unit tests.
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(NasalMenuTests, "Unit tests");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(XMLDialogTests, "Unit tests");
diff --git a/test_suite/unit_tests/GUI/test_nasalMenu.cxx b/test_suite/unit_tests/GUI/test_nasalMenu.cxx
new file mode 100644
index 000000000..4434c3212
--- /dev/null
+++ b/test_suite/unit_tests/GUI/test_nasalMenu.cxx
@@ -0,0 +1,301 @@
+/*
+ * SPDX-FileCopyrightText: 2026 James Turner <ja...@fl...>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "test_nasalMenu.hxx"
+#include "config.h"
+
+#include "cppunit/TestAssert.h"
+#include "test_suite/FGTestApi/NavDataCache.hxx"
+#include "test_suite/FGTestApi/testGlobals.hxx"
+
+#include <simgear/canvas/Canvas.hxx>
+#include <simgear/props/props.hxx>
+
+#include <Main/fg_commands.hxx>
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+
+#include <Canvas/canvas_mgr.hxx>
+#include <Canvas/gui_mgr.hxx>
+
+#include "test_suite/FGTestApi/DummyCanvasSystemAdapter.hxx"
+
+#include <GUI/new_gui.hxx>
+
+using namespace std::string_literals;
+
+extern bool global_nasalMinimalInit;
+
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+
+/**
+ * Populate /sim/menubar/default with a minimal two-menu structure:
+ *
+ * menu[0] name="test-file-menu" label="Test File"
+ * item[0] name="test-reset" label="Test Reset" enabled=true
+ * item[1] name="test-exit" label="Test Exit" enabled=false
+ *
+ * menu[1] name="test-help-menu" label="Test Help"
+ * item[0] name="test-about" label="Test About" enabled=true
+ */
+static void populateTestMenubar()
+{
+ auto menubarNode = fgGetNode("/sim/menubar/default", true);
+
+ auto fileMenu = menubarNode->addChild("menu");
+ fileMenu->setStringValue("name", "test-file-menu");
+ fileMenu->setStringValue("label", "Test File");
+
+ auto item0 = fileMenu->addChild("item");
+ item0->setStringValue("name", "test-reset");
+ item0->setStringValue("label", "Test Reset");
+
+ auto item1 = fileMenu->addChild("item");
+ item1->setStringValue("name", "test-exit");
+ item1->setStringValue("label", "Test Exit");
+ item1->setBoolValue("enabled", false);
+
+ auto helpMenu = menubarNode->addChild("menu");
+ helpMenu->setStringValue("name", "test-help-menu");
+ helpMenu->setStringValue("label", "Test Help");
+
+ auto helpItem0 = helpMenu->addChild("item");
+ helpItem0->setStringValue("name", "test-about");
+ helpItem0->setStringValue("label", "Test About");
+}
+
+// ---------------------------------------------------------------------------
+
+void NasalMenuTests::setUp()
+{
+ global_nasalMinimalInit = false;
+
+ FGTestApi::setUp::initTestGlobals("nasal-menu");
+ FGTestApi::setUp::initNavDataCache(); // dialog loader uses the cache
+
+ populateTestMenubar();
+
+ // Force the NasalMenuBar implementation (not the native OS bars).
+ fgSetBool("/sim/menubar/native", false);
+
+ // Canvas needs loadxml command.
+ fgInitCommands();
+
+ simgear::canvas::Canvas::setSystemAdapter(
+ simgear::canvas::SystemAdapterPtr(new canvas::DummyCanvasSystemAdapter));
+
+ auto sm = globals->get_subsystem_mgr();
+ sm->add<CanvasMgr>();
+ sm->add<NewGUI>();
+ sm->add("CanvasGUI", new GUIMgr, SGSubsystemMgr::DISPLAY);
+
+ sm->bind();
+ sm->init();
+
+ FGTestApi::setUp::initStandardNasal(true /* withCanvas */);
+
+ // Override gui._createMenuBar before postinit so we can capture the
+ // menubar ghost in a global variable without needing a live Canvas window.
+ bool ok = FGTESTAPI_EXECUTE_NASAL(R"(
+ globals._testMenubarGhost = nil;
+ gui._createMenuBar = func(ghost) {
+ globals._testMenubarGhost = ghost;
+ };
+ )");
+ ;
+ CPPUNIT_ASSERT(ok);
+
+ sm->postinit();
+
+ // Sanity check – the hook should have fired.
+ ok = FGTESTAPI_EXECUTE_NASAL(R"(
+ unitTest.assert(_testMenubarGhost != nil, "menubar ghost was not captured");
+ )");
+ ;
+ CPPUNIT_ASSERT(ok);
+}
+
+void NasalMenuTests::tearDown()
+{
+ FGTestApi::tearDown::shutdownTestGlobals();
+}
+
+// ---------------------------------------------------------------------------
+// Test 1 – basic structure and fields exposed to Nasal
+// ---------------------------------------------------------------------------
+
+void NasalMenuTests::testBasicStructure()
+{
+ bool ok = FGTESTAPI_EXECUTE_NASAL(R"(
+ var bar = _testMenubarGhost;
+
+ # Two top-level menus.
+ var menus = bar.menus;
+ unitTest.assert_equal(size(menus), 2, "menu count");
+
+ # First menu identity.
+ var fileMenu = menus[0];
+ unitTest.assert_equal(fileMenu.name, "test-file-menu", "menu[0].name");
+ unitTest.assert_equal(fileMenu.label, "Test File", "menu[0].label");
+ unitTest.assert_equal(fileMenu.enabled, 1, "menu[0].enabled");
+
+ # Second menu.
+ var helpMenu = menus[1];
+ unitTest.assert_equal(helpMenu.name, "test-help-menu", "menu[1].name");
+ unitTest.assert_equal(helpMenu.label, "Test Help", "menu[1].label");
+
+ # Items in the first menu.
+ var items = fileMenu.items;
+ unitTest.assert_equal(size(items), 2, "file menu item count");
+
+ var resetItem = items[0];
+ unitTest.assert_equal(resetItem.name, "test-reset", "item[0].name");
+ unitTest.assert_equal(resetItem.label, "Test Reset", "item[0].label");
+ unitTest.assert_equal(resetItem.enabled, 1, "item[0].enabled");
+ unitTest.assert_equal(resetItem.separator, 0, "item[0].separator");
+ unitTest.assert_equal(resetItem.checkable, 0, "item[0].checkable");
+
+ var exitItem = items[1];
+ unitTest.assert_equal(exitItem.name, "test-exit", "item[1].name");
+ unitTest.assert_equal(exitItem.label, "Test Exit", "item[1].label");
+ unitTest.assert_equal(exitItem.enabled, 0, "item[1].enabled");
+
+ # Items in the second menu.
+ var helpItems = helpMenu.items;
+ unitTest.assert_equal(size(helpItems), 1, "help menu item count");
+ unitTest.assert_equal(helpItems[0].name, "test-about", "help item[0].name");
+
+ # MenuChangeKind constants must be exposed on gui.Menu.
+ unitTest.assert_equal(gui.Menu.ChildAdded, 0, "gui.Menu.ChildAdded");
+ unitTest.assert_equal(gui.Menu.ChildRemoved, 1, "gui.Menu.ChildRemoved");
+ unitTest.assert_equal(gui.Menu.Updated, 2, "gui.Menu.Updated");
+ )");
+ CPPUNIT_ASSERT(ok);
+}
+
+// ---------------------------------------------------------------------------
+// Test 2 – changes to config properties trigger the Updated callback
+// ---------------------------------------------------------------------------
+
+void NasalMenuTests::testUpdateCallback()
+{
+ // Register callbacks on the first menu and on its first item, then
+ // trigger changes via property-tree writes and verify the callbacks fire.
+ bool ok = FGTESTAPI_EXECUTE_NASAL(R"(
+ var fileMenu = _testMenubarGhost.menus[0];
+ var resetItem = fileMenu.items[0];
+
+ # --- menu-level callback ---
+ var menuCallCount = 0;
+ var menuLastKind = -1;
+ var menuLastIndex = -1;
+
+ fileMenu.addChangedCallback(func(kind, index) {
+ menuCallCount += 1;
+ menuLastKind = kind;
+ menuLastIndex = index;
+ });
+
+ # Disable the menu via the property tree.
+ var menuNode = props.globals.getNode("/sim/menubar/default/menu[0]");
+ menuNode.getNode("enabled").setBoolValue(0);
+
+ unitTest.assert_equal(menuCallCount, 1, "menu callback fire count");
+ unitTest.assert_equal(menuLastKind, gui.xml.Menu.Updated, "menu callback kind");
+ unitTest.assert_equal(menuLastIndex, -1, "menu callback index");
+
+ # --- item-level callback ---
+ var itemCallCount = 0;
+ var itemLastKind = -1;
+
+ resetItem.addChangedCallback(func(kind, index) {
+ itemCallCount += 1;
+ itemLastKind = kind;
+ });
+
+ # Change the enabled state of the first item.
+ var itemNode = menuNode.getNode("item[0]");
+ itemNode.getNode("enabled").setBoolValue(0);
+
+ unitTest.assert_equal(itemCallCount, 1, "item callback fire count");
+ unitTest.assert_equal(itemLastKind, gui.Menu.Updated, "item callback kind");
+
+ # The ghost accessor must reflect the new state.
+ unitTest.assert_equal(resetItem.enabled, 0, "item.enabled after disable");
+ )");
+ CPPUNIT_ASSERT(ok);
+}
+
+// ---------------------------------------------------------------------------
+// Test 3 – dynamic item insertion and removal trigger ChildAdded / ChildRemoved
+// ---------------------------------------------------------------------------
+
+void NasalMenuTests::testDynamicItemAddRemove()
+{
+ bool ok = FGTESTAPI_EXECUTE_NASAL(R"(
+ var fileMenu = _testMenubarGhost.menus[0];
+
+ var events = []; # collect (kind, index) pairs in order
+
+ fileMenu.addChangedCallback(func(kind, index) {
+ append(events, {kind: kind, index: index});
+ });
+
+ var menuNode = props.globals.getNode("/sim/menubar/default/menu[0]");
+
+ # --- add a new item ---
+ # addChild("item") appends item[2] (indices 0 and 1 already exist).
+ var newItemNode = menuNode.addChild("item");
+ newItemNode.getNode("name", 1).setValue("test-new");
+ newItemNode.getNode("label", 1).setValue("Test New");
+
+ unitTest.assert_equal(size(events), 1, "event count after add");
+ unitTest.assert_equal(events[0].kind, gui.xml.Menu.ChildAdded, "add event kind");
+ unitTest.assert_equal(events[0].index, newItemNode.getIndex(), "add event index");
+
+ # The item should now appear in the items vector.
+ unitTest.assert_equal(size(fileMenu.items), 3, "item count after add");
+
+ # --- remove the newly added item ---
+ menuNode.removeChild("item", newItemNode.getIndex());
+
+ unitTest.assert_equal(size(events), 2, "event count after remove");
+ unitTest.assert_equal(events[1].kind, gui.xml.Menu.ChildRemoved, "remove event kind");
+
+ # ChildRemoved fires BEFORE the internal vector is updated, so the
+ # callback should have been invoked while the item was still present.
+ # After the remove returns, the vector must be back to 2.
+ unitTest.assert_equal(size(fileMenu.items), 2, "item count after remove");
+
+ # --- verify ordering: insert at an explicit index between item[0] and item[1] ---
+ # Create item[1] with an index between the two existing items by first
+ # removing item[1], giving item[0] and then re-adding two items.
+ # Simpler: create a fresh menu and verify insertions are ordered.
+ var barNode = props.globals.getNode("/sim/menubar/default");
+ var testMenu2 = barNode.addChild("menu");
+ testMenu2.getNode("name", 1).setValue("test-order-menu");
+
+ var m2ghost = nil;
+ foreach (var m; _testMenubarGhost.menus) {
+ if (m.name == "test-order-menu") { m2ghost = m; break; }
+ }
+ unitTest.assert(m2ghost != nil, "Could not find test-order-menu ghost");
+
+ # Insert item[5] first, then item[2]. The items vector should be
+ # ordered item[2] before item[5].
+ var hi = testMenu2.getChild("item", 5, 1);
+ hi.getNode("name", 1).setValue("test-hi");
+ var lo = testMenu2.getChild("item", 2, 1);
+ lo.getNode("name", 1).setValue("test-lo");
+
+ var orderedItems = m2ghost.items;
+ unitTest.assert_equal(size(orderedItems), 2, "order-test menu item count");
+ unitTest.assert_equal(orderedItems[0].name, "test-lo", "first ordered item should have index 2");
+ unitTest.assert_equal(orderedItems[1].name, "test-hi", "second ordered item should have index 5");
+ )");
+ CPPUNIT_ASSERT(ok);
+}
diff --git a/test_suite/unit_tests/GUI/test_nasalMenu.hxx b/test_suite/unit_tests/GUI/test_nasalMenu.hxx
new file mode 100644
index 000000000..66eecd314
--- /dev/null
+++ b/test_suite/unit_tests/GUI/test_nasalMenu.hxx
@@ -0,0 +1,30 @@
+/*
+ * SPDX-FileComment: Unit tests for NasalMenu / FGNasalMenuBar
+ * SPDX-FileCopyrightText: 2026 James Turner <ja...@fl...>
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+
+class NasalMenuTests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(NasalMenuTests);
+ CPPUNIT_TEST(testBasicStructure);
+ CPPUNIT_TEST(testUpdateCallback);
+ CPPUNIT_TEST(testDynamicItemAddRemove);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void setUp();
+ void tearDown();
+
+ void testBasicStructure();
+ void testUpdateCallback();
+ void testDynamicItemAddRemove();
+
+private:
+};
|
|
From: <fli...@li...> - 2026-04-19 08:01:12
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new 15c476df Revert "Minimal change to unbreak FG while flightgear!467 is being reviewed"
15c476df is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/15c476dff50339d45016f1a7eeb4eecdae2ead51/
Commit: 15c476dff50339d45016f1a7eeb4eecdae2ead51
Author: Florent Rougon
Committer: Florent Rougon
AuthorDate: Sun Apr 19 09:36:08 2026 +0200
Revert "Minimal change to unbreak FG while flightgear!467 is being reviewed"
This reverts commit 13430e600ac04cbc60ee9a9949c16a54bda02d74, which is
not needed anymore.
---
simgear/misc/ResourceManager.hxx | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/simgear/misc/ResourceManager.hxx b/simgear/misc/ResourceManager.hxx
index 1c3e71fc..a7368ae9 100644
--- a/simgear/misc/ResourceManager.hxx
+++ b/simgear/misc/ResourceManager.hxx
@@ -82,10 +82,7 @@ public:
virtual ~ResourceProvider();
- virtual std::vector<SGPath> findAllOfType(ResourceManager::FileType type) const
- {
- return {}; // temporary workaround to let FG compile
- }
+ virtual std::vector<SGPath> findAllOfType(ResourceManager::FileType type) const = 0;
virtual ResourceManager::Priority priority() const
{
|
|
From: <fli...@li...> - 2026-04-18 07:08:12
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new 369166f3d Implement base path retrieval API for resource providers
369166f3d is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/369166f3dbcea1a4a312ce2afacc25dfa80a80c7/
Commit: 369166f3dbcea1a4a312ce2afacc25dfa80a80c7
Author: Frederic Türpe
Committer: Frederic Türpe
AuthorDate: Sat Apr 18 09:08:04 2026 +0200
Implement base path retrieval API for resource providers
---
src/AIModel/AIManager.cxx | 2 +-
src/Add-ons/AddonManager.cxx | 13 ++++++++++---
src/Add-ons/AddonManager.hxx | 3 +--
src/Add-ons/AddonResourceProvider.cxx | 9 +++++++++
src/Add-ons/AddonResourceProvider.hxx | 1 +
src/GUI/LocalAircraftCache.cxx | 12 ++++++++++++
src/GUI/new_gui.cxx | 1 +
src/Main/globals.cxx | 21 ++++++++++++++++++---
8 files changed, 53 insertions(+), 9 deletions(-)
diff --git a/src/AIModel/AIManager.cxx b/src/AIModel/AIManager.cxx
index a8a16f9ad..492b9718c 100644
--- a/src/AIModel/AIManager.cxx
+++ b/src/AIModel/AIManager.cxx
@@ -16,6 +16,7 @@
#include <simgear/structure/commands.hxx>
#include <simgear/structure/exception.hxx>
+#include <Add-ons/Addon.hxx>
#include <Add-ons/AddonManager.hxx>
#include <Airports/airport.hxx>
#include <Main/fg_props.hxx>
@@ -29,7 +30,6 @@
#include "AIEscort.hxx"
#include "AIGroundVehicle.hxx"
#include "AIManager.hxx"
-#include "AIMultiplayer.hxx"
#include "AIShip.hxx"
#include "AIStatic.hxx"
#include "AIStorm.hxx"
diff --git a/src/Add-ons/AddonManager.cxx b/src/Add-ons/AddonManager.cxx
index 3334fe512..15b2b4f96 100644
--- a/src/Add-ons/AddonManager.cxx
+++ b/src/Add-ons/AddonManager.cxx
@@ -8,7 +8,6 @@
#include "config.h"
-#include <algorithm>
#include <memory>
#include <string>
#include <utility>
@@ -37,9 +36,8 @@
namespace strutils = simgear::strutils;
using std::string;
-using std::vector;
-using std::shared_ptr;
using std::unique_ptr;
+using std::vector;
namespace flightgear
{
@@ -267,6 +265,15 @@ AddonManager::addonBasePath(const string& addonId) const
return getAddon(addonId)->getBasePath();
}
+PathList AddonManager::addonBasePaths() const
+{
+ PathList paths;
+ for (const auto& element : _idToAddonMap) {
+ paths.push_back(element.second->getBasePath());
+ }
+ return paths;
+}
+
SGPropertyNode_ptr AddonManager::addonNode(const string& addonId) const
{
return getAddon(addonId)->getAddonNode();
diff --git a/src/Add-ons/AddonManager.hxx b/src/Add-ons/AddonManager.hxx
index 603adb49c..a7acb5da1 100644
--- a/src/Add-ons/AddonManager.hxx
+++ b/src/Add-ons/AddonManager.hxx
@@ -17,8 +17,6 @@
#include <simgear/props/props.hxx>
#include "addon_fwd.hxx"
-#include "Addon.hxx"
-#include "AddonVersion.hxx"
namespace flightgear
{
@@ -70,6 +68,7 @@ public:
AddonRef getAddon(const std::string& addonId) const;
AddonVersionRef addonVersion(const std::string& addonId) const;
SGPath addonBasePath(const std::string& addonId) const;
+ std::vector<SGPath> addonBasePaths() const;
// Base node pertaining to the add-on in the Global Property Tree
SGPropertyNode_ptr addonNode(const std::string& addonId) const;
diff --git a/src/Add-ons/AddonResourceProvider.cxx b/src/Add-ons/AddonResourceProvider.cxx
index b94c70e65..d33b54df2 100644
--- a/src/Add-ons/AddonResourceProvider.cxx
+++ b/src/Add-ons/AddonResourceProvider.cxx
@@ -62,6 +62,15 @@ ResourceProvider::resolve(const string& resource, SGPath& context) const
return SGPath(candidate).validate(/* write */ false);
}
+std::vector<SGPath> ResourceProvider::findAllOfType(simgear::ResourceManager::FileType type) const
+{
+ std::vector<SGPath> paths;
+ for (const SGPath& path : AddonManager::instance()->addonBasePaths()) {
+ findAllOfTypeHelper(path, type, paths);
+ }
+ return paths;
+}
+
} // of namespace addons
} // of namespace flightgear
diff --git a/src/Add-ons/AddonResourceProvider.hxx b/src/Add-ons/AddonResourceProvider.hxx
index 1c65566c3..4e3fec703 100644
--- a/src/Add-ons/AddonResourceProvider.hxx
+++ b/src/Add-ons/AddonResourceProvider.hxx
@@ -26,6 +26,7 @@ public:
virtual SGPath resolve(const std::string& resource, SGPath& context) const
override;
+ std::vector<SGPath> findAllOfType(simgear::ResourceManager::FileType type) const override;
};
} // of namespace addons
diff --git a/src/GUI/LocalAircraftCache.cxx b/src/GUI/LocalAircraftCache.cxx
index 5a00d2f00..2cf63bcff 100644
--- a/src/GUI/LocalAircraftCache.cxx
+++ b/src/GUI/LocalAircraftCache.cxx
@@ -23,6 +23,8 @@
#include <Main/sentryIntegration.hxx>
#include <simgear/misc/ResourceManager.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
@@ -324,6 +326,11 @@ public:
_currentAircraftPath = p;
}
+ std::vector<SGPath> findAllOfType(simgear::ResourceManager::FileType type) const override
+ {
+ return {};
+ }
+
private:
SGPath _currentScanPath;
SGPath _currentAircraftPath;
@@ -355,6 +362,11 @@ public:
return SGPath{};
}
+
+ std::vector<SGPath> findAllOfType(simgear::ResourceManager::FileType type) const override
+ {
+ return {};
+ }
};
class AircraftScanThread : public QThread
diff --git a/src/GUI/new_gui.cxx b/src/GUI/new_gui.cxx
index e11f49af9..19b3d2fc9 100644
--- a/src/GUI/new_gui.cxx
+++ b/src/GUI/new_gui.cxx
@@ -25,6 +25,7 @@
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
+#include <Add-ons/Addon.hxx>
#include <Add-ons/AddonManager.hxx>
#include <Main/fg_props.hxx>
#include <Main/sentryIntegration.hxx>
diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx
index 3c88e3ef1..db6985b79 100644
--- a/src/Main/globals.cxx
+++ b/src/Main/globals.cxx
@@ -50,7 +50,6 @@
#include "globals.hxx"
#include "locale.hxx"
-#include "fg_io.hxx"
#include "fg_props.hxx"
class AircraftResourceProvider : public simgear::ResourceProvider
@@ -60,7 +59,7 @@ public:
{
}
- virtual SGPath resolve(const std::string& aResource, SGPath&) const
+ virtual SGPath resolve(const std::string& aResource, SGPath&) const override
{
string_list pieces(sgPathBranchSplit(aResource));
if ((pieces.size() < 3) || (pieces.front() != "Aircraft")) {
@@ -101,6 +100,15 @@ public:
return SGPath(); // not found
}
+
+ virtual std::vector<SGPath> findAllOfType(simgear::ResourceManager::FileType type) const override
+ {
+ std::vector<SGPath> paths;
+ for (const SGPath& path : globals->get_aircraft_paths()) {
+ findAllOfTypeHelper(path, type, paths);
+ }
+ return paths;
+ }
};
class CurrentAircraftDirProvider : public simgear::ResourceProvider
@@ -110,12 +118,19 @@ public:
{
}
- virtual SGPath resolve(const std::string& aResource, SGPath&) const
+ virtual SGPath resolve(const std::string& aResource, SGPath&) const override
{
SGPath p = SGPath::fromUtf8(fgGetString("/sim/aircraft-dir"));
p.append(aResource);
return p.exists() ? p : SGPath();
}
+
+ virtual std::vector<SGPath> findAllOfType(simgear::ResourceManager::FileType type) const override
+ {
+ std::vector<SGPath> paths;
+ findAllOfTypeHelper(SGPath::fromUtf8(fgGetString("/sim/aircraft-dir")), type, paths);
+ return paths;
+ }
};
////////////////////////////////////////////////////////////////////////
|
|
From: <fli...@li...> - 2026-04-17 09:49:49
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new fb6cb9fb Add resource manager API to retrieve all base paths used by the individual resource providers
fb6cb9fb is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/fb6cb9fb2a3c4e06a1cff3c623b7d98859f21f1b/
Commit: fb6cb9fb2a3c4e06a1cff3c623b7d98859f21f1b
Author: Frederic Türpe
Committer: Frederic Türpe
AuthorDate: Mon Apr 13 17:57:13 2026 +0200
Add resource manager API to retrieve all base paths used by the individual resource providers
---
simgear/misc/ResourceManager.cxx | 100 ++++++++++++++++++++++++++++++++-------
simgear/misc/ResourceManager.hxx | 23 +++++++--
2 files changed, 104 insertions(+), 19 deletions(-)
diff --git a/simgear/misc/ResourceManager.cxx b/simgear/misc/ResourceManager.cxx
index 9589a231..fa96963f 100644
--- a/simgear/misc/ResourceManager.cxx
+++ b/simgear/misc/ResourceManager.cxx
@@ -6,29 +6,81 @@
* @brief manage finding resources by names/paths
*/
-#include <assert.h>
#include <algorithm>
+#include <cassert>
#include <mutex>
+#include <vector>
-#include <simgear_config.h>
-
-#include <simgear/misc/ResourceManager.hxx>
+#include <simgear/debug/debug_types.h>
#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/ResourceManager.hxx>
+#include <simgear/misc/sg_dir.hxx>
+#include <simgear/misc/sg_path.hxx>
namespace simgear
{
-
+
static inline std::mutex static_manager_mutex;
static ResourceManager* static_manager = nullptr;
+std::ostream& operator<<(std::ostream& stream, ResourceManager::FileType type)
+{
+ switch (type) {
+ case ResourceManager::FileType::Font:
+ stream << "Font";
+ break;
+ default:
+ stream << "Unknown";
+ }
+ return stream;
+}
+
ResourceProvider::~ResourceProvider()
{
// pin to this compilation unit
}
+void ResourceProvider::findAllOfTypeHelper(
+ SGPath path, ResourceManager::FileType type,
+ std::vector<SGPath>& result) const
+{
+ if (!path.exists()) {
+ return;
+ }
+ switch (type) {
+ case ResourceManager::FileType::Font:
+ path.append("Fonts");
+ break;
+ default:
+ SG_LOG(SG_IO, SG_DEV_WARN, "ResourceManager::findAllOfType: type '" << type << "' not handled");
+ return;
+ }
+ findAllOfTypeHelper(Dir(path), type, result);
+}
+
+void ResourceProvider::findAllOfTypeHelper(
+ const Dir& dir, ResourceManager::FileType type,
+ std::vector<SGPath>& result) const
+{
+ if (!dir.exists()) {
+ return;
+ }
+ for (const auto& c : dir.children()) {
+ if (c.isDir()) {
+ findAllOfTypeHelper(c, type, result);
+ } else if (c.isFile()) {
+ const std::string suffix = c.complete_lower_extension();
+ if (type == ResourceManager::FileType::Font) {
+ if (suffix == "ttf" || suffix == "otf") {
+ result.push_back(c);
+ }
+ }
+ }
+ }
+}
+
ResourceManager::ResourceManager()
{
-
}
ResourceManager* ResourceManager::instance()
@@ -37,9 +89,9 @@ ResourceManager* ResourceManager::instance()
if (!static_manager) {
static_manager = new ResourceManager();
}
-
+
return static_manager;
-}
+}
bool ResourceManager::haveInstance()
{
@@ -52,8 +104,8 @@ ResourceManager::~ResourceManager()
const std::lock_guard<std::mutex> lock(static_manager_mutex);
assert(this == static_manager);
static_manager = nullptr;
- std::for_each(_providers.begin(), _providers.end(),
- [](ResourceProvider* p) { delete p; });
+ std::for_each(_providers.begin(), _providers.end(),
+ [](ResourceProvider* p) { delete p; });
}
void ResourceManager::reset()
@@ -75,16 +127,22 @@ public:
ResourceProvider(aPriority),
_base(aBase)
{
-
}
-
- virtual SGPath resolve(const std::string& aResource, SGPath&) const
+
+ virtual PathList findAllOfType(ResourceManager::FileType type) const override
+ {
+ std::vector<SGPath> paths;
+ findAllOfTypeHelper(_base, type, paths);
+ return paths;
+ }
+
+ virtual SGPath resolve(const std::string& aResource, SGPath&) const override
{
SGPath p(_base, aResource);
return p.exists() ? p : SGPath();
}
private:
- SGPath _base;
+ SGPath _base;
};
void ResourceManager::addBasePath(const SGPath& aPath, Priority aPriority)
@@ -103,7 +161,7 @@ void ResourceManager::addProvider(ResourceProvider* aProvider)
return;
}
}
-
+
// fell out of the iteration, goes to the end of the vec
_providers.push_back(aProvider);
}
@@ -113,7 +171,7 @@ void ResourceManager::removeProvider(ResourceProvider* aProvider)
assert(aProvider);
auto it = std::find(_providers.begin(), _providers.end(), aProvider);
if (it == _providers.end()) {
- SG_LOG(SG_GENERAL, SG_DEV_ALERT, "unknown provider doing remove");
+ SG_LOG(SG_GENERAL, SG_DEV_ALERT, "Cannot remove unregistered resource provider");
return;
}
@@ -151,4 +209,14 @@ SGPath ResourceManager::findPath(const std::string& aResource, SGPath aContext)
return SGPath();
}
+std::vector<SGPath> ResourceManager::findAllOfType(FileType type)
+{
+ std::vector<SGPath> paths;
+ for (const auto& provider : _providers) {
+ std::vector<SGPath> foundPaths = provider->findAllOfType(type);
+ paths.insert(paths.end(), foundPaths.begin(), foundPaths.end());
+ }
+ return paths;
+}
+
} // of namespace simgear
diff --git a/simgear/misc/ResourceManager.hxx b/simgear/misc/ResourceManager.hxx
index e519f8ba..a7368ae9 100644
--- a/simgear/misc/ResourceManager.hxx
+++ b/simgear/misc/ResourceManager.hxx
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
-// SPDX-File-CopyrightText: 2010 James Turner <ja...@fl...>
+// SPDX-FileCopyrightText: 2010 James Turner <ja...@fl...>
/**
* @file
@@ -9,8 +9,10 @@
#ifndef SG_RESOURCE_MANAGER_HXX
#define SG_RESOURCE_MANAGER_HXX
+#include <iosfwd>
#include <vector>
+#include <simgear/misc/sg_dir.hxx>
#include <simgear/misc/sg_path.hxx>
namespace simgear
@@ -33,6 +35,10 @@ public:
PRIORITY_HIGH = 1000
} Priority;
+ enum class FileType {
+ Font,
+ };
+
static ResourceManager* instance();
static bool haveInstance();
@@ -58,6 +64,7 @@ public:
* against (e.g a current directory)
*/
SGPath findPath(const std::string& aResource, SGPath aContext = SGPath());
+ std::vector<SGPath> findAllOfType(FileType type);
private:
ResourceManager();
@@ -66,6 +73,8 @@ private:
ProviderVec _providers;
};
+std::ostream& operator<<(std::ostream& stream, ResourceManager::FileType type);
+
class ResourceProvider
{
public:
@@ -73,17 +82,25 @@ public:
virtual ~ResourceProvider();
+ virtual std::vector<SGPath> findAllOfType(ResourceManager::FileType type) const = 0;
+
virtual ResourceManager::Priority priority() const
{
return _priority;
}
protected:
- ResourceProvider(ResourceManager::Priority aPriority) :
- _priority(aPriority)
+ ResourceProvider(ResourceManager::Priority aPriority) : _priority(aPriority)
{}
+ void findAllOfTypeHelper(
+ SGPath path, ResourceManager::FileType type,
+ std::vector<SGPath>& result) const;
+
ResourceManager::Priority _priority = ResourceManager::PRIORITY_DEFAULT;
+
+private:
+ void findAllOfTypeHelper(const Dir& dir, ResourceManager::FileType type, std::vector<SGPath>& result) const;
};
} // of simgear namespace
|
|
From: <fli...@li...> - 2026-04-17 07:53:21
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new b0bb5878 Fix for c-ares compatbility breakage in the v1.34 branch
b0bb5878 is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/b0bb58785a0443c5631508188e216973b4a3484d/
Commit: b0bb58785a0443c5631508188e216973b4a3484d
Author: Florent Rougon
Committer: Florent Rougon
AuthorDate: Thu Apr 16 17:44:39 2026 +0200
Fix for c-ares compatbility breakage in the v1.34 branch
Compatibility was broken by c-ares commit 6475221a42739[1]. Use a custom
type `simgear::DNS::cares_char_type` whose definition depends on c-ares
type `ares_callback` in order to have our code build and work before as
well as after the c-ares change.
Issue-Id: flightgear/simgear#45
[1] https://github.com/c-ares/c-ares/commit/6475221a427394b6d2a3d3cb0b0abe189681ddd4
---
simgear/io/DNSClient_cares.cxx | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/simgear/io/DNSClient_cares.cxx b/simgear/io/DNSClient_cares.cxx
index f52ad5c4..28c20fd6 100644
--- a/simgear/io/DNSClient_cares.cxx
+++ b/simgear/io/DNSClient_cares.cxx
@@ -4,6 +4,7 @@
#include <simgear_config.h>
#include <algorithm>
+#include <type_traits>
#include "DNSClient.hxx"
#include <ares.h>
@@ -28,6 +29,22 @@ namespace DNS {
#define ARES_REC_TYPE_TXT 16
#endif
+// Compatibility breakage from c-ares commit 6475221a427394b6d2a3d3cb0b0abe18:
+// the fourth argument of functions of type 'ares_callback' was changed from
+// 'unsigned char*' to 'const unsigned char*'.
+//
+// TODO: use ARES_VERSION for this when it becomes possible. At the time of
+// this writing, c-ares v1.34.6 uses 'unsigned char*'; more recent commits in
+// the v1.34 branch use 'const unsigned char*', however v1.34.7 hasn't been
+// released yet.
+using cares_char_type =
+ std::conditional<
+ std::is_same_v<ares_callback,
+ void (*)(void*, int, int, unsigned char*, int)>,
+ unsigned char,
+ const unsigned char>::type;
+
+
class Client::ClientPrivate {
public:
ClientPrivate(const std::string& nameserver)
@@ -84,7 +101,8 @@ public:
request);
}
- static void callback(void* arg, int status, int timeouts, unsigned char* abuf, int alen) {
+ static void callback(void* arg, int status, int timeouts, cares_char_type* abuf, int alen)
+ {
Request* r = static_cast<Request*>(arg);
if (status != ARES_SUCCESS) {
@@ -110,8 +128,8 @@ public:
r->setComplete(true);
}
- static void parse_NAPTR( unsigned char * abuf, int alen, NAPTRRequest * record ) {
-
+ static void parse_NAPTR(cares_char_type* abuf, int alen, NAPTRRequest* record)
+ {
struct ares_naptr_reply* naptr_out;
int result = ares_parse_naptr_reply(abuf, alen, &naptr_out);
if (result != ARES_SUCCESS) {
@@ -147,7 +165,7 @@ public:
ares_free_data(naptr_out);
}
- static void parse_SRV(unsigned char* abuf, int alen, SRVRequest* record)
+ static void parse_SRV(cares_char_type* abuf, int alen, SRVRequest* record)
{
struct ares_srv_reply* srv_out;
int result = ares_parse_srv_reply(abuf, alen, &srv_out);
@@ -173,7 +191,7 @@ public:
ares_free_data(srv_out);
}
- static void parse_TXT(unsigned char* abuf, int alen, TXTRequest* record)
+ static void parse_TXT(cares_char_type* abuf, int alen, TXTRequest* record)
{
struct ares_txt_reply* txt_out;
int result = ares_parse_txt_reply(abuf, alen, &txt_out);
|
|
From: <fli...@li...> - 2026-04-15 20:30:39
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new 13430e60 Minimal change to unbreak FG while flightgear!467 is being reviewed
13430e60 is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/13430e600ac04cbc60ee9a9949c16a54bda02d74/
Commit: 13430e600ac04cbc60ee9a9949c16a54bda02d74
Author: Florent Rougon
Committer: Florent Rougon
AuthorDate: Wed Apr 15 21:18:18 2026 +0200
Minimal change to unbreak FG while flightgear!467 is being reviewed
---
simgear/misc/ResourceManager.hxx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/simgear/misc/ResourceManager.hxx b/simgear/misc/ResourceManager.hxx
index a7368ae9..1c3e71fc 100644
--- a/simgear/misc/ResourceManager.hxx
+++ b/simgear/misc/ResourceManager.hxx
@@ -82,7 +82,10 @@ public:
virtual ~ResourceProvider();
- virtual std::vector<SGPath> findAllOfType(ResourceManager::FileType type) const = 0;
+ virtual std::vector<SGPath> findAllOfType(ResourceManager::FileType type) const
+ {
+ return {}; // temporary workaround to let FG compile
+ }
virtual ResourceManager::Priority priority() const
{
|
|
From: <fli...@li...> - 2026-04-15 05:49:49
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new aab57efa5 refactor input classes
aab57efa5 is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/aab57efa5414697e774953eeed825cf255b8dd13/
Commit: aab57efa5414697e774953eeed825cf255b8dd13
Author: James Turner
Committer: James Turner
AuthorDate: Fri Apr 10 12:40:46 2026 +0100
refactor input classes
---
src/Input/CMakeLists.txt | 18 +-
src/Input/FGAxisEvent.cxx | 173 +++++
src/Input/FGAxisEvent.hxx | 85 +++
src/Input/FGButtonEvent.cxx | 201 ++++++
src/Input/FGButtonEvent.hxx | 74 ++
src/Input/FGEventInput.cxx | 749 +-------------------
src/Input/FGEventInput.hxx | 324 +--------
src/Input/{FGHIDEventInput.cxx => FGHIDDevice.cxx} | 271 +------
src/Input/FGHIDDevice.hxx | 123 ++++
src/Input/FGHIDEventInput.cxx | 781 +--------------------
src/Input/FGInputDevice.cxx | 173 +++++
src/Input/FGInputDevice.hxx | 121 ++++
src/Input/FGInputEvent.cxx | 84 +++
src/Input/FGInputEvent.hxx | 92 +++
src/Input/FGReportSetting.cxx | 163 +++++
...GEventInput_private.hxx => FGReportSetting.hxx} | 23 +-
16 files changed, 1348 insertions(+), 2107 deletions(-)
diff --git a/src/Input/CMakeLists.txt b/src/Input/CMakeLists.txt
index 574245750..cde72863e 100644
--- a/src/Input/CMakeLists.txt
+++ b/src/Input/CMakeLists.txt
@@ -13,8 +13,8 @@ else()
endif()
if (ENABLE_HID_INPUT)
- list(APPEND EVENT_INPUT_SOURCES FGHIDEventInput.cxx FGHIDUsage.cxx)
- list(APPEND EVENT_INPUT_HEADERS FGHIDEventInput.hxx FGHIDUsage.hxx)
+ list(APPEND EVENT_INPUT_SOURCES FGHIDEventInput.cxx FGHIDUsage.cxx FGHIDDevice.cxx)
+ list(APPEND EVENT_INPUT_HEADERS FGHIDEventInput.hxx FGHIDUsage.hxx FGHIDDevice.hxx)
endif()
set(SOURCES
@@ -22,6 +22,11 @@ set(SOURCES
FGCommonInput.cxx
FGDeviceConfigurationMap.cxx
FGEventInput.cxx
+ FGInputEvent.cxx
+ FGButtonEvent.cxx
+ FGAxisEvent.cxx
+ FGInputDevice.cxx
+ FGReportSetting.cxx
FGKeyboardInput.cxx
FGMouseInput.cxx
input.cxx
@@ -32,6 +37,11 @@ set(HEADERS
FGCommonInput.hxx
FGDeviceConfigurationMap.hxx
FGEventInput.hxx
+ FGInputEvent.hxx
+ FGButtonEvent.hxx
+ FGAxisEvent.hxx
+ FGInputDevice.hxx
+ FGReportSetting.hxx
FGKeyboardInput.hxx
FGMouseInput.hxx
input.hxx
@@ -77,7 +87,9 @@ endif()
if (ENABLE_HID_INPUT)
if (COMMAND flightgear_test)
set(HID_INPUT_TEST_SOURCES test_hidinput.cxx FGEventInput.cxx
- FGCommonInput.cxx FGDeviceConfigurationMap.cxx)
+ FGCommonInput.cxx FGDeviceConfigurationMap.cxx
+ FGInputEvent.cxx FGButtonEvent.cxx FGAxisEvent.cxx
+ FGInputDevice.cxx FGReportSetting.cxx)
flightgear_test(hidinput "${HID_INPUT_TEST_SOURCES}")
target_link_libraries(hidinput ${EVENT_INPUT_LIBRARIES} hidapi)
diff --git a/src/Input/FGAxisEvent.cxx b/src/Input/FGAxisEvent.cxx
new file mode 100644
index 000000000..bda22f323
--- /dev/null
+++ b/src/Input/FGAxisEvent.cxx
@@ -0,0 +1,173 @@
+// FGAxisEvent.cxx -- axis input event classes (absolute, relative)
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Torsten Dreyer
+
+#include "FGAxisEvent.hxx"
+
+#include <simgear/math/SGMath.hxx>
+#include <simgear/math/interpolater.hxx>
+#include <simgear/structure/exception.hxx>
+
+FGAxisEvent::FGAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGInputEvent(device, eventNode)
+{
+ tolerance = eventNode->getDoubleValue("tolerance", 0.002);
+ minRange = eventNode->getDoubleValue("min-range", 0.0);
+ maxRange = eventNode->getDoubleValue("max-range", 0.0);
+ center = eventNode->getDoubleValue("center", 0.0);
+ deadband = eventNode->getDoubleValue("dead-band", 0.0);
+
+ // interpolation of values
+ if (eventNode->hasChild("interpolater")) {
+ interpolater.reset(new SGInterpTable{eventNode->getChild("interpolater")});
+ mirrorInterpolater = eventNode->getBoolValue("interpolater/mirrored", false);
+ }
+
+ if (eventNode->hasChild("output-mode")) {
+ const auto s = eventNode->getStringValue("output-mode");
+ if (s == "signed-normalized") {
+ _outputMode = OutputMode::SignedNormalized;
+ } else if (s == "unsigned-normalized") {
+ _outputMode = OutputMode::UnsignedNormalized;
+ } else if (s == "direct") {
+ _outputMode = OutputMode::Direct;
+ } else {
+ throw sg_io_exception("Invalid output mode:" + s, sg_location(eventNode));
+ }
+ }
+
+ if (eventNode->hasChild("invert")) {
+ _invert = eventNode->getBoolValue("invert", false);
+ }
+
+ if (eventNode->hasChild("low")) {
+ _lowButton = ButtonEvent_ptr(new FGButtonEvent(device, eventNode->getChild("low")));
+ }
+
+ if (eventNode->hasChild("high")) {
+ _highButton = ButtonEvent_ptr(new FGButtonEvent(device, eventNode->getChild("high")));
+ }
+
+ setDefaultThresholds();
+ if (eventNode->hasChild("low-threshold") || eventNode->hasChild("high-threshold")) {
+ lowThreshold = eventNode->getDoubleValue("low-threshold", lowThreshold);
+ highThreshold = eventNode->getDoubleValue("high-threshold", highThreshold);
+ }
+}
+
+void FGAxisEvent::setDefaultThresholds()
+{
+ if (_outputMode == OutputMode::SignedNormalized) {
+ lowThreshold = -0.9;
+ highThreshold = 0.9;
+ } else if (_outputMode == OutputMode::UnsignedNormalized) {
+ lowThreshold = 0.1;
+ highThreshold = 0.9;
+ }
+}
+
+void FGAxisEvent::SetDefaultRange(double min, double max)
+{
+ if ((minRange == 0.0) && (maxRange == 0.0)) {
+ minRange = min;
+ maxRange = max;
+ }
+}
+
+FGAxisEvent::~FGAxisEvent() = default;
+
+void FGAxisEvent::update(double dt)
+{
+ FGInputEvent::update(dt);
+ // ensure buttons repeat, since this common for hats
+ if (_lowButton) {
+ _lowButton->update(dt);
+ }
+ if (_highButton) {
+ _highButton->update(dt);
+ }
+}
+
+void FGAxisEvent::fire(FGEventData& eventData)
+{
+ if (fabs(eventData.value - lastValue) < tolerance)
+ return;
+ lastValue = eventData.value;
+
+ // We need a copy of the FGEventData struct to set the new value and to avoid side effects
+ FGEventData ed = eventData;
+ ed.value = computeValue(lastValue);
+
+ if (interpolater) {
+ if ((ed.value < 0.0) && mirrorInterpolater) {
+ // mirror the positive interpolation for negative values
+ ed.value = -interpolater->interpolate(fabs(ed.value));
+ } else {
+ ed.value = interpolater->interpolate(ed.value);
+ }
+ }
+
+ FGInputEvent::fire(ed);
+ const auto v = ed.value;
+ if (_lowButton) {
+ ed.value = (v < lowThreshold) ? 1.0 : 0.0;
+ _lowButton->fire(ed);
+ }
+
+ if (_highButton) {
+ ed.value = (v > highThreshold) ? 1.0 : 0.0;
+ _highButton->fire(ed);
+ }
+}
+
+double FGAxisEvent::computeValue(double rawValue) const
+{
+ const double usedMinRange = minRange;
+ const double usedMaxRange = maxRange;
+
+ SG_CLAMP_RANGE(rawValue, usedMinRange, usedMaxRange);
+ const auto range = usedMaxRange - usedMinRange;
+
+ double value = rawValue;
+ // normalize to -1.0 ... 1.0
+ if (_outputMode == OutputMode::SignedNormalized) {
+ value = (2.0 * (rawValue - usedMinRange) / range) - 1.0;
+ if (_invert) {
+ value = -value;
+ }
+
+ // apply deadband around center position
+ if (fabs(value - center) < deadband) {
+ value = center;
+ }
+ } else if (_outputMode == OutputMode::UnsignedNormalized) {
+ value = (rawValue - usedMinRange) / range;
+ if (_invert) {
+ value = 1.0 - value;
+ }
+ } else if (_outputMode == OutputMode::Direct) {
+ if (_invert) {
+ value = maxRange - (rawValue - minRange);
+ }
+ }
+
+ return value;
+}
+
+void FGAbsAxisEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
+{
+ // sets the "setting" node
+ binding->fire(eventData.value);
+}
+
+FGRelAxisEvent::FGRelAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGAxisEvent(device, eventNode)
+{
+ // relative axes can't use tolerance
+ tolerance = 0.0;
+}
+
+void FGRelAxisEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
+{
+ // sets the "offset" node
+ binding->fire(eventData.value, 1.0);
+}
diff --git a/src/Input/FGAxisEvent.hxx b/src/Input/FGAxisEvent.hxx
new file mode 100644
index 000000000..949c05542
--- /dev/null
+++ b/src/Input/FGAxisEvent.hxx
@@ -0,0 +1,85 @@
+// FGAxisEvent.hxx -- axis input event classes (absolute, relative)
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Torsten Dreyer
+
+#pragma once
+
+#include "FGButtonEvent.hxx"
+#include "FGInputEvent.hxx"
+
+#include <limits>
+#include <memory>
+
+class SGInterpTable;
+
+/// TODO: document
+class FGAxisEvent : public FGInputEvent
+{
+public:
+ FGAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode);
+ ~FGAxisEvent();
+
+ void update(double dt) override;
+
+ void SetRange(double min, double max)
+ {
+ minRange = min;
+ maxRange = max;
+ }
+
+ /**
+ * @brief set the range based on system data (eg, HID descriptor logical range)
+ * only used if the config node didn't define range data
+ */
+ void SetDefaultRange(double min, double max);
+
+ enum class OutputMode {
+ SignedNormalized, ///< output in range [-1.0, 1.0], with center at 0.0
+ UnsignedNormalized, ///< output in range [0.0, 1.0],
+ Direct
+ };
+
+protected:
+ void fire(FGEventData& eventData) override;
+
+ double computeValue(double rawValue) const;
+ void setDefaultThresholds();
+
+ double tolerance = 0.0;
+ double minRange = 0.0;
+ double maxRange = 0.0;
+ double center = 0.0;
+ double deadband = 0.0;
+ double lowThreshold = 0.0;
+ double highThreshold = 0.0;
+ double lastValue = std::numeric_limits<double>::quiet_NaN();
+
+ std::unique_ptr<SGInterpTable> interpolater;
+ bool mirrorInterpolater = false;
+
+ bool _invert = false;
+ OutputMode _outputMode = OutputMode::SignedNormalized;
+
+ ButtonEvent_ptr _lowButton, _highButton;
+};
+
+/// TODO: document
+class FGRelAxisEvent : public FGAxisEvent
+{
+public:
+ FGRelAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode);
+
+protected:
+ void fire(SGAbstractBinding* binding, FGEventData& eventData) override;
+};
+
+/// TODO: document
+class FGAbsAxisEvent : public FGAxisEvent
+{
+public:
+ FGAbsAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGAxisEvent(device, eventNode) {}
+
+protected:
+ void fire(SGAbstractBinding* binding, FGEventData& eventData) override;
+};
diff --git a/src/Input/FGButtonEvent.cxx b/src/Input/FGButtonEvent.cxx
new file mode 100644
index 000000000..2a82410d2
--- /dev/null
+++ b/src/Input/FGButtonEvent.cxx
@@ -0,0 +1,201 @@
+// FGButtonEvent.cxx -- button and extended-button input event classes
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Torsten Dreyer
+
+#include "FGButtonEvent.hxx"
+
+#include "FGInputDevice.hxx"
+#include <simgear/structure/exception.hxx>
+
+#include <Main/fg_props.hxx>
+
+using std::string;
+
+FGButtonEvent::FGButtonEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGInputEvent(device, eventNode),
+ repeatable(false),
+ lastState(false)
+{
+ repeatable = eventNode->getBoolValue("repeatable", repeatable);
+ if (eventNode->hasChild("output-mode")) {
+ const auto s = eventNode->getStringValue("output-mode");
+ if (s == "button") {
+ _outputMode = OutputMode::Button;
+ } else if (s == "switch") {
+ _outputMode = OutputMode::Switch;
+ } else {
+ throw sg_io_exception("Invalid output mode:" + s, sg_location(eventNode));
+ }
+ }
+
+ if (_outputMode == OutputMode::Switch) {
+ if (repeatable) {
+ throw sg_io_exception("Switch mode doesn't support repeatable events", sg_location(eventNode));
+ }
+ }
+
+ _invert = eventNode->getBoolValue("invert", false);
+}
+
+void FGButtonEvent::fire(FGEventData& eventData)
+{
+ bool pressed = eventData.value > 0.0;
+ if (_invert) {
+ pressed = !pressed;
+ }
+
+ if (_outputMode == OutputMode::Button) {
+ // In button mode, we fire the press event on press, and the mod-up binding on release
+ if (pressed) {
+ // The press event may be repeated.
+ if (!lastState || repeatable) {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been pressed");
+ FGInputEvent::fire(eventData);
+ }
+ } else {
+ // The release event is never repeated.
+ if (lastState) {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been released");
+ eventData.modifiers |= KEYMOD_RELEASED;
+ FGInputEvent::fire(eventData);
+ }
+ }
+ } else if (_outputMode == OutputMode::Switch) {
+ // In switch mode, we fire with value=true on press, and value=false on release
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been " << (pressed ? "pressed" : "released"));
+ eventData.value = pressed ? 1.0 : 0.0;
+ FGInputEvent::fire(eventData);
+ }
+
+ lastState = pressed;
+}
+
+void FGButtonEvent::update(double dt)
+{
+ if (repeatable && lastState) {
+ // interval / dt handling is done by base ::fire method
+ FGEventData ed{1.0, dt, 0 /* modifiers */};
+ FGInputEvent::fire(ed);
+ }
+}
+
+void FGButtonEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
+{
+ SGPropertyNode_ptr args(new SGPropertyNode);
+ args->setBoolValue("value", eventData.value > 0.0);
+ binding->fire(args);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// FGExtendedButtonEvent
+
+FGExtendedButtonEvent::FGExtendedButtonEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode)
+ : FGButtonEvent(device, eventNode)
+{
+ readTimedBindings(eventNode, "mod-double-press", _doublePressBind);
+ readTimedBindings(eventNode, "mod-long-press", _longPressBind);
+
+ if (auto* n = eventNode->getChild("mod-double-press"))
+ _doublePressIntervalSec = readDoubleClickInterval(n);
+ if (auto* n = eventNode->getChild("mod-long-press"))
+ _longPressIntervalSec = readLongPressInterval(n);
+}
+
+void FGExtendedButtonEvent::readTimedBindings(SGPropertyNode_ptr eventNode, const char* nodeName, SGBindingList& bindList)
+{
+ auto* subNode = eventNode->getChild(nodeName);
+ if (!subNode)
+ return;
+ const auto& nasalMod = device->GetNasalModule();
+ for (auto b : subNode->getChildren("binding")) {
+ if (b->getStringValue("command") == "nasal" && !nasalMod.empty()) {
+ b->setStringValue("module", nasalMod);
+ }
+ bindList.push_back(SGAbstractBinding::createFromProps(b, globals->get_props()));
+ }
+}
+
+double FGExtendedButtonEvent::readDoubleClickInterval(SGPropertyNode_ptr subNode) const
+{
+ return subNode->getDoubleValue("interval-sec",
+ fgGetDouble("/sim/input/double-press-sec", 0.4));
+}
+
+double FGExtendedButtonEvent::readLongPressInterval(SGPropertyNode_ptr subNode) const
+{
+ return subNode->getDoubleValue("interval-sec",
+ fgGetDouble("/sim/input/long-press-sec", 0.8));
+}
+
+void FGExtendedButtonEvent::fire(FGEventData& eventData)
+{
+ bool pressed = eventData.value > 0.0;
+ if (_invert) {
+ pressed = !pressed;
+ }
+
+ if (_outputMode == OutputMode::Button) {
+ if (pressed) {
+ // Reset long-press tracking on each new press
+ _pressHeldTime = 0.0;
+ _longPressFired = false;
+
+ if (!lastState || repeatable) {
+ if (_waitingForDoublePress && !_doublePressBind.empty()) {
+ // Second press within the double-press window: fire double-press bindings
+ // and suppress the normal press bindings
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' double-pressed");
+ for (auto& b : _doublePressBind)
+ FGButtonEvent::fire(b.get(), eventData);
+ _timeSinceFirstPress = 0.0;
+ } else {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been pressed");
+ FGInputEvent::fire(eventData);
+ if (!_doublePressBind.empty()) {
+ _waitingForDoublePress = true;
+ _timeSinceFirstPress = 0.0;
+ }
+ }
+ }
+ } else {
+ if (lastState) {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been released");
+ eventData.modifiers |= KEYMOD_RELEASED;
+ FGInputEvent::fire(eventData);
+ _pressHeldTime = 0.0;
+ }
+ }
+ } else if (_outputMode == OutputMode::Switch) {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been " << (pressed ? "pressed" : "released"));
+ eventData.value = pressed ? 1.0 : 0.0;
+ FGInputEvent::fire(eventData);
+ }
+
+ lastState = pressed;
+}
+
+void FGExtendedButtonEvent::update(double dt)
+{
+ FGButtonEvent::update(dt);
+
+ // Double-press timeout: clear the waiting flag once the window expires
+ if (_waitingForDoublePress) {
+ _timeSinceFirstPress += dt;
+ if (_timeSinceFirstPress >= _doublePressIntervalSec) {
+ _waitingForDoublePress = false;
+ _timeSinceFirstPress = 0.0;
+ }
+ }
+
+ // Long-press: fire the long-press bindings once the hold time is exceeded
+ if (lastState && !_longPressBind.empty() && !_longPressFired) {
+ _pressHeldTime += dt;
+ if (_pressHeldTime >= _longPressIntervalSec) {
+ SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' long-pressed");
+ FGEventData ed{1.0, dt, 0 /* modifiers */};
+ for (auto& b : _longPressBind)
+ FGButtonEvent::fire(b.get(), ed);
+ _longPressFired = true;
+ }
+ }
+}
diff --git a/src/Input/FGButtonEvent.hxx b/src/Input/FGButtonEvent.hxx
new file mode 100644
index 000000000..e6f0b0288
--- /dev/null
+++ b/src/Input/FGButtonEvent.hxx
@@ -0,0 +1,74 @@
+// FGButtonEvent.hxx -- button and extended-button input event classes
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Torsten Dreyer
+
+#pragma once
+
+#include "FGInputEvent.hxx"
+
+#include <simgear/structure/SGBinding.hxx>
+
+/// TODO: document
+class FGButtonEvent : public FGInputEvent
+{
+public:
+ FGButtonEvent(FGInputDevice* device, SGPropertyNode_ptr node);
+ void fire(FGEventData& eventData) override;
+
+ void update(double dt) override;
+
+ enum class OutputMode {
+ Button, ///< fire on press, do mod-up binding on release
+ Switch ///< fire with value=true on press, value=false on release
+ };
+
+protected:
+ void fire(SGAbstractBinding* binding, FGEventData& eventData) override;
+
+ bool repeatable;
+ bool lastState;
+
+ bool _invert = false;
+ OutputMode _outputMode = OutputMode::Button;
+};
+
+using ButtonEvent_ptr = SGSharedPtr<FGButtonEvent>;
+
+/**
+ * FGButtonEvent subclass adding double-press and long-press support.
+ *
+ * Created by FGInputEvent::NewObject when @c mod-double-press or
+ * @c mod-long-press child nodes are present on the event node.
+ */
+class FGExtendedButtonEvent : public FGButtonEvent
+{
+public:
+ FGExtendedButtonEvent(FGInputDevice* device, SGPropertyNode_ptr node);
+ void fire(FGEventData& eventData) override;
+ void update(double dt) override;
+
+private:
+ void readTimedBindings(SGPropertyNode_ptr eventNode, const char* nodeName, SGBindingList& bindList);
+ double readDoubleClickInterval(SGPropertyNode_ptr subNode) const;
+ double readLongPressInterval(SGPropertyNode_ptr subNode) const;
+
+ /// Bindings fired on a double-press (second press within _doublePressIntervalSec).
+ /// When defined, the second press does not fire the regular down bindings.
+ SGBindingList _doublePressBind;
+
+ /// Bindings fired when the button has been held for _longPressIntervalSec.
+ /// When defined, the subsequent release does not fire the regular mod-up bindings.
+ SGBindingList _longPressBind;
+
+ double _doublePressIntervalSec = 0.0;
+ double _longPressIntervalSec = 0.0;
+
+ // double-press detection state
+ bool _waitingForDoublePress = false;
+ double _timeSinceFirstPress = 0.0;
+
+ // long-press detection state
+ double _pressHeldTime = 0.0;
+ bool _longPressFired = false;
+};
diff --git a/src/Input/FGEventInput.cxx b/src/Input/FGEventInput.cxx
index 542c0444d..fe0d27153 100644
--- a/src/Input/FGEventInput.cxx
+++ b/src/Input/FGEventInput.cxx
@@ -5,645 +5,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2009 Torsten Dreyer
-#include "Input/FGDeviceConfigurationMap.hxx"
-#include "simgear/debug/debug_types.h"
-#include "simgear/misc/strutils.hxx"
-#include "simgear/nasal/nasal.h"
-#include "simgear/sg_inlines.h"
-#include "simgear/structure/exception.hxx"
-
#include <config.h>
#include "FGEventInput.hxx"
-#include <Main/fg_props.hxx>
-#include <Scripting/NasalSys.hxx>
-#include <cstdint>
-#include <cstring>
-#include <simgear/debug/ErrorReportingCallback.hxx>
-#include <simgear/io/sg_file.hxx>
-#include <simgear/math/SGMath.hxx>
-#include <simgear/math/interpolater.hxx>
-#include <simgear/misc/strutils.hxx>
+
+#include <simgear/debug/debug_types.h>
#include <simgear/props/props_io.hxx>
-#include <utility>
+#include <simgear/structure/exception.hxx>
+
+#include <Main/fg_props.hxx>
-using simgear::PropertyList;
-using std::cout;
-using std::endl;
using std::map;
using std::string;
using namespace std::string_literals;
-FGEventSetting::FGEventSetting(SGPropertyNode_ptr base) : value(0.0)
-{
- SGPropertyNode_ptr n;
-
- if ((n = base->getNode("value")) != NULL) {
- valueNode = NULL;
- value = n->getDoubleValue();
- } else {
- n = base->getNode("property");
- if (n == NULL) {
- SG_LOG(SG_INPUT, SG_WARN, "Neither <value> nor <property> defined for event setting:" << base->getLocation());
- } else {
- valueNode = fgGetNode(n->getStringValue(), true);
- }
- }
-
- if ((n = base->getChild("condition")) != NULL) {
- condition = sgReadCondition(base, n);
- } else {
- simgear::reportFailure(simgear::LoadFailure::Misconfigured,
- simgear::ErrorCode::InputDeviceConfig,
- "No condition for event setting",
- sg_location(base));
- }
-}
-
-double FGEventSetting::GetValue()
-{
- return valueNode == NULL ? value : valueNode->getDoubleValue();
-}
-
-bool FGEventSetting::Test()
-{
- return condition == NULL ? true : condition->test();
-}
-
-static inline bool StartsWith(string& s, const char* cp)
-{
- return s.find(cp) == 0;
-}
-
-FGInputEvent* FGInputEvent::NewObject(FGInputDevice* device, SGPropertyNode_ptr eventNode)
-{
- string name = eventNode->getStringValue("name", "");
- if (StartsWith(name, "button-")) {
- if (eventNode->hasChild("mod-double-press") || eventNode->hasChild("mod-long-press")) {
- return new FGExtendedButtonEvent(device, eventNode);
- }
- return new FGButtonEvent(device, eventNode);
- }
-
- if (StartsWith(name, "rel-"))
- return new FGRelAxisEvent(device, eventNode);
-
- if (StartsWith(name, "abs-"))
- return new FGAbsAxisEvent(device, eventNode);
-
- return new FGInputEvent(device, eventNode);
-}
-
-FGInputEvent::FGInputEvent(FGInputDevice* aDevice, SGPropertyNode_ptr eventNode) : device(aDevice),
- lastDt(0.0),
- lastSettingValue(std::numeric_limits<float>::quiet_NaN())
-{
- name = eventNode->getStringValue("name", "");
- desc = eventNode->getStringValue("desc", "");
- intervalSec = eventNode->getDoubleValue("interval-sec", 0.0);
-
- read_bindings(eventNode, bindings, KEYMOD_NONE, device->GetNasalModule());
-
- for (auto child : eventNode->getChildren("setting"))
- settings.push_back(new FGEventSetting(child));
-}
-
-FGInputEvent::~FGInputEvent() = default;
-
-// send changed value to device (if condition matches)
-void FGInputEvent::update(double dt)
-{
- for (auto setting : settings) {
- if (setting->Test()) {
- const double value = setting->GetValue();
- if (value != lastSettingValue) {
- device->Send(GetName(), value);
- lastSettingValue = value;
- }
- }
- }
-}
-
-void FGInputEvent::fire(FGEventData& eventData)
-{
- lastDt += eventData.dt;
- if (lastDt >= intervalSec) {
- for (auto b : bindings[eventData.modifiers]) {
- fire(b, eventData);
- }
-
- lastDt -= intervalSec;
- }
-}
-
-void FGInputEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
-{
- binding->fire(eventData.value);
-}
-
-FGAxisEvent::FGAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGInputEvent(device, eventNode)
-{
- tolerance = eventNode->getDoubleValue("tolerance", 0.002);
- minRange = eventNode->getDoubleValue("min-range", 0.0);
- maxRange = eventNode->getDoubleValue("max-range", 0.0);
- center = eventNode->getDoubleValue("center", 0.0);
- deadband = eventNode->getDoubleValue("dead-band", 0.0);
-
- // interpolation of values
- if (eventNode->hasChild("interpolater")) {
- interpolater.reset(new SGInterpTable{eventNode->getChild("interpolater")});
- mirrorInterpolater = eventNode->getBoolValue("interpolater/mirrored", false);
- }
-
- if (eventNode->hasChild("output-mode")) {
- const auto s = eventNode->getStringValue("output-mode");
- if (s == "signed-normalized") {
- _outputMode = OutputMode::SignedNormalized;
- } else if (s == "unsigned-normalized") {
- _outputMode = OutputMode::UnsignedNormalized;
- } else if (s == "direct") {
- _outputMode = OutputMode::Direct;
- } else {
- throw sg_io_exception("Invalid output mode:" + s, sg_location(eventNode));
- }
- }
-
- if (eventNode->hasChild("invert")) {
- _invert = eventNode->getBoolValue("invert", false);
- }
-
- if (eventNode->hasChild("low")) {
- _lowButton = ButtonEvent_ptr(new FGButtonEvent(device, eventNode->getChild("low")));
- }
-
- if (eventNode->hasChild("high")) {
- _highButton = ButtonEvent_ptr(new FGButtonEvent(device, eventNode->getChild("high")));
- }
-
- setDefaultThresholds();
- if (eventNode->hasChild("low-threshold") || eventNode->hasChild("high-threshold")) {
- lowThreshold = eventNode->getDoubleValue("low-threshold", lowThreshold);
- highThreshold = eventNode->getDoubleValue("high-threshold", highThreshold);
- }
-}
-
-void FGAxisEvent::setDefaultThresholds()
-{
- if (_outputMode == OutputMode::SignedNormalized) {
- lowThreshold = -0.9;
- highThreshold = 0.9;
- } else if (_outputMode == OutputMode::UnsignedNormalized) {
- lowThreshold = 0.1;
- highThreshold = 0.9;
- }
-}
-void FGAxisEvent::SetDefaultRange(double min, double max)
-{
- if ((minRange == 0.0) && (maxRange == 0.0)) {
- minRange = min;
- maxRange = max;
- }
-}
-
-FGAxisEvent::~FGAxisEvent() = default;
-
-void FGAxisEvent::update(double dt)
-{
- FGInputEvent::update(dt);
- // ensure buttons repeat, since this common for hats
- if (_lowButton) {
- _lowButton->update(dt);
- }
- if (_highButton) {
- _highButton->update(dt);
- }
-}
-
-void FGAxisEvent::fire(FGEventData& eventData)
-{
- if (fabs(eventData.value - lastValue) < tolerance)
- return;
- lastValue = eventData.value;
-
- // We need a copy of the FGEventData struct to set the new value and to avoid side effects
- FGEventData ed = eventData;
- ed.value = computeValue(lastValue);
-
- if (interpolater) {
- if ((ed.value < 0.0) && mirrorInterpolater) {
- // mirror the positive interpolation for negative values
- ed.value = -interpolater->interpolate(fabs(ed.value));
- } else {
- ed.value = interpolater->interpolate(ed.value);
- }
- }
-
- FGInputEvent::fire(ed);
- const auto v = ed.value;
- if (_lowButton) {
- ed.value = (v < lowThreshold) ? 1.0 : 0.0;
- _lowButton->fire(ed);
- }
-
- if (_highButton) {
- ed.value = (v > highThreshold) ? 1.0 : 0.0;
- _highButton->fire(ed);
- }
-}
-
-double FGAxisEvent::computeValue(double rawValue) const
-{
- const double usedMinRange = minRange;
- const double usedMaxRange = maxRange;
-
- SG_CLAMP_RANGE(rawValue, usedMinRange, usedMaxRange);
- const auto range = usedMaxRange - usedMinRange;
-
- double value = rawValue;
- // normalize to -1.0 ... 1.0
- if (_outputMode == OutputMode::SignedNormalized) {
- value = (2.0 * (rawValue - usedMinRange) / range) - 1.0;
- if (_invert) {
- value = -value;
- }
-
- // apply deadband around center position
- if (fabs(value - center) < deadband) {
- value = center;
- }
- } else if (_outputMode == OutputMode::UnsignedNormalized) {
- value = (rawValue - usedMinRange) / range;
- if (_invert) {
- value = 1.0 - value;
- }
- } else if (_outputMode == OutputMode::Direct) {
- if (_invert) {
- value = maxRange - (rawValue - minRange);
- }
- }
-
- return value;
-}
-
-void FGAbsAxisEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
-{
- // sets the "setting" node
- binding->fire(eventData.value);
-}
-
-FGRelAxisEvent::FGRelAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGAxisEvent(device, eventNode)
-{
- // relative axes can't use tolerance
- tolerance = 0.0;
-}
-
-void FGRelAxisEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
-{
- // sets the "offset" node
- binding->fire(eventData.value, 1.0);
-}
-
-FGButtonEvent::FGButtonEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGInputEvent(device, eventNode),
- repeatable(false),
- lastState(false)
-{
- repeatable = eventNode->getBoolValue("repeatable", repeatable);
- if (eventNode->hasChild("output-mode")) {
- const auto s = eventNode->getStringValue("output-mode");
- if (s == "button") {
- _outputMode = OutputMode::Button;
- } else if (s == "switch") {
- _outputMode = OutputMode::Switch;
- } else {
- throw sg_io_exception("Invalid output mode:" + s, sg_location(eventNode));
- }
- }
-
- if (_outputMode == OutputMode::Switch) {
- if (repeatable) {
- throw sg_io_exception("Switch mode doesn't support repeatable events", sg_location(eventNode));
- }
- }
-
- _invert = eventNode->getBoolValue("invert", false);
-}
-
-void FGButtonEvent::fire(FGEventData& eventData)
-{
- bool pressed = eventData.value > 0.0;
- if (_invert) {
- pressed = !pressed;
- }
-
- if (_outputMode == OutputMode::Button) {
- // In button mode, we fire the press event on press, and the mod-up binding on release
- if (pressed) {
- // The press event may be repeated.
- if (!lastState || repeatable) {
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been pressed");
- FGInputEvent::fire(eventData);
- }
- } else {
- // The release event is never repeated.
- if (lastState) {
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been released");
- eventData.modifiers |= KEYMOD_RELEASED;
- FGInputEvent::fire(eventData);
- }
- }
- } else if (_outputMode == OutputMode::Switch) {
- // In switch mode, we fire with value=true on press, and value=false on release
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been " << (pressed ? "pressed" : "released"));
- eventData.value = pressed ? 1.0 : 0.0;
- FGInputEvent::fire(eventData);
- }
-
- lastState = pressed;
-}
-
-void FGButtonEvent::update(double dt)
-{
- if (repeatable && lastState) {
- // interval / dt handling is done by base ::fire method
- FGEventData ed{1.0, dt, 0 /* modifiers */};
- FGInputEvent::fire(ed);
- }
-}
-
-void FGButtonEvent::fire(SGAbstractBinding* binding, FGEventData& eventData)
-{
- SGPropertyNode_ptr args(new SGPropertyNode);
- args->setBoolValue("value", eventData.value > 0.0);
- binding->fire(args);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// FGExtendedButtonEvent
-
-FGExtendedButtonEvent::FGExtendedButtonEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode)
- : FGButtonEvent(device, eventNode)
-{
- readTimedBindings(eventNode, "mod-double-press", _doublePressBind);
- readTimedBindings(eventNode, "mod-long-press", _longPressBind);
-
- if (auto* n = eventNode->getChild("mod-double-press"))
- _doublePressIntervalSec = readDoubleClickInterval(n);
- if (auto* n = eventNode->getChild("mod-long-press"))
- _longPressIntervalSec = readLongPressInterval(n);
-}
-
-void FGExtendedButtonEvent::readTimedBindings(SGPropertyNode_ptr eventNode, const char* nodeName, SGBindingList& bindList)
-{
- auto* subNode = eventNode->getChild(nodeName);
- if (!subNode)
- return;
- const auto& nasalMod = device->GetNasalModule();
- for (auto b : subNode->getChildren("binding")) {
- if (b->getStringValue("command") == "nasal" && !nasalMod.empty()) {
- b->setStringValue("module", nasalMod);
- }
- bindList.push_back(SGAbstractBinding::createFromProps(b, globals->get_props()));
- }
-}
-
-double FGExtendedButtonEvent::readDoubleClickInterval(SGPropertyNode_ptr subNode) const
-{
- return subNode->getDoubleValue("interval-sec",
- fgGetDouble("/sim/input/double-press-sec", 0.4));
-}
-
-double FGExtendedButtonEvent::readLongPressInterval(SGPropertyNode_ptr subNode) const
-{
- return subNode->getDoubleValue("interval-sec",
- fgGetDouble("/sim/input/long-press-sec", 0.8));
-}
-
-void FGExtendedButtonEvent::fire(FGEventData& eventData)
-{
- bool pressed = eventData.value > 0.0;
- if (_invert) {
- pressed = !pressed;
- }
-
- if (_outputMode == OutputMode::Button) {
- if (pressed) {
- // Reset long-press tracking on each new press
- _pressHeldTime = 0.0;
- _longPressFired = false;
-
- if (!lastState || repeatable) {
- if (_waitingForDoublePress && !_doublePressBind.empty()) {
- // Second press within the double-press window: fire double-press bindings
- // and suppress the normal press bindings
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' double-pressed");
- for (auto& b : _doublePressBind)
- FGButtonEvent::fire(b.get(), eventData);
- _timeSinceFirstPress = 0.0;
- } else {
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been pressed");
- FGInputEvent::fire(eventData);
- if (!_doublePressBind.empty()) {
- _waitingForDoublePress = true;
- _timeSinceFirstPress = 0.0;
- }
- }
- }
- } else {
- if (lastState) {
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been released");
- eventData.modifiers |= KEYMOD_RELEASED;
- FGInputEvent::fire(eventData);
- _pressHeldTime = 0.0;
- }
- }
- } else if (_outputMode == OutputMode::Switch) {
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' has been " << (pressed ? "pressed" : "released"));
- eventData.value = pressed ? 1.0 : 0.0;
- FGInputEvent::fire(eventData);
- }
-
- lastState = pressed;
-}
-
-void FGExtendedButtonEvent::update(double dt)
-{
- FGButtonEvent::update(dt);
-
- // Double-press timeout: clear the waiting flag once the window expires
- if (_waitingForDoublePress) {
- _timeSinceFirstPress += dt;
- if (_timeSinceFirstPress >= _doublePressIntervalSec) {
- _waitingForDoublePress = false;
- _timeSinceFirstPress = 0.0;
- }
- }
-
- // Long-press: fire the long-press bindings once the hold time is exceeded
- if (lastState && !_longPressBind.empty() && !_longPressFired) {
- _pressHeldTime += dt;
- if (_pressHeldTime >= _longPressIntervalSec) {
- SG_LOG(SG_INPUT, SG_DEBUG, "Button '" << this->name << "' long-pressed");
- FGEventData ed{1.0, dt, 0 /* modifiers */};
- for (auto& b : _longPressBind)
- FGButtonEvent::fire(b.get(), ed);
- _longPressFired = true;
- }
- }
-}
-
-FGInputDevice::~FGInputDevice()
-{
- auto nas = globals->get_subsystem<FGNasalSys>();
- if (nas && deviceNode) {
- SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
- if (nasal) {
- SGPropertyNode_ptr nasalClose = nasal->getNode("close");
- if (nasalClose) {
- const string s = nasalClose->getStringValue();
- nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode);
- }
- }
- nas->deleteModule(nasalModule.c_str());
- }
-}
-
-void FGInputDevice::Configure(SGPropertyNode_ptr aDeviceNode)
-{
- deviceNode = aDeviceNode;
-
- // export our class_id to property tree
- deviceNode->setStringValue("_class-id", class_id);
- deviceNode->setStringValue("serial-number", serialNumber);
- deviceNode->setStringValue("unique-name", _uniqueName);
-
- SG_LOG(SG_INPUT, SG_DEBUG, "FGInputDevice::Configure");
-
- // use _uniqueName here so each loaded device gets its own Nasal module
- nasalModule = string("__event:") + _uniqueName;
-
- for (auto ev : deviceNode->getChildren("event")) {
- try {
- AddHandledEvent(FGInputEvent::NewObject(this, ev));
- } catch (sg_exception& e) {
- simgear::reportFailure(simgear::LoadFailure::Misconfigured,
- simgear::ErrorCode::InputDeviceConfig,
- "Event config error: "s + e.getMessage(),
- sg_location(ev));
- }
- }
-
- debugEvents = deviceNode->getBoolValue("debug-events", debugEvents);
- grab = deviceNode->getBoolValue("grab", grab);
-
- auto reportNodes = deviceNode->getChildren("report");
- for (auto repNode : reportNodes) {
- try {
- FGReportSetting_ptr r = new FGReportSetting(repNode);
- reportSettings.push_back(r);
- } catch (sg_exception& e) {
- simgear::reportFailure(simgear::LoadFailure::Misconfigured,
- simgear::ErrorCode::InputDeviceConfig,
- "Event report config error: "s + e.getMessage(),
- sg_location(repNode));
- }
- }
-
-
- lastEventName = deviceNode->getNode("last-event", true)->getNode("name", true);
- lastEventName->setStringValue("");
- lastEventValue = deviceNode->getNode("last-event")->getNode("value", true);
- lastEventValue->setDoubleValue(0.0);
-
- SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
- if (nasal) {
- SGPropertyNode_ptr open = nasal->getNode("open");
- if (open) {
- const string s = open->getStringValue();
- auto nas = globals->get_subsystem<FGNasalSys>();
- if (nas)
- nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode);
- }
- }
-}
-
-void FGInputDevice::AddHandledEvent(FGInputEvent_ptr event)
-{
- auto it = handledEvents.find(event->GetName());
- if (it == handledEvents.end()) {
- handledEvents.insert(it, std::make_pair(event->GetName(), event));
- }
-}
-
-void FGInputDevice::update(double dt)
-{
- for (map<string, FGInputEvent_ptr>::iterator it = handledEvents.begin(); it != handledEvents.end(); it++)
- (*it).second->update(dt);
-
- for (auto r : reportSettings) {
- if (r->hasError()) {
- continue;
- }
-
- try {
- if (r->Test()) {
- auto reportData = r->reportBytes(nasalModule);
- if (debugEvents) {
- SG_LOG(SG_INPUT, SG_INFO, class_id << " " << GetUniqueName() << ": Sending report " << r->getReportId() << simgear::strutils::encodeHex(reportData));
- }
- if (r->getReportType() == FGReportSetting::Type::Feature) {
- SendFeatureReport(r->getReportId(), reportData);
- } else {
- SendOutputReport(r->getReportId(), reportData);
- }
- }
- } catch (sg_exception& e) {
- r->markAsError();
- simgear::reportFailure(simgear::LoadFailure::Unknown,
- simgear::ErrorCode::InputDeviceConfig,
- "Failed to send report:"s + e.getMessage(),
- e.getLocation());
- }
- } // of report setting iteration
-}
-
-void FGInputDevice::HandleEvent(FGEventData& eventData)
-{
- string eventName = TranslateEventName(eventData);
- if (debugEvents) {
- SG_LOG(SG_INPUT, SG_INFO, class_id << " " << GetUniqueName() << " has event " << eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value);
- }
- lastEventName->setStringValue(eventName);
- lastEventValue->setValue(eventData.value);
- if (handledEvents.count(eventName) > 0) {
- handledEvents[eventName]->fire(eventData);
- }
-}
-
-void FGInputDevice::SetName(string name)
-{
- this->name = name;
-}
-
-void FGInputDevice::SetUniqueName(const std::string& name)
-{
- _uniqueName = name;
-}
-
-void FGInputDevice::SetSerialNumber(std::string serial)
-{
- serialNumber = serial;
-}
-
-void FGInputDevice::SendFeatureReport(unsigned int reportId, const simgear::UInt8Vector& data)
-{
- SG_LOG(SG_INPUT, SG_WARN, "SendFeatureReport not implemented");
-}
-
-void FGInputDevice::SendOutputReport(unsigned int reportId, const simgear::UInt8Vector& data)
-{
- SG_LOG(SG_INPUT, SG_WARN, "SendOutputReport not implemented");
-}
-
FGEventInput::FGEventInput() = default;
FGEventInput::FGEventInput(const char* filePath, const char* propertyRoot) : filePath(filePath),
@@ -789,117 +164,3 @@ void FGEventInput::RemoveDevice(unsigned index)
}
deviceNode = baseNode->removeChild("device", index);
}
-
-FGReportSetting::FGReportSetting(SGPropertyNode_ptr base)
-{
- location = base->getLocation();
- reportId = base->getIntValue("report-id");
-
- auto nas = globals->get_subsystem<FGNasalSys>();
- if (!nas) {
- SG_LOG(SG_INPUT, SG_DEV_ALERT, "Nasal subsystem not available, input report settings won't work");
- return;
- }
-
- const auto loc = base->getLocation();
- if (base->hasChild("nasal-function")) {
- auto nasalFunction = base->getStringValue("nasal-function");
- // we're compiling a trivial function call as code, so we can use the same
- // code path at runtime
- nasalCode = nas->createCode(nasalFunction + "()", loc.getPath(), loc.getLine());
- } else if (base->hasChild("nasal")) {
- nasalCode = nas->createCode(base->getStringValue("nasal"), loc.getPath(), loc.getLine());
- } else {
- simgear::reportFailure(simgear::LoadFailure::Misconfigured,
- simgear::ErrorCode::InputDeviceConfig,
- "No nasal/nasal-function defined for report setting",
- sg_location(base));
- }
-
- if (base->hasChild("report-type")) {
- const auto s = base->getStringValue("report-type");
- if (s == "output") {
- _type = Type::Output;
- } else if (s == "feature") {
- _type = Type::Feature;
- } else {
- simgear::reportFailure(simgear::LoadFailure::Misconfigured,
- simgear::ErrorCode::InputDeviceConfig,
- "Invalid report type:" + s,
- sg_location(base));
- }
- }
-
- auto watchNodes = base->getChildren("watch");
- for (auto w : watchNodes) {
- std::string path = w->getStringValue();
- SGPropertyNode_ptr n = globals->get_props()->getNode(path, true);
- n->addChangeListener(this);
- }
-}
-
-bool FGReportSetting::Test()
-{
- bool d = dirty;
- dirty = false;
- return d;
-}
-
-simgear::UInt8Vector FGReportSetting::reportBytes(const std::string& moduleName) const
-{
- auto nas = globals->get_subsystem<FGNasalSys>();
- if (!nas) {
- return {};
- }
-
- naRef locals = nas->getModule(moduleName, true /*create*/);
- naRef result = nasalCode.callWithLocals(locals);
-
- if (naIsString(result)) {
- size_t len = naStr_len(result);
- char* bytes = naStr_data(result);
- char* endByte = bytes + len;
- return simgear::UInt8Vector(
- reinterpret_cast<uint8_t*>(bytes),
- reinterpret_cast<uint8_t*>(endByte));
- }
-
- if (naIsVector(result)) {
- int len = naVec_size(result);
- simgear::UInt8Vector d;
- for (int b = 0; b < len; ++b) {
- int num = naNumValue(naVec_get(result, b)).num;
- d.push_back(static_cast<uint8_t>(num));
- }
-
- return d;
- }
-
- // allow returning nil to mean no data
- if (naIsNil(result)) {
- return {};
- }
-
- throw sg_exception("Bad data from input report setting", "result was not a string or vector", sg_location(location));
-}
-
-void FGReportSetting::valueChanged(SGPropertyNode* n)
-{
- auto it = watchValueCache.find(n);
- const auto val = n->getStringValue();
- if (it == watchValueCache.end()) {
- watchValueCache.insert(std::make_pair(n, val));
- dirty = true;
- return;
- }
-
- // because we use string equality, for floating-point values, we will
- // quantise to the precision of the string representation.
- // that's an almost-feature, until we define explicit precision on properties
- if (val == it->second) {
- return;
- }
-
- it->second = val;
- dirty = true;
-}
diff --git a/src/Input/FGEventInput.hxx b/src/Input/FGEventInput.hxx
index e6e3dafba..9773e1406 100644
--- a/src/Input/FGEventInput.hxx
+++ b/src/Input/FGEventInput.hxx
@@ -8,333 +8,17 @@
#pragma once
#include "FGCommonInput.hxx"
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "FGButton.hxx"
#include "FGDeviceConfigurationMap.hxx"
-#include "simgear/structure/SGSourceLocation.hxx"
-#include <simgear/misc/strutils.hxx>
-#include <simgear/structure/subsystem_mgr.hxx>
-
-#include "FGEventInput_private.hxx"
-
-// forward decls
-class SGInterpTable;
-
-/*
- * A base structure for event data.
- * To be extended for O/S specific implementation data
- */
-struct FGEventData {
- FGEventData(double aValue, double aDt, int aModifiers) : modifiers(aModifiers), value(aValue), dt(aDt) {}
- int modifiers{0};
- double value{0.0};
- double dt{0.0};
-};
-
-class FGButtonEvent;
-using ButtonEvent_ptr = SGSharedPtr<FGButtonEvent>;
-
-/*
- * A wrapper class for a configured event.
- *
- * <event>
- * <desc>Change the view pitch</desc>
- * <name>rel-x-rotate</name>
- * <binding>
- * <command>property-adjust</command>
- * <property>sim/current-view/pitch-offset-deg</property>
- * <factor type="double">0.01</factor>
- * <min type="double">-90.0</min>
- * <max type="double">90.0</max>
- * <wrap type="bool">false</wrap>
- * </binding>
- * <mod-xyz>
- * <binding>
- * ...
- * </binding>
- * </mod-xyz>
- * </event>
- */
-class FGInputDevice;
-class FGInputEvent : public SGReferenced,
- FGCommonInput
-{
-public:
- FGInputEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode);
- virtual ~FGInputEvent();
-
- // dispatch the event value through all bindings
- virtual void fire(FGEventData& eventData);
-
- std::string GetName() const { return name; }
- std::string GetDescription() const { return desc; }
-
- virtual void update(double dt);
- static FGInputEvent* NewObject(FGInputDevice* device, SGPropertyNode_ptr node);
-
-protected:
- virtual void fire(SGAbstractBinding* binding, FGEventData& eventData);
- /* A more or less meaningful description of the event */
- std::string desc;
-
- /* One of the predefined names of the event */
- std::string name;
-
- /* A list of SGBinding objects */
- binding_list_t bindings[KEYMOD_MAX];
+#include "FGInputDevice.hxx"
- /* A list of FGEventSetting objects */
- setting_list_t settings;
-
- /* A pointer to the associated device */
- FGInputDevice* device;
-
- double lastDt = std::nan("");
- double intervalSec = std::nan("");
- double lastSettingValue = std::nan("");
-};
-
-class FGButtonEvent : public FGInputEvent
-{
-public:
- FGButtonEvent(FGInputDevice* device, SGPropertyNode_ptr node);
- void fire(FGEventData& eventData) override;
-
- void update(double dt) override;
-
- enum class OutputMode {
- Button, ///< fire on press, do mod-up binding on release
- Switch ///< fire with value=true on press, value=false on release
- };
-
-protected:
- void fire(SGAbstractBinding* binding, FGEventData& eventData) override;
-
- bool repeatable;
- bool lastState;
-
- bool _invert = false;
- OutputMode _outputMode = OutputMode::Button;
-};
-
-/**
- * FGButtonEvent subclass adding double-press and long-press support.
- *
- * Created by FGInputEvent::NewObject when @c mod-double-press or
- * @c mod-long-press child nodes are present on the event node.
- */
-class FGExtendedButtonEvent : public FGButtonEvent
-{
-public:
- FGExtendedButtonEvent(FGInputDevice* device, SGPropertyNode_ptr node);
- void fire(FGEventData& eventData) override;
- void update(double dt) override;
-
-private:
- void readTimedBindings(SGPropertyNode_ptr eventNode, const char* nodeName, SGBindingList& bindList);
- double readDoubleClickInterval(SGPropertyNode_ptr subNode) const;
- double readLongPressInterval(SGPropertyNode_ptr subNode) const;
-
- /// Bindings fired on a double-press (second press within _doublePressIntervalSec).
- /// When defined, the second press does not fire the regular down bindings.
- SGBindingList _doublePressBind;
-
- /// Bindings fired when the button has been held for _longPressIntervalSec.
- /// When defined, the subsequent release does not fire the regular mod-up bindings.
- SGBindingList _longPressBind;
-
- double _doublePressIntervalSec = 0.0;
- double _longPressIntervalSec = 0.0;
-
- // double-press detection state
- bool _waitingForDoublePress = false;
- double _timeSinceFirstPress = 0.0;
-
- // long-press detection state
- double _pressHeldTime = 0.0;
- bool _longPressFired = false;
-};
-
-class FGAxisEvent : public FGInputEvent
-{
-public:
- FGAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode);
- ~FGAxisEvent();
-
- void update(double dt) override;
-
- void SetRange(double min, double max)
- {
- minRange = min;
- maxRange = max;
- }
-
- /**
- * @brief set the range based on system data (eg, HID descriptor logical range)
- * only used if the config node didn't define range data
- */
- void SetDefaultRange(double min, double max);
-
- enum class OutputMode {
- SignedNormalized, ///< output in range [-1.0, 1.0], with center at 0.0
- UnsignedNormalized, ///< output in range [0.0, 1.0],
- Direct
- };
-
-protected:
- void fire(FGEventData& eventData) override;
-
- double computeValue(double rawValue) const;
- void setDefaultThresholds();
-
- double tolerance = 0.0;
- double minRange = 0.0;
- double maxRange = 0.0;
- double center = 0.0;
- double deadband = 0.0;
- double lowThreshold = 0.0;
- double highThreshold = 0.0;
- double lastValue = std::numeric_limits<double>::quiet_NaN();
-
- std::unique_ptr<SGInterpTable> interpolater;
- bool mirrorInterpolater = false;
-
- bool _invert = false;
- OutputMode _outputMode = OutputMode::SignedNormalized;
-
- ButtonEvent_ptr _lowButton, _highButton;
-};
-
-class FGRelAxisEvent : public FGAxisEvent
-{
-public:
- FGRelAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode);
-
-protected:
- void fire(SGAbstractBinding* binding, FGEventData& eventData) override;
-};
-
-class FGAbsAxisEvent : public FGAxisEvent
-{
-public:
- FGAbsAxisEvent(FGInputDevice* device, SGPropertyNode_ptr eventNode) : FGAxisEvent(device, eventNode) {}
-
-protected:
- void fire(SGAbstractBinding* binding, FGEventData& eventData) override;
-};
-
-typedef class SGSharedPtr<FGInputEvent> FGInputEvent_ptr;
-
-/*
- * A abstract class implementing basic functionality of input devices for
- * all operating systems. This is the base class for the O/S-specific
- * implementation of input device handlers
- */
-class FGInputDevice : public SGReferenced
-{
-public:
- FGInputDevice() {}
- FGInputDevice(std::string aName, std::string aSerial = {}) : name(aName), serialNumber(aSerial) {}
-
- virtual ~FGInputDevice();
-
- virtual bool Open() = 0;
- virtual void Close() = 0;
-
- virtual void Send(const char* eventName, double value) = 0;
-
- inline void Send(const std::string& eventName, double value)
- {
- Send(eventName.c_str(), value);
- }
-
- virtual void SendFeatureReport(unsigned int reportId, const simgear::UInt8Vector& data);
- virtual void SendOutputReport(unsigned int reportId, const simgear::UInt8Vector& data);
-
- virtual const char* TranslateEventName(FGEventData& eventData) = 0;
-
-
- void SetName(std::string name);
- std::string& GetName() { return name; }
-
- void SetUniqueName(const std::string& name);
- const std::string GetUniqueName() const { return _uniqueName; }
-
- void SetSerialNumber(std::string serial);
- std::string& GetSerialNumber() { return serialNumber; }
-
- void HandleEvent(FGEventData& eventData);
-
- virtual void AddHandledEvent(FGInputEvent_ptr handledEvent);
-
- virtual void Configure(SGPropertyNode_ptr deviceNode);
-
- virtual void update(double dt);
-
- bool GetDebugEvents() const { return debugEvents; }
-
- bool GetGrab() const { return grab; }
-
- const std::string& GetNasalModule() const { return nasalModule; }
- std::string class_id = "FGInputDevice";
-
- // allow matching based on HID IDs, as well as names
- uint32_t GetVendorDeviceId() const
- {
- return _vendorDeviceId;
- }
-
- void SetVendorDeviceId(uint32_t id)
- {
- _vendorDeviceId = id;
- }
-
-protected:
- // A map of events, this device handles
- std::map<std::string, FGInputEvent_ptr> handledEvents;
-
- // the device has a name to be recognized
- std::string name;
-
- // serial number string to disambiguate multiple instances
- // of the same device
- std::string serialNumber;
-
- // print out events coming in from the device
- // if true
- bool debugEvents = false;
-
- // grab the device exclusively, if O/S supports this
- // so events are not sent to other applications
- bool grab = false;
-
- //configuration in property tree
- SGPropertyNode_ptr deviceNode;
- SGPropertyNode_ptr lastEventName;
- SGPropertyNode_ptr lastEventValue;
-
- std::string nasalModule;
-
- report_setting_list_t reportSettings;
-
- /// name, but with suffix / serial appended. This is important
- /// when loading the device multiple times, to ensure the Nasal
- /// module is unique
- std::string _uniqueName;
-
- uint32_t _vendorDeviceId = 0;
-};
-
-typedef SGSharedPtr<FGInputDevice> FGInputDevice_ptr;
+#include <map>
+#include <simgear/structure/subsystem_mgr.hxx>
/*
* The Subsystem for the event input device
*/
+/// TODO: document
class FGEventInput : public SGSubsystem,
FGCommonInput
{
diff --git a/src/Input/FGHIDEventInput.cxx b/src/Input/FGHIDDevice.cxx
similarity index 74%
copy from src/Input/FGHIDEventInput.cxx
copy to src/Input/FGHIDDevice.cxx
index c50dd765a..ba5d43df7 100644
--- a/src/Input/FGHIDEventInput.cxx
+++ b/src/Input/FGHIDDevice.cxx
@@ -1,31 +1,26 @@
-// FGHIDEventInput.cxx -- handle event driven input devices via HIDAPI
+// FGHIDDevice.cxx -- HID input device implementation via HIDAPI
//
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2017 James Turner <ja...@fl...>
-#include "Input/FGEventInput.hxx"
-#include "config.h"
-#include "simgear/debug/debug_types.h"
+#include "FGHIDDevice.hxx"
-#include "FGHIDEventInput.hxx"
-
-#include <algorithm>
+#include "FGAxisEvent.hxx"
#include <cassert>
#include <cstdlib>
+#include <cstring>
#include <string>
-#include <unordered_set>
-
-#include <Main/fg_props.hxx>
-#include <hidapi/hidapi.h>
-#include <hidapi/hidparse.h>
#include <simgear/debug/ErrorReportingCallback.hxx>
+#include <simgear/debug/debug_types.h>
#include <simgear/io/lowlevel.hxx>
+#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/strutils.hxx>
-#include <simgear/sg_inlines.h>
#include <simgear/structure/exception.hxx>
-#include "FGHIDUsage.hxx"
+#include <Main/fg_props.hxx>
+
+#include "FGHIDEventInput.hxx"
using simgear::strutils::encodeHex;
@@ -55,7 +50,6 @@ bool shouldPrefixWithAbs(uint32_t usagePage, uint32_t usage)
return false;
}
-
static int hatXValue(int hatValue)
{
switch (hatValue) {
@@ -100,7 +94,6 @@ static int hatYValue(int hatValue)
}
}
-
ReportType reportTypeFromString(const std::string& s)
{
if (s == "input") return ReportType::In;
@@ -108,121 +101,11 @@ ReportType reportTypeFromString(const std::string& s)
if (s == "feature") return ReportType::Feature;
return ReportType::Invalid;
}
-} // namespace HID
-
-class FGHIDEventInput::FGHIDEventInputPrivate
-{
-public:
- FGHIDEventInput* p = nullptr;
-
- void evaluateDevice(hid_device_info* deviceInfo);
-};
-
-// anonymous namespace to define our device subclass
-namespace {
-
-class FGHIDDevice : public FGInputDevice
-{
-public:
- FGHIDDevice(hid_device_info* devInfo,
- FGHIDEventInput* subsys);
-
- virtual ~FGHIDDevice();
-
- bool Open() override;
- void Close() override;
- void Configure(SGPropertyNode_ptr node) over...
[truncated message content] |
|
From: <fli...@li...> - 2026-04-13 21:49:49
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new 57b93b56f Get all tests added to Ctest
57b93b56f is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/57b93b56f079c8577351bcc09f5edcd6eed864ad/
Commit: 57b93b56f079c8577351bcc09f5edcd6eed864ad
Author: James Turner
Committer: James Turner
AuthorDate: Thu Apr 9 20:26:39 2026 +0100
Get all tests added to Ctest
---
test_suite/CMakeLists.txt | 146 +++++++--------------
test_suite/FGTestApi/CMakeLists.txt | 47 +++----
test_suite/fgdata_tests/CMakeLists.txt | 22 +---
test_suite/gui_tests/CMakeLists.txt | 22 +---
test_suite/simgear_tests/CMakeLists.txt | 18 +--
test_suite/simgear_tests/canvas/CMakeLists.txt | 16 +--
test_suite/simgear_tests/math/CMakeLists.txt | 16 +--
test_suite/simgear_tests/props/CMakeLists.txt | 20 ++-
test_suite/simgear_tests/structure/CMakeLists.txt | 17 +--
test_suite/simgear_tests/timing/CMakeLists.txt | 16 +--
test_suite/simgear_tests/timing/test_SGTime.cxx | 8 +-
test_suite/system_tests/CMakeLists.txt | 21 +--
test_suite/system_tests/FDM/CMakeLists.txt | 16 +--
.../system_tests/Instrumentation/CMakeLists.txt | 17 +--
test_suite/system_tests/Main/CMakeLists.txt | 16 +--
test_suite/system_tests/Navaids/CMakeLists.txt | 17 +--
test_suite/system_tests/subsystems/CMakeLists.txt | 21 ++-
test_suite/unit_tests/AI/CMakeLists.txt | 43 +++---
test_suite/unit_tests/ATC/CMakeLists.txt | 19 +--
test_suite/unit_tests/Add-ons/CMakeLists.txt | 16 +--
test_suite/unit_tests/Aircraft/CMakeLists.txt | 17 +--
test_suite/unit_tests/Airports/CMakeLists.txt | 21 +--
test_suite/unit_tests/Autopilot/CMakeLists.txt | 31 ++---
test_suite/unit_tests/CMakeLists.txt | 18 +--
test_suite/unit_tests/FDM/CMakeLists.txt | 24 ++--
test_suite/unit_tests/GUI/CMakeLists.txt | 16 +--
test_suite/unit_tests/Input/CMakeLists.txt | 25 ++--
.../unit_tests/Instrumentation/CMakeLists.txt | 41 +++---
test_suite/unit_tests/Main/CMakeLists.txt | 32 ++---
test_suite/unit_tests/Navaids/CMakeLists.txt | 31 ++---
test_suite/unit_tests/Network/CMakeLists.txt | 39 ++----
test_suite/unit_tests/Scripting/CMakeLists.txt | 27 ++--
test_suite/unit_tests/Translations/CMakeLists.txt | 17 +--
test_suite/unit_tests/general/CMakeLists.txt | 20 ++-
34 files changed, 308 insertions(+), 585 deletions(-)
diff --git a/test_suite/CMakeLists.txt b/test_suite/CMakeLists.txt
index 5aa87e98f..5dae5970f 100644
--- a/test_suite/CMakeLists.txt
+++ b/test_suite/CMakeLists.txt
@@ -6,43 +6,16 @@ include(SetupFGFSEmbeddedResources)
include(SetupFGFSIncludes)
include(SetupFGFSLibraries)
-# Add each test suite category.
-foreach(test_category
- gui_tests
- simgear_tests
- system_tests
- unit_tests
- fgdata_tests
- )
- add_subdirectory(${test_category})
-endforeach(test_category)
-
-# Add the testing API.
-add_subdirectory(FGTestApi)
-
-# Add all test suite sources and headers.
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- bootstrap.cxx
- dataStore.cxx
- fgCompilerOutputter.cxx
- fgJunitOutputter.cxx
- fgTestListener.cxx
- fgTestRunner.cxx
- formatting.cxx
- logging.cxx
- testSuite.cxx
-)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- dataStore.hxx
- fgCompilerOutputter.hxx
- fgJunitOutputter.hxx
- fgTestListener.hxx
- fgTestRunner.hxx
- formatting.hxx
- logging.hxx
-)
+#-----------------------------------------------------------------------------
+# Register a CppUnit test suite with ctest.
+# SUITE_NAME must match the first argument of CPPUNIT_TEST_SUITE_NAMED_REGISTRATION
+# in the corresponding TestSuite.cxx.
+# TYPE is the single-letter ctest category flag:
+# u unit tests, s system tests, m simgear unit tests
+function(fg_add_test_suite SUITE_NAME TYPE)
+ add_test(NAME "${SUITE_NAME}"
+ COMMAND fgfs_test_suite --ctest -${TYPE} "${SUITE_NAME}")
+endfunction()
# The test suite output directory.
set(TESTSUITE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
@@ -54,7 +27,6 @@ if (NOT SYSTEM_CPPUNIT)
get_property(CPPUNIT_SOURCES GLOBAL PROPERTY CPPUNIT_SOURCES)
get_property(CPPUNIT_HEADERS GLOBAL PROPERTY CPPUNIT_HEADERS)
-
add_library(CppUnitLib STATIC ${CPPUNIT_SOURCES} ${CPPUNIT_HEADERS})
target_include_directories(CppUnitLib PUBLIC "${PROJECT_SOURCE_DIR}/3rdparty/cppunit/include")
@@ -64,46 +36,11 @@ else()
message(STATUS "CppUnit: Linking to the system supplied CppUnit library")
endif()
-#-----------------------------------------------------------------------------
-# Set up all test suites as CTests.
-
-# System test suites.
-add_test(AeroMeshSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s AeroMeshTests)
-#add_test(GPSSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s GPSTests)
-add_test(InstancedSubsystemSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s InstancedSubsystemTests)
-#add_test(NavaidsSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s NavaidsTests)
-add_test(NonInstancedSubsystemSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s NonInstancedSubsystemTests)
-
-# Unit test suites.
-add_test(AddonManagementUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AddonManagementTests)
-add_test(AeroElementUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AeroElementTests)
-add_test(AircraftPerformanceUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AircraftPerformanceTests)
-add_test(AutosaveMigrationUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AutosaveMigrationTests)
-add_test(FlightplanUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u FlightplanTests)
-add_test(FPNasalUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u FPNasalTests)
-add_test(GPSUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u GPSTests)
-add_test(HoldControllerUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u HoldControllerTests)
-if(ENABLE_HID_INPUT)
- add_test(HIDInputUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u HIDInputTests)
-endif()
-add_test(MktimeUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u MktimeTests)
-add_test(NasalSysUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NasalSysTests)
-add_test(NasalSysUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NasalLibTests)
-add_test(NavaidsUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NavaidsTests)
-add_test(NavRadioUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NavRadioTests)
-add_test(PosInitUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u PosInitTests)
-add_test(RNAVProcedureUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u RNAVProcedureTests)
-add_test(RouteManagerUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u RouteManagerTests)
-add_test(YASimAtmosphereUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u YASimAtmosphereTests)
-
-# GUI test suites.
-
-# Simgear unit test suites.
-add_test(CanvasSimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -m CanvasTests)
-add_test(MathGeodesySimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -m MathGeodesyTests)
-add_test(SimgearPropsSimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -m SimgearPropsTests)
-
-# FGData test suites.
+# most object files come from fgfsObjects target: this property
+# contains all the sources which need to be compiled separately
+# for the test-suite, because they depend on BUILDING_TESTSUITE define
+# we setup below via target_compile_definitions
+get_property(TEST_SOURCES GLOBAL PROPERTY FG_TEST_SOURCES)
#-----------------------------------------------------------------------------
# Set up the binary.
@@ -111,19 +48,18 @@ add_test(SimgearPropsSimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --
# Set up the embedded resources.
setup_fgfs_embedded_resources()
-
-# most object files come from fgfsObjects target: this property
-# contains all the sources which need to be compiled separately
-# for the test-suite, because they depend on BUILDING_TESTSUITE define
-# we setup below via target_compile_definitions
-
-get_property(TEST_SOURCES GLOBAL PROPERTY FG_TEST_SOURCES)
-
# Set up the separate executable for running the test suite.
add_executable(fgfs_test_suite
${TEST_SOURCES}
- ${TESTSUITE_SOURCES}
- ${TESTSUITE_HEADERS}
+ bootstrap.cxx
+ dataStore.cxx
+ fgCompilerOutputter.cxx
+ fgJunitOutputter.cxx
+ fgTestListener.cxx
+ fgTestRunner.cxx
+ formatting.cxx
+ logging.cxx
+ testSuite.cxx
)
target_link_libraries(fgfs_test_suite PRIVATE fgfsObjects)
@@ -133,19 +69,13 @@ set_target_properties(fgfs_test_suite
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${TESTSUITE_OUTPUT_DIR}"
)
-if(ENABLE_AUTOTESTING)
- set(TEST_SUITE_COMMAND "fgfs_test_suite")
- set(TEST_SUITE_COMMENT "Running the full FlightGear test suite")
-else()
- set(TEST_SUITE_COMMENT "Building the FlightGear test suite.")
-endif(ENABLE_AUTOTESTING)
# Set up the target links.
setup_fgfs_libraries(fgfs_test_suite)
# Additional search paths for includes.
setup_fgfs_includes(fgfs_test_suite)
-# test codce includes its headers as test_suite/foo.h, so we need this
+# test code includes its headers as test_suite/foo.h, so we need this
target_include_directories(fgfs_test_suite PUBLIC ${PROJECT_SOURCE_DIR})
target_compile_definitions(fgfs_test_suite PUBLIC BUILDING_TESTSUITE)
@@ -153,7 +83,6 @@ target_compile_definitions(fgfs_test_suite PUBLIC BUILDING_TESTSUITE)
# Additional libraries just for the test suite.
target_link_libraries(fgfs_test_suite PRIVATE CppUnitLib)
-# target to run the tests
if (MSVC)
file(TO_NATIVE_PATH "${FG_QT_BIN_DIR}" _qt_bin_dir_native)
file(TO_NATIVE_PATH "${FINAL_MSVC_3RDPARTY_DIR}/bin" _msvc_3rdparty_bin_dir)
@@ -167,6 +96,31 @@ if (FG_QT_ROOT_DIR)
target_include_directories(fgfs_test_suite PRIVATE ${FG_QT_ROOT_DIR}/include)
endif()
+#-----------------------------------------------------------------------------
+# Add each test suite category.
+# Each subdirectory uses fg_add_test_suite() to register its sources with the
+# fgfs_test_suite target and to add ctest entries.
+
+add_subdirectory(FGTestApi)
+
+foreach(test_category
+ gui_tests
+ simgear_tests
+ system_tests
+ unit_tests
+ fgdata_tests
+ )
+ add_subdirectory(${test_category})
+endforeach()
+
+#-----------------------------------------------------------------------------
+# target to run the tests
+if(ENABLE_AUTOTESTING)
+ set(TEST_SUITE_COMMAND "fgfs_test_suite")
+ set(TEST_SUITE_COMMENT "Running the full FlightGear test suite")
+else()
+ set(TEST_SUITE_COMMENT "Building the FlightGear test suite.")
+endif(ENABLE_AUTOTESTING)
add_custom_target(test_suite
${TEST_SUITE_COMMAND}
diff --git a/test_suite/FGTestApi/CMakeLists.txt b/test_suite/FGTestApi/CMakeLists.txt
index 00f936bd2..7f76c935d 100644
--- a/test_suite/FGTestApi/CMakeLists.txt
+++ b/test_suite/FGTestApi/CMakeLists.txt
@@ -1,32 +1,23 @@
-# SPDX-FileName: CMakeLists.txt
# SPDX-FileCopyrightText: Copyright (C) 2020 Edward d'Auvergne
# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/testGlobals.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/NavDataCache.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/PrivateAccessorFDM.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/scene_graph.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/TestPilot.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/NasalUnitTesting_TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/TestDataLogger.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testApis.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/DummyCanvasSystemAdapter.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testStringUtils.cxx
- PARENT_SCOPE
-)
-
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testGlobals.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/NavDataCache.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/PrivateAccessorFDM.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/scene_graph.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/TestPilot.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/TestDataLogger.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/DummyCanvasSystemAdapter.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testStringUtils.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ testGlobals.cxx
+ NavDataCache.cxx
+ PrivateAccessorFDM.cxx
+ scene_graph.cxx
+ TestPilot.cxx
+ NasalUnitTesting_TestSuite.cxx
+ TestDataLogger.cxx
+ testApis.cxx
+ DummyCanvasSystemAdapter.cxx
+ testStringUtils.cxx
+ testGlobals.hxx
+ NavDataCache.hxx
+ PrivateAccessorFDM.hxx
+ scene_graph.hxx
+ TestPilot.hxx
+ TestDataLogger.hxx
+ DummyCanvasSystemAdapter.hxx
+ testStringUtils.hxx
)
diff --git a/test_suite/fgdata_tests/CMakeLists.txt b/test_suite/fgdata_tests/CMakeLists.txt
index 6c2314987..c4853a83a 100644
--- a/test_suite/fgdata_tests/CMakeLists.txt
+++ b/test_suite/fgdata_tests/CMakeLists.txt
@@ -1,19 +1,5 @@
-# Add each simgear test category.
-foreach( simgear_test_category
- )
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
- add_subdirectory(${simgear_test_category})
-
-endforeach( simgear_test_category )
-
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- PARENT_SCOPE
-)
-
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- PARENT_SCOPE
-)
+# Add each FGData test category.
+# (No subcategories currently.)
diff --git a/test_suite/gui_tests/CMakeLists.txt b/test_suite/gui_tests/CMakeLists.txt
index 64a3eeb3c..66da8370b 100644
--- a/test_suite/gui_tests/CMakeLists.txt
+++ b/test_suite/gui_tests/CMakeLists.txt
@@ -1,19 +1,5 @@
-# Add each GUI test category.
-foreach( gui_test_category
- )
-
- add_subdirectory(${gui_test_category})
-
-endforeach( gui_test_category )
-
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- PARENT_SCOPE
-)
-
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- PARENT_SCOPE
-)
+# Add each GUI test category.
+# (No subcategories currently.)
diff --git a/test_suite/simgear_tests/CMakeLists.txt b/test_suite/simgear_tests/CMakeLists.txt
index d49ef2e2f..7a85dac87 100644
--- a/test_suite/simgear_tests/CMakeLists.txt
+++ b/test_suite/simgear_tests/CMakeLists.txt
@@ -2,26 +2,12 @@
# SPDX-FileCopyrightText: 2020 Edward d'Auvergne
# Add each simgear test category.
-foreach( simgear_test_category
+foreach(simgear_test_category
math
props
canvas
structure
timing
)
-
add_subdirectory(${simgear_test_category})
-
-endforeach( simgear_test_category )
-
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- PARENT_SCOPE
-)
-
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- PARENT_SCOPE
-)
+endforeach()
diff --git a/test_suite/simgear_tests/canvas/CMakeLists.txt b/test_suite/simgear_tests/canvas/CMakeLists.txt
index d437cec8d..698df2a0b 100644
--- a/test_suite/simgear_tests/canvas/CMakeLists.txt
+++ b/test_suite/simgear_tests/canvas/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testCanvas.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testCanvas.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx testCanvas.cxx testCanvas.hxx)
+
+fg_add_test_suite(CanvasTests m)
diff --git a/test_suite/simgear_tests/math/CMakeLists.txt b/test_suite/simgear_tests/math/CMakeLists.txt
index 2f728b0c1..bb49a068b 100644
--- a/test_suite/simgear_tests/math/CMakeLists.txt
+++ b/test_suite/simgear_tests/math/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test-up.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testSGGeodesy.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx test-up.cxx testSGGeodesy.hxx)
+
+fg_add_test_suite(MathGeodesyTests m)
diff --git a/test_suite/simgear_tests/props/CMakeLists.txt b/test_suite/simgear_tests/props/CMakeLists.txt
index 9dcb3e6bd..92e36d58d 100644
--- a/test_suite/simgear_tests/props/CMakeLists.txt
+++ b/test_suite/simgear_tests/props/CMakeLists.txt
@@ -1,14 +1,10 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_props.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_condition.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_props.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_condition.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_props.cxx test_condition.cxx
+ test_props.hxx test_condition.hxx
)
+
+fg_add_test_suite(SimgearPropsTests m)
+fg_add_test_suite(SimgearConditionTests m)
diff --git a/test_suite/simgear_tests/structure/CMakeLists.txt b/test_suite/simgear_tests/structure/CMakeLists.txt
index 4bfed8b71..d2e9bc78b 100644
--- a/test_suite/simgear_tests/structure/CMakeLists.txt
+++ b/test_suite/simgear_tests/structure/CMakeLists.txt
@@ -1,17 +1,10 @@
# SPDX-FileCopyrightText: 2020 James Turner <ja...@fl...>
# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_binding.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_event.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_binding.cxx test_event.cxx
+ test_binding.hxx test_event.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_binding.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_event.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(SimgearEventTests m)
+fg_add_test_suite(SimgearBindingTests m)
diff --git a/test_suite/simgear_tests/timing/CMakeLists.txt b/test_suite/simgear_tests/timing/CMakeLists.txt
index ab4fb9524..e9beac851 100644
--- a/test_suite/simgear_tests/timing/CMakeLists.txt
+++ b/test_suite/simgear_tests/timing/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_SGTime.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_SGTime.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx test_SGTime.cxx test_SGTime.hxx)
+
+fg_add_test_suite(SimgearTimingTests m)
diff --git a/test_suite/simgear_tests/timing/test_SGTime.cxx b/test_suite/simgear_tests/timing/test_SGTime.cxx
index a28b3e3c5..9e676dd6e 100644
--- a/test_suite/simgear_tests/timing/test_SGTime.cxx
+++ b/test_suite/simgear_tests/timing/test_SGTime.cxx
@@ -34,12 +34,12 @@ void SimgearTimingTests::testBadZoneDetectPosition()
if (rootPath.isNull()) {
return;
}
-
- std::unique_ptr<SGTime> t(new SGTime{rootPath});
-
+
+ std::unique_ptr<SGTime> t(new SGTime{rootPath / "Timezone"});
+
const auto goodPos = SGGeod::fromDeg(-69.5, 12.0);
CPPUNIT_ASSERT(t->updateLocal(goodPos, rootPath / "Timezone"));
-
+
// discovered while flying with the Shuttle, but actually
// can happen at sea level.
// https://sourceforge.net/p/flightgear/codetickets/2780/
diff --git a/test_suite/system_tests/CMakeLists.txt b/test_suite/system_tests/CMakeLists.txt
index 054becdc8..26f3184e2 100644
--- a/test_suite/system_tests/CMakeLists.txt
+++ b/test_suite/system_tests/CMakeLists.txt
@@ -1,24 +1,13 @@
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
+
# Add each system test category.
-foreach( system_test_category
+foreach(system_test_category
FDM
Instrumentation
Navaids
Main
subsystems
)
-
add_subdirectory(${system_test_category})
-
-endforeach( system_test_category )
-
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- PARENT_SCOPE
-)
-
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- PARENT_SCOPE
-)
+endforeach()
diff --git a/test_suite/system_tests/FDM/CMakeLists.txt b/test_suite/system_tests/FDM/CMakeLists.txt
index 4bbf525c2..daec30792 100644
--- a/test_suite/system_tests/FDM/CMakeLists.txt
+++ b/test_suite/system_tests/FDM/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testAeroMesh.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testAeroMesh.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx testAeroMesh.cxx testAeroMesh.hxx)
+
+fg_add_test_suite(AeroMeshTests s)
diff --git a/test_suite/system_tests/Instrumentation/CMakeLists.txt b/test_suite/system_tests/Instrumentation/CMakeLists.txt
index 3cc2157ba..b9045ccf5 100644
--- a/test_suite/system_tests/Instrumentation/CMakeLists.txt
+++ b/test_suite/system_tests/Instrumentation/CMakeLists.txt
@@ -1,12 +1,9 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- #${CMAKE_CURRENT_SOURCE_DIR}/testgps.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- #${CMAKE_CURRENT_SOURCE_DIR}/testgps.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ #testgps.cxx
)
+
+#fg_add_test_suite(GPSTests s)
diff --git a/test_suite/system_tests/Main/CMakeLists.txt b/test_suite/system_tests/Main/CMakeLists.txt
index c1c4cfe6e..c63f03cdc 100644
--- a/test_suite/system_tests/Main/CMakeLists.txt
+++ b/test_suite/system_tests/Main/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testOptions.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testOptions.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx testOptions.cxx testOptions.hxx)
+
+fg_add_test_suite(OptionsTests s)
diff --git a/test_suite/system_tests/Navaids/CMakeLists.txt b/test_suite/system_tests/Navaids/CMakeLists.txt
index 5d0c73755..4145ea7b5 100644
--- a/test_suite/system_tests/Navaids/CMakeLists.txt
+++ b/test_suite/system_tests/Navaids/CMakeLists.txt
@@ -1,12 +1,9 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- #${CMAKE_CURRENT_SOURCE_DIR}/testnavs.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- #${CMAKE_CURRENT_SOURCE_DIR}/testnavs.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ #testnavs.cxx
)
+
+#fg_add_test_suite(NavaidsTests s)
diff --git a/test_suite/system_tests/subsystems/CMakeLists.txt b/test_suite/system_tests/subsystems/CMakeLists.txt
index 416cffc2e..4bb11e2fb 100644
--- a/test_suite/system_tests/subsystems/CMakeLists.txt
+++ b/test_suite/system_tests/subsystems/CMakeLists.txt
@@ -1,14 +1,11 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_instanced_creation.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_noninstanced_creation.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_instanced_creation.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_noninstanced_creation.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ test_instanced_creation.cxx test_noninstanced_creation.cxx
+ test_instanced_creation.hxx test_noninstanced_creation.hxx
)
+
+fg_add_test_suite(InstancedSubsystemTests s)
+fg_add_test_suite(NonInstancedSubsystemTests s)
diff --git a/test_suite/unit_tests/AI/CMakeLists.txt b/test_suite/unit_tests/AI/CMakeLists.txt
index 20a96c09a..d2d4153df 100644
--- a/test_suite/unit_tests/AI/CMakeLists.txt
+++ b/test_suite/unit_tests/AI/CMakeLists.txt
@@ -1,27 +1,26 @@
# SPDX-FileCopyrightText: (C) 2020 James Turner <ja...@fl...>
# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AIFlightPlan.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AIManager.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AirportGroundRadar.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_traffic.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_TrafficMgr.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_submodels.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_VectorMath.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ test_AIFlightPlan.cxx
+ test_AIManager.cxx
+ test_AirportGroundRadar.cxx
+ test_traffic.cxx
+ test_TrafficMgr.cxx
+ test_submodels.cxx
+ test_VectorMath.cxx
+ test_AIFlightPlan.hxx
+ test_AIManager.hxx
+ test_AirportGroundRadar.hxx
+ test_traffic.hxx
+ test_TrafficMgr.hxx
+ test_submodels.hxx
+ test_VectorMath.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AIFlightPlan.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AIManager.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AirportGroundRadar.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_traffic.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_TrafficMgr.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_submodels.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_VectorMath.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(AIFlightPlanTests u)
+fg_add_test_suite(AIManagerTests u)
+fg_add_test_suite(AirportGroundRadarTests u)
+fg_add_test_suite(SubmodelsTests u)
+fg_add_test_suite(VectorMathTests u)
diff --git a/test_suite/unit_tests/ATC/CMakeLists.txt b/test_suite/unit_tests/ATC/CMakeLists.txt
index b11197664..6303eda5a 100644
--- a/test_suite/unit_tests/ATC/CMakeLists.txt
+++ b/test_suite/unit_tests/ATC/CMakeLists.txt
@@ -1,15 +1,10 @@
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_ATCController.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_Quadtree.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_ATCController.cxx test_Quadtree.cxx
+ test_ATCController.hxx test_Quadtree.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_ATCController.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_Quadtree.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(QuadtreeTests u)
+fg_add_test_suite(ATCControllerTests u)
diff --git a/test_suite/unit_tests/Add-ons/CMakeLists.txt b/test_suite/unit_tests/Add-ons/CMakeLists.txt
index 7bea20402..8a8da5b03 100644
--- a/test_suite/unit_tests/Add-ons/CMakeLists.txt
+++ b/test_suite/unit_tests/Add-ons/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AddonManagement.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_AddonManagement.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx test_AddonManagement.cxx test_AddonManagement.hxx)
+
+fg_add_test_suite(AddonManagementTests u)
diff --git a/test_suite/unit_tests/Aircraft/CMakeLists.txt b/test_suite/unit_tests/Aircraft/CMakeLists.txt
index 336934854..1e4604c00 100644
--- a/test_suite/unit_tests/Aircraft/CMakeLists.txt
+++ b/test_suite/unit_tests/Aircraft/CMakeLists.txt
@@ -1,17 +1,10 @@
# SPDX-FileCopyrightText: (C) 2025 James Turner <ja...@fl...>
# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_controls.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_history.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_controls.cxx test_history.cxx
+ test_controls.hxx test_history.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_controls.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_history.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(ControlsTests u)
+fg_add_test_suite(HistoryTests u)
diff --git a/test_suite/unit_tests/Airports/CMakeLists.txt b/test_suite/unit_tests/Airports/CMakeLists.txt
index 3db5e954e..232777f82 100644
--- a/test_suite/unit_tests/Airports/CMakeLists.txt
+++ b/test_suite/unit_tests/Airports/CMakeLists.txt
@@ -1,20 +1,11 @@
# SPDX-FileCopyrightText: (C) 2018 Edward d'Auvergne
# SPDX-License-Identifier: GPL-2.0-or-later
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_airport.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_groundnet.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_runway.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_airport.cxx test_groundnet.cxx test_runway.cxx
+ test_airport.hxx test_groundnet.hxx test_runway.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_airport.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_groundnet.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_runway.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(AirportTests u)
+fg_add_test_suite(GroundnetTests u)
+fg_add_test_suite(RunwayTests u)
diff --git a/test_suite/unit_tests/Autopilot/CMakeLists.txt b/test_suite/unit_tests/Autopilot/CMakeLists.txt
index 3b7738c64..43ebfd568 100644
--- a/test_suite/unit_tests/Autopilot/CMakeLists.txt
+++ b/test_suite/unit_tests/Autopilot/CMakeLists.txt
@@ -1,20 +1,15 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testDigitalFilter.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testPidController.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testPidControllerData.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testInputValue.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testMonostable.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testDigitalFilter.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testPidController.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testPidControllerData.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testInputValue.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testMonostable.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ testDigitalFilter.cxx testPidController.cxx testPidControllerData.cxx
+ testInputValue.cxx testMonostable.cxx
+ testDigitalFilter.hxx testPidController.hxx testPidControllerData.hxx
+ testInputValue.hxx testMonostable.hxx
)
+
+fg_add_test_suite(MonostableTests u)
+fg_add_test_suite(DigitalFilterTests u)
+fg_add_test_suite(PidControllerTests u)
+fg_add_test_suite(InputValueTests u)
diff --git a/test_suite/unit_tests/CMakeLists.txt b/test_suite/unit_tests/CMakeLists.txt
index ea5e10790..1b3581698 100644
--- a/test_suite/unit_tests/CMakeLists.txt
+++ b/test_suite/unit_tests/CMakeLists.txt
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Add each unit test category.
-foreach( unit_test_category
+foreach(unit_test_category
Add-ons
Aircraft
general
@@ -20,19 +20,5 @@ foreach( unit_test_category
GUI
Translations
)
-
add_subdirectory(${unit_test_category})
-
-endforeach( unit_test_category )
-
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- PARENT_SCOPE
-)
-
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- PARENT_SCOPE
-)
+endforeach()
diff --git a/test_suite/unit_tests/FDM/CMakeLists.txt b/test_suite/unit_tests/FDM/CMakeLists.txt
index e9ad4b42d..d7382f683 100644
--- a/test_suite/unit_tests/FDM/CMakeLists.txt
+++ b/test_suite/unit_tests/FDM/CMakeLists.txt
@@ -1,21 +1,13 @@
# SPDX-FileCopyrightText: 2018 Edware d'Auvergne
# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testAeroElement.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testFGInterface.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testYASimAtmosphere.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testYASimGear.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ testAeroElement.cxx testFGInterface.cxx testYASimAtmosphere.cxx testYASimGear.cxx
+ testAeroElement.hxx testFGInterface.hxx testYASimAtmosphere.hxx testYASimGear.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testAeroElement.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testFGInterface.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testYASimAtmosphere.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testYASimGear.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(AeroElementTests u)
+fg_add_test_suite(YASimAtmosphereTests u)
+fg_add_test_suite(YASimGearTests u)
+fg_add_test_suite(FGInterfaceTests u)
diff --git a/test_suite/unit_tests/GUI/CMakeLists.txt b/test_suite/unit_tests/GUI/CMakeLists.txt
index 8341e6397..649a371a6 100644
--- a/test_suite/unit_tests/GUI/CMakeLists.txt
+++ b/test_suite/unit_tests/GUI/CMakeLists.txt
@@ -1,12 +1,6 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_xmlDialog.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2010 James Turner
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_xmlDialog.hxx
- PARENT_SCOPE
-)
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx test_xmlDialog.cxx test_xmlDialog.hxx)
+
+fg_add_test_suite(XMLDialogTests u)
diff --git a/test_suite/unit_tests/Input/CMakeLists.txt b/test_suite/unit_tests/Input/CMakeLists.txt
index 758045d2e..9666c4804 100644
--- a/test_suite/unit_tests/Input/CMakeLists.txt
+++ b/test_suite/unit_tests/Input/CMakeLists.txt
@@ -1,22 +1,13 @@
# SPDX-FileCopyrightText: (C) 2025 James Turner <ja...@fl...>
# SPDX-License-Identifier: GPL-2.0-or-later
-if(ENABLE_HID_INPUT)
- set(HID_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/test_hidinput.cxx)
- set(HID_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/test_hidinput.hxx)
-endif()
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_inputDevice.cxx
- ${HID_SOURCE}
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_inputDevice.cxx test_inputDevice.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_inputDevice.hxx
- ${HID_HEADER}
- PARENT_SCOPE
-)
+fg_add_test_suite(InputDeviceTests u)
+
+if(ENABLE_HID_INPUT)
+ target_sources(fgfs_test_suite PRIVATE test_hidinput.cxx test_hidinput.hxx)
+ fg_add_test_suite(HIDInputTests u)
+endif()
diff --git a/test_suite/unit_tests/Instrumentation/CMakeLists.txt b/test_suite/unit_tests/Instrumentation/CMakeLists.txt
index 4e5f68f2f..350cbfb7f 100644
--- a/test_suite/unit_tests/Instrumentation/CMakeLists.txt
+++ b/test_suite/unit_tests/Instrumentation/CMakeLists.txt
@@ -1,26 +1,19 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_navRadio.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_gps.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_hold_controller.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_rnav_procedures.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_dme.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_commRadio.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_transponder.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_headingIndicator.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_navRadio.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_gps.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_hold_controller.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_rnav_procedures.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_dme.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_commRadio.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_transponder.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_headingIndicator.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ test_navRadio.cxx test_gps.cxx test_hold_controller.cxx test_rnav_procedures.cxx
+ test_dme.cxx test_commRadio.cxx test_transponder.cxx test_headingIndicator.cxx
+ test_navRadio.hxx test_gps.hxx test_hold_controller.hxx test_rnav_procedures.hxx
+ test_dme.hxx test_commRadio.hxx test_transponder.hxx test_headingIndicator.hxx
)
+
+fg_add_test_suite(NavRadioTests u)
+fg_add_test_suite(GPSTests u)
+fg_add_test_suite(HoldControllerTests u)
+fg_add_test_suite(RNAVProcedureTests u)
+fg_add_test_suite(DMEReceiverTests u)
+fg_add_test_suite(CommRadioTests u)
+fg_add_test_suite(TransponderTests u)
+fg_add_test_suite(HeadingIndicatorTests u)
diff --git a/test_suite/unit_tests/Main/CMakeLists.txt b/test_suite/unit_tests/Main/CMakeLists.txt
index 646a1d6af..ceb21b7cf 100644
--- a/test_suite/unit_tests/Main/CMakeLists.txt
+++ b/test_suite/unit_tests/Main/CMakeLists.txt
@@ -1,20 +1,16 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_autosaveMigration.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_FGLocale.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_posinit.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_timeManager.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_commands.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_autosaveMigration.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_FGLocale.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_posinit.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_timeManager.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_commands.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ test_autosaveMigration.cxx test_FGLocale.cxx test_posinit.cxx
+ test_timeManager.cxx test_commands.cxx
+ test_autosaveMigration.hxx test_FGLocale.hxx test_posinit.hxx
+ test_timeManager.hxx test_commands.hxx
)
+
+fg_add_test_suite(AutosaveMigrationTests u)
+fg_add_test_suite(FGLocaleTests u)
+fg_add_test_suite(PosInitTests u)
+fg_add_test_suite(TimeManagerTests u)
+fg_add_test_suite(CommandsTests u)
diff --git a/test_suite/unit_tests/Navaids/CMakeLists.txt b/test_suite/unit_tests/Navaids/CMakeLists.txt
index cc6ec4d0c..c05a3f4d3 100644
--- a/test_suite/unit_tests/Navaids/CMakeLists.txt
+++ b/test_suite/unit_tests/Navaids/CMakeLists.txt
@@ -1,19 +1,16 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_flightplan.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_fpNasal.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_navaids2.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_aircraftPerformance.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_routeManager.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_flightplan.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_fpNasal.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_aircraftPerformance.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_routeManager.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ test_flightplan.cxx test_fpNasal.cxx test_navaids2.cxx
+ test_aircraftPerformance.cxx test_routeManager.cxx
+ test_flightplan.hxx test_fpNasal.hxx
+ test_aircraftPerformance.hxx test_routeManager.hxx
)
+
+fg_add_test_suite(FlightplanTests u)
+fg_add_test_suite(FPNasalTests u)
+fg_add_test_suite(NavaidsTests u)
+fg_add_test_suite(AircraftPerformanceTests u)
+fg_add_test_suite(RouteManagerTests u)
diff --git a/test_suite/unit_tests/Network/CMakeLists.txt b/test_suite/unit_tests/Network/CMakeLists.txt
index 9f8ed2ace..d0bc758ff 100644
--- a/test_suite/unit_tests/Network/CMakeLists.txt
+++ b/test_suite/unit_tests/Network/CMakeLists.txt
@@ -1,28 +1,13 @@
-
-
-if (ENABLE_SWIFT)
- set(SWIFT_TESTS_SOURCES
- ${CMAKE_CURRENT_SOURCE_DIR}/test_swiftService.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_swiftAircraftManager.cxx
- )
-
- set(SWIFT_TESTS_HEADERS
- ${CMAKE_CURRENT_SOURCE_DIR}/test_swiftService.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_swiftAircraftManager.hxx
- )
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+target_sources(fgfs_test_suite PRIVATE TestSuite.cxx)
+
+if(ENABLE_SWIFT)
+ target_sources(fgfs_test_suite PRIVATE
+ test_swiftService.cxx test_swiftAircraftManager.cxx
+ test_swiftService.hxx test_swiftAircraftManager.hxx
+ )
+ fg_add_test_suite(SwiftAircraftManagerTest u)
+ fg_add_test_suite(SwiftServiceTest u)
endif()
-
-
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${SWIFT_TESTS_SOURCES}
- PARENT_SCOPE
- )
-
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${SWIFT_TESTS_HEADERS}
- PARENT_SCOPE
- )
-
diff --git a/test_suite/unit_tests/Scripting/CMakeLists.txt b/test_suite/unit_tests/Scripting/CMakeLists.txt
index cdcd519a2..bc29fa379 100644
--- a/test_suite/unit_tests/Scripting/CMakeLists.txt
+++ b/test_suite/unit_tests/Scripting/CMakeLists.txt
@@ -1,23 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# SPDX-FileCopyrightText: (C) 2015 Edward d'Auvergne
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testNasalSys.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testNasalLib.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testGC.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/benchmarkPropsAccess.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testVector.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx
+ testNasalSys.cxx testNasalLib.cxx testGC.cxx benchmarkPropsAccess.cxx testVector.cxx
+ testNasalSys.hxx testNasalLib.hxx testGC.hxx benchmarkPropsAccess.hxx testVector.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/testNasalSys.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testNasalLib.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testGC.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/benchmarkPropsAccess.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/testVector.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(NasalSysTests u)
+fg_add_test_suite(NasalGCTests u)
+fg_add_test_suite(NasalLibTests u)
+fg_add_test_suite(BenchmarkPropsAccess u)
+fg_add_test_suite(VectorTests u)
diff --git a/test_suite/unit_tests/Translations/CMakeLists.txt b/test_suite/unit_tests/Translations/CMakeLists.txt
index a4e979631..36c48c3a7 100644
--- a/test_suite/unit_tests/Translations/CMakeLists.txt
+++ b/test_suite/unit_tests/Translations/CMakeLists.txt
@@ -1,17 +1,10 @@
# SPDX-FileCopyrightText: 2025 Florent Rougon
# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_FGTranslate.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_TranslationResource.cxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test_FGTranslate.cxx test_TranslationResource.cxx
+ test_FGTranslate.hxx test_TranslationResource.hxx
)
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test_FGTranslate.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_TranslationResource.hxx
- PARENT_SCOPE
-)
+fg_add_test_suite(FGTranslateTests u)
+fg_add_test_suite(TranslationResourceTests u)
diff --git a/test_suite/unit_tests/general/CMakeLists.txt b/test_suite/unit_tests/general/CMakeLists.txt
index f78d02ac9..712e15c90 100644
--- a/test_suite/unit_tests/general/CMakeLists.txt
+++ b/test_suite/unit_tests/general/CMakeLists.txt
@@ -1,14 +1,10 @@
-set(TESTSUITE_SOURCES
- ${TESTSUITE_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test-mktime.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_Views.cxx
- PARENT_SCOPE
-)
+# SPDX-FileCopyrightText: 2016 Edward d'Auvergne
+# SPDX-License-Identifier: GPL-2.0-or-later
-set(TESTSUITE_HEADERS
- ${TESTSUITE_HEADERS}
- ${CMAKE_CURRENT_SOURCE_DIR}/test-mktime.hxx
- ${CMAKE_CURRENT_SOURCE_DIR}/test_Views.hxx
- PARENT_SCOPE
+target_sources(fgfs_test_suite PRIVATE
+ TestSuite.cxx test-mktime.cxx test_Views.cxx
+ test-mktime.hxx test_Views.hxx
)
+
+fg_add_test_suite(MktimeTests u)
+fg_add_test_suite(ViewsTests u)
|
|
From: <fli...@li...> - 2026-04-13 12:49:49
|
unknown user pushed a commit to branch next
in repository flightgear.
The following commit(s) were added to refs/heads/next by this push:
new 4367143f5 Adjust handling of log-level arg
4367143f5 is described below
SF URL: http://sourceforge.net/p/flightgear/flightgear/ci/4367143f5bc5e23e21c033a9e6e1e954ab5d5516/
Commit: 4367143f5bc5e23e21c033a9e6e1e954ab5d5516
Author: James Turner
Committer: James Turner
AuthorDate: Thu Apr 9 12:21:26 2026 +0100
Adjust handling of log-level arg
---
src/Main/fg_init.cxx | 8 +++-----
src/Main/fg_props.cxx | 15 ++++++---------
2 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx
index f62546260..5b9b31b41 100755
--- a/src/Main/fg_init.cxx
+++ b/src/Main/fg_init.cxx
@@ -577,11 +577,9 @@ void fgInitLogging(const std::string& pri)
fileLogLevel.set(SG_ALL, SG_INFO);
// https://sourceforge.net/p/flightgear/codetickets/2100/
if (!pri.empty()) {
- try {
- auto priVal = simgear::priorityFromString(pri);
- fileLogLevel.set(SG_ALL, priVal);
- } catch (std::exception&) {
- // let's not worry about this, and just log at INFO
+ const auto levels = simgear::parseLogSpecFromString(pri);
+ if (levels.has_value()) {
+ fileLogLevel = levels.value();
}
}
diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx
index fc719f5b5..90d85c149 100644
--- a/src/Main/fg_props.cxx
+++ b/src/Main/fg_props.cxx
@@ -73,15 +73,12 @@ getLoggingPriority ()
void
setLoggingPriority (const char * p)
{
- if (p == 0)
- return;
-
- const string ps = p;
- try {
- sglog().set_log_priority(simgear::priorityFromString(ps));
- } catch (std::exception& e) {
- SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority: " << ps);
- }
+ const auto levels = simgear::parseLogSpecFromString(p);
+ if (levels) {
+ sglog().setLogLevels(levels.value(), "console");
+ } else {
+ SG_LOG(SG_GENERAL, SG_ALERT, "Error parsing logging specification '" << p << "'");
+ }
}
|