From 528b0cc2556870ff4112df85042e596ed3161ab4 Mon Sep 17 00:00:00 2001 From: Lars Toenning Date: Tue, 12 Nov 2024 17:27:07 +0100 Subject: [PATCH] feat: Add MSFS support Co-Authored-By: Roland Rossgotterer Co-Authored-By: tzobler --- .../swift-plugin-simulators.xml | 3 + src/config/buildconfig.h | 3 + src/config/buildconfig.inc | 2 +- src/config/buildconfig_gen.inc.in | 7 +- src/core/fsd/fsdclient.cpp | 1 + .../components/configsimulatorcomponent.cpp | 6 + .../components/configsimulatorcomponent.ui | 7 + src/gui/components/dbownmodelscomponent.cpp | 57 +++++- src/gui/components/dbownmodelsetcomponent.cpp | 16 ++ .../distributorpreferencescomponent.cpp | 8 + src/gui/components/simulatorselector.cpp | 22 +- src/gui/components/simulatorselector.ui | 18 +- src/misc/simulation/aircraftmodel.cpp | 2 + src/misc/simulation/aircraftmodellist.h | 12 +- .../aircraftmodelloaderprovider.cpp | 5 + .../simulation/aircraftmodelloaderprovider.h | 2 + src/misc/simulation/aircraftmodelutils.cpp | 5 + src/misc/simulation/autopublishdata.cpp | 1 + src/misc/simulation/data/modelcaches.cpp | 27 ++- src/misc/simulation/data/modelcaches.h | 18 ++ src/misc/simulation/distributor.cpp | 8 +- src/misc/simulation/distributor.h | 1 + .../simulation/distributorlistpreferences.cpp | 2 + .../simulation/distributorlistpreferences.h | 2 + .../simulation/fscommon/aircraftcfgparser.cpp | 7 +- .../simulation/fscommon/aircraftcfgparser.h | 2 +- src/misc/simulation/fscommon/fscommon.h | 2 +- src/misc/simulation/fscommon/fscommonutil.cpp | 7 + src/misc/simulation/fscommon/fscommonutil.h | 8 +- .../simulation/fscommon/fsdirectories.cpp | 193 ++++++++++++++++++ src/misc/simulation/fscommon/fsdirectories.h | 33 +++ .../simulation/settings/simulatorsettings.cpp | 19 ++ .../simulation/settings/simulatorsettings.h | 16 ++ src/misc/simulation/simulatorinfo.cpp | 40 ++-- src/misc/simulation/simulatorinfo.h | 15 +- src/misc/simulation/simulatorinfolist.cpp | 1 + src/misc/simulation/simulatorplugininfo.cpp | 1 + src/plugins/simulator/CMakeLists.txt | 3 +- .../fsxcommon/simconnectdatadefinition.cpp | 19 +- .../fsxcommon/simconnectdatadefinition.h | 15 +- .../fsxcommon/simulatorfsxcommon.cpp | 78 ++++++- .../simulator/fsxcommon/simulatorfsxcommon.h | 7 + .../fsxcommon/simulatorfsxsimconnectproc.cpp | 6 + src/plugins/simulator/msfs/simulatormsfs.cpp | 16 -- src/plugins/simulator/msfs/simulatormsfs.json | 5 +- .../simulator/msfsconfig/CMakeLists.txt | 27 +++ .../msfsconfig/simulatormsfsconfig.cpp | 18 ++ .../msfsconfig/simulatormsfsconfig.h | 34 +++ .../msfsconfig/simulatormsfsconfig.json | 3 + .../simulatormsfsconfig.json.license | 3 + 50 files changed, 735 insertions(+), 78 deletions(-) create mode 100644 src/plugins/simulator/msfsconfig/CMakeLists.txt create mode 100644 src/plugins/simulator/msfsconfig/simulatormsfsconfig.cpp create mode 100644 src/plugins/simulator/msfsconfig/simulatormsfsconfig.h create mode 100644 src/plugins/simulator/msfsconfig/simulatormsfsconfig.json create mode 100644 src/plugins/simulator/msfsconfig/simulatormsfsconfig.json.license diff --git a/installer/installbuilder/swift-plugin-simulators.xml b/installer/installbuilder/swift-plugin-simulators.xml index 86f9aabb8..15ea38b8d 100644 --- a/installer/installbuilder/swift-plugin-simulators.xml +++ b/installer/installbuilder/swift-plugin-simulators.xml @@ -93,6 +93,9 @@ This plugin acts as the interface between swift and MSFS. ../../dist/bin/plugins/simulator/simulatormsfs.dll + + ../../dist/bin/plugins/simulator/simulatormsfsconfig.dll + diff --git a/src/config/buildconfig.h b/src/config/buildconfig.h index a5bf357df..55606eee4 100644 --- a/src/config/buildconfig.h +++ b/src/config/buildconfig.h @@ -38,6 +38,9 @@ namespace swift::config //! with FG support? static constexpr bool isCompiledWithFGSupport(); // defined in buildconfig_gen.inc.in + //! with MSFS support? + static constexpr bool isCompiledWithMSFSSupport(); // defined in buildconfig_gen.inc.in + //! with FSUIPC support? static constexpr bool isCompiledWithFsuipcSupport(); // defined in buildconfig_gen.inc.in diff --git a/src/config/buildconfig.inc b/src/config/buildconfig.inc index 19b9a8d33..4fe255d02 100644 --- a/src/config/buildconfig.inc +++ b/src/config/buildconfig.inc @@ -14,7 +14,7 @@ namespace swift::config { constexpr bool CBuildConfig::isCompiledWithMsFlightSimulatorSupport() { - return CBuildConfig::isCompiledWithFs9Support() || CBuildConfig::isCompiledWithFsxSupport() || CBuildConfig::isCompiledWithP3DSupport(); + return CBuildConfig::isCompiledWithFs9Support() || CBuildConfig::isCompiledWithFsxSupport() || CBuildConfig::isCompiledWithP3DSupport() || isCompiledWithMSFSSupport(); } constexpr bool CBuildConfig::isCompiledWithFlightSimulatorSupport() diff --git a/src/config/buildconfig_gen.inc.in b/src/config/buildconfig_gen.inc.in index 9215abe01..4e9af4d24 100644 --- a/src/config/buildconfig_gen.inc.in +++ b/src/config/buildconfig_gen.inc.in @@ -40,7 +40,7 @@ constexpr bool swift::config::CBuildConfig::isCompiledWithFsxSupport() constexpr bool swift::config::CBuildConfig::isCompiledWithFsuipcSupport() { - return isCompiledWithFsxSupport() || isCompiledWithP3DSupport() || isCompiledWithFs9Support() || SWIFTCONFIG_${SWIFT_BUILD_MSFS_PLUGIN}; + return isCompiledWithFsxSupport() || isCompiledWithP3DSupport() || isCompiledWithFs9Support() || isCompiledWithMSFSSupport(); } constexpr bool swift::config::CBuildConfig::isCompiledWithXPlaneSupport() @@ -53,6 +53,11 @@ constexpr bool swift::config::CBuildConfig::isCompiledWithFGSupport() return SWIFTCONFIG_${SWIFT_BUILD_FLIGHTGEAR_PLUGIN}; } +constexpr bool swift::config::CBuildConfig::isCompiledWithMSFSSupport() +{ + return SWIFTCONFIG_${SWIFT_BUILD_MSFS_PLUGIN}; +} + constexpr bool swift::config::CBuildConfig::isCompiledWithGui() { return SWIFTCONFIG_${SWIFT_BUILD_GUI}; diff --git a/src/core/fsd/fsdclient.cpp b/src/core/fsd/fsdclient.cpp index e828d5c40..8b099d2be 100644 --- a/src/core/fsd/fsdclient.cpp +++ b/src/core/fsd/fsdclient.cpp @@ -213,6 +213,7 @@ namespace swift::core::fsd case CSimulatorInfo::FS9: m_simType = SimType::MSFS2004; break; case CSimulatorInfo::FG: m_simType = SimType::FlightGear; break; case CSimulatorInfo::XPLANE: m_simType = SimType::XPLANE11; break; + case CSimulatorInfo::MSFS: m_simType = SimType::MSFS; break; default: m_simType = SimType::Unknown; break; } m_simTypeInfo = CSimulatorInfo(simulator); diff --git a/src/gui/components/configsimulatorcomponent.cpp b/src/gui/components/configsimulatorcomponent.cpp index afe9777a5..cce27084b 100644 --- a/src/gui/components/configsimulatorcomponent.cpp +++ b/src/gui/components/configsimulatorcomponent.cpp @@ -56,6 +56,7 @@ namespace swift::gui::components const bool p3d = (sims.isP3D() || !CFsDirectories::p3dDir().isEmpty()) && CBuildConfig::isCompiledWithP3DSupport(); const bool fsx = (sims.isFSX() || !CFsDirectories::fsxDir().isEmpty()) && CBuildConfig::isCompiledWithFsxSupport(); const bool fs9 = (sims.isFS9() || !CFsDirectories::fs9Dir().isEmpty()) && CBuildConfig::isCompiledWithFs9Support(); + const bool msfs = (sims.isMSFS() || !CFsDirectories::msfsDir().isEmpty()) && CBuildConfig::isCompiledWithMSFSSupport(); const bool xp = sims.isXPlane() && CBuildConfig::isCompiledWithXPlaneSupport(); const bool fg = sims.isFG() && CBuildConfig::isCompiledWithFGSupport(); @@ -64,24 +65,28 @@ namespace swift::gui::components ui->cb_FS9->setChecked(fs9); ui->cb_XP->setChecked(xp); ui->cb_FG->setChecked(fg); + ui->cb_MSFS->setChecked(msfs); ui->cb_P3D->setEnabled(CBuildConfig::isCompiledWithP3DSupport()); ui->cb_FSX->setEnabled(CBuildConfig::isCompiledWithFsxSupport()); ui->cb_FS9->setEnabled(CBuildConfig::isCompiledWithFs9Support()); ui->cb_XP->setEnabled(CBuildConfig::isCompiledWithXPlaneSupport()); ui->cb_FG->setEnabled(CBuildConfig::isCompiledWithFGSupport()); + ui->cb_MSFS->setEnabled(CBuildConfig::isCompiledWithMSFSSupport()); CGuiUtility::checkBoxReadOnly(ui->cb_P3D, !CBuildConfig::isCompiledWithP3DSupport()); CGuiUtility::checkBoxReadOnly(ui->cb_FSX, !CBuildConfig::isCompiledWithFsxSupport()); CGuiUtility::checkBoxReadOnly(ui->cb_FS9, !CBuildConfig::isCompiledWithFs9Support()); CGuiUtility::checkBoxReadOnly(ui->cb_XP, !CBuildConfig::isCompiledWithXPlaneSupport()); CGuiUtility::checkBoxReadOnly(ui->cb_FG, !CBuildConfig::isCompiledWithFGSupport()); + CGuiUtility::checkBoxReadOnly(ui->cb_MSFS, !CBuildConfig::isCompiledWithMSFSSupport()); if (p3d) { ui->comp_SettingsSimulator->setSimulator(CSimulatorInfo(CSimulatorInfo::P3D)); } else if (fsx) { ui->comp_SettingsSimulator->setSimulator(CSimulatorInfo(CSimulatorInfo::FSX)); } else if (fs9) { ui->comp_SettingsSimulator->setSimulator(CSimulatorInfo(CSimulatorInfo::FS9)); } else if (xp) { ui->comp_SettingsSimulator->setSimulator(CSimulatorInfo(CSimulatorInfo::XPLANE)); } else if (fg) { ui->comp_SettingsSimulator->setSimulator(CSimulatorInfo(CSimulatorInfo::FG)); } + else if (msfs) { ui->comp_SettingsSimulator->setSimulator(CSimulatorInfo(CSimulatorInfo::MSFS)); } } QStringList CConfigSimulatorComponent::selectedSimsToPluginIds() @@ -94,6 +99,7 @@ namespace swift::gui::components if (ui->cb_P3D->isChecked()) { ids << CSimulatorPluginInfo::p3dPluginIdentifier(); } if (ui->cb_XP->isChecked()) { ids << CSimulatorPluginInfo::xplanePluginIdentifier(); } if (ui->cb_FG->isChecked()) { ids << CSimulatorPluginInfo::fgPluginIdentifier(); } + if (ui->cb_MSFS->isChecked()) { ids << CSimulatorPluginInfo::msfsPluginIdentifier(); } return ids; } diff --git a/src/gui/components/configsimulatorcomponent.ui b/src/gui/components/configsimulatorcomponent.ui index b159d7bdc..5d91c1b22 100644 --- a/src/gui/components/configsimulatorcomponent.ui +++ b/src/gui/components/configsimulatorcomponent.ui @@ -85,6 +85,13 @@ + + + + MSFS (64-bit) + + + diff --git a/src/gui/components/dbownmodelscomponent.cpp b/src/gui/components/dbownmodelscomponent.cpp index c593cf4a0..43bde4a10 100644 --- a/src/gui/components/dbownmodelscomponent.cpp +++ b/src/gui/components/dbownmodelscomponent.cpp @@ -309,7 +309,7 @@ namespace swift::gui::components QPointer ownModelsComp(qobject_cast(this->parent())); Q_ASSERT_X(ownModelsComp, Q_FUNC_INFO, "Cannot access parent"); - if (m_loadActions.isEmpty()) { m_loadActions = QList({ nullptr, nullptr, nullptr, nullptr, nullptr }); } + if (m_loadActions.isEmpty()) { m_loadActions = QList({ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }); } menuActions.addMenuSimulator(); if (sims.isFSX()) { @@ -376,12 +376,25 @@ namespace swift::gui::components } menuActions.addAction(m_loadActions[4], CMenuAction::pathSimulator()); } + if (sims.isMSFS()) + { + if (!m_loadActions[5]) + { + m_loadActions[5] = new QAction(CIcons::appModels16(), "MSFS models", this); + connect(m_loadActions[5], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked) { + if (!ownModelsComp) { return; } + Q_UNUSED(checked) + ownModelsComp->setSimulator(CSimulatorInfo::msfs(), true); + }); + } + menuActions.addAction(m_loadActions[5], CMenuAction::pathSimulator()); + } // with models loaded I allow a refresh reload // I need those models because I want to merge with DB data in the loader if (sGui && sGui->getWebDataServices() && sGui->getWebDataServices()->getModelsCount() > 0) { - if (m_reloadActions.isEmpty()) { m_reloadActions = QList({ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }); } + if (m_reloadActions.isEmpty()) { m_reloadActions = QList({ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }); } menuActions.addMenu(CIcons::refresh16(), "Force model reload", CMenuAction::pathSimulatorModelsReload()); if (sims.isFSX()) { @@ -512,6 +525,31 @@ namespace swift::gui::components menuActions.addAction(m_reloadActions[8], CMenuAction::pathSimulatorModelsReload()); menuActions.addAction(m_reloadActions[9], CMenuAction::pathSimulatorModelsReload()); } + if (sims.isMSFS()) + { + if (!m_reloadActions[10]) + { + m_reloadActions[10] = new QAction(CIcons::appModels16(), "MSFS models", this); + connect(m_reloadActions[10], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked) { + if (!ownModelsComp) { return; } + Q_UNUSED(checked) + ownModelsComp->requestSimulatorModels(CSimulatorInfo::msfs(), IAircraftModelLoader::InBackgroundNoCache); + }); + m_reloadActions[11] = new QAction(CIcons::appModels16(), "MSFS models from directoy", this); + connect(m_reloadActions[11], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked) { + if (!ownModelsComp) { return; } + Q_UNUSED(checked) + const CSimulatorInfo sim(CSimulatorInfo::MSFS); + const QString dir = ownModelsComp->directorySelector(sim); + if (!dir.isEmpty()) + { + ownModelsComp->requestSimulatorModels(sim, IAircraftModelLoader::InBackgroundNoCache, QStringList(dir)); + } + }); + } + menuActions.addAction(m_reloadActions[10], CMenuAction::pathSimulatorModelsReload()); + menuActions.addAction(m_reloadActions[11], CMenuAction::pathSimulatorModelsReload()); + } } else { @@ -520,7 +558,7 @@ namespace swift::gui::components a.setActionEnabled(false); // gray out } - if (m_clearCacheActions.isEmpty()) { m_clearCacheActions = QList({ nullptr, nullptr, nullptr, nullptr, nullptr }); } + if (m_clearCacheActions.isEmpty()) { m_clearCacheActions = QList({ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }); } menuActions.addMenu(CIcons::delete16(), "Clear model caches", CMenuAction::pathSimulatorModelsClearCache()); if (sims.isFSX()) { @@ -587,6 +625,19 @@ namespace swift::gui::components } menuActions.addAction(m_clearCacheActions[4], CMenuAction::pathSimulatorModelsClearCache()); } + if (sims.isMSFS()) + { + if (!m_clearCacheActions[5]) + { + m_clearCacheActions[5] = new QAction(CIcons::appModels16(), "Clear MSFS cache", this); + connect(m_clearCacheActions[5], &QAction::triggered, ownModelsComp, [ownModelsComp](bool checked) { + if (!ownModelsComp) { return; } + Q_UNUSED(checked) + ownModelsComp->clearSimulatorCache(CSimulatorInfo::msfs()); + }); + } + menuActions.addAction(m_clearCacheActions[5], CMenuAction::pathSimulatorModelsClearCache()); + } if (sims.isXPlane() && CBuildConfig::isRunningOnWindowsNtPlatform() && CBuildConfig::buildWordSize() == 64) { diff --git a/src/gui/components/dbownmodelsetcomponent.cpp b/src/gui/components/dbownmodelsetcomponent.cpp index 6c03959f1..2423aa0cd 100644 --- a/src/gui/components/dbownmodelsetcomponent.cpp +++ b/src/gui/components/dbownmodelsetcomponent.cpp @@ -590,6 +590,22 @@ namespace swift::gui::components }); m_setNewActions.append(a); } + if (sims.isMSFS()) + { + QAction *a = new QAction(CIcons::appModels16(), "MSFS models", this); + connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) { + Q_UNUSED(checked) + ownModelSetComp->setSimulator(CSimulatorInfo(CSimulatorInfo::MSFS)); + }); + m_setActions.append(a); + + a = new QAction(CIcons::appModels16(), "New set MSFS models", this); + connect(a, &QAction::triggered, ownModelSetComp, [ownModelSetComp](bool checked) { + Q_UNUSED(checked) + ownModelSetComp->setModelSet(CAircraftModelList(), CSimulatorInfo(CSimulatorInfo::MSFS)); + }); + m_setNewActions.append(a); + } QAction *a = new QAction(CIcons::appDistributors16(), "Apply distributor preferences", this); connect(a, &QAction::triggered, ownModelSetComp, &CDbOwnModelSetComponent::distributorPreferencesChanged, Qt::QueuedConnection); diff --git a/src/gui/components/distributorpreferencescomponent.cpp b/src/gui/components/distributorpreferencescomponent.cpp index 59c74ecf3..599aafb70 100644 --- a/src/gui/components/distributorpreferencescomponent.cpp +++ b/src/gui/components/distributorpreferencescomponent.cpp @@ -121,6 +121,14 @@ namespace swift::gui::components preferences.setDistributors(distributors, simulator); const CStatusMessage m = m_distributorPreferences.setAndSave(preferences); CLogMessage::preformatted(m); + if (m.isSuccess()) + { + this->showOverlayHTMLMessage("Saved settings", 5000); + } + else + { + this->showOverlayMessage(m); + } } void CDistributorPreferencesComponent::onSimulatorChanged(const CSimulatorInfo &simulator) diff --git a/src/gui/components/simulatorselector.cpp b/src/gui/components/simulatorselector.cpp index 4297e9a02..109a2cefe 100644 --- a/src/gui/components/simulatorselector.cpp +++ b/src/gui/components/simulatorselector.cpp @@ -36,12 +36,14 @@ namespace swift::gui::components connect(ui->rb_P3D, &QRadioButton::toggled, this, &CSimulatorSelector::radioButtonChanged); connect(ui->rb_FG, &QRadioButton::toggled, this, &CSimulatorSelector::radioButtonChanged); connect(ui->rb_XPlane, &QRadioButton::toggled, this, &CSimulatorSelector::radioButtonChanged); + connect(ui->rb_MSFS, &QRadioButton::toggled, this, &CSimulatorSelector::radioButtonChanged); connect(ui->cb_FS9, &QRadioButton::toggled, this, &CSimulatorSelector::checkBoxChanged); connect(ui->cb_FSX, &QRadioButton::toggled, this, &CSimulatorSelector::checkBoxChanged); connect(ui->cb_P3D, &QRadioButton::toggled, this, &CSimulatorSelector::checkBoxChanged); connect(ui->cb_FG, &QRadioButton::toggled, this, &CSimulatorSelector::checkBoxChanged); connect(ui->cb_XPlane, &QRadioButton::toggled, this, &CSimulatorSelector::checkBoxChanged); + connect(ui->cb_MSFS, &QRadioButton::toggled, this, &CSimulatorSelector::checkBoxChanged); connect(ui->cb_Simulators, &QComboBox::currentTextChanged, this, &CSimulatorSelector::comboBoxChanged); } @@ -75,8 +77,8 @@ namespace swift::gui::components switch (m_mode) { default: - case CheckBoxes: return CSimulatorInfo(ui->cb_FSX->isChecked(), ui->cb_FS9->isChecked(), ui->cb_XPlane->isChecked(), ui->cb_P3D->isChecked(), ui->cb_FG->isChecked()); - case RadioButtons: return CSimulatorInfo(ui->rb_FSX->isChecked(), ui->rb_FS9->isChecked(), ui->rb_XPlane->isChecked(), ui->rb_P3D->isChecked(), ui->rb_FG->isChecked()); + case CheckBoxes: return CSimulatorInfo(ui->cb_FSX->isChecked(), ui->cb_FS9->isChecked(), ui->cb_XPlane->isChecked(), ui->cb_P3D->isChecked(), ui->cb_FG->isChecked(), ui->cb_MSFS->isChecked()); + case RadioButtons: return CSimulatorInfo(ui->rb_FSX->isChecked(), ui->rb_FS9->isChecked(), ui->rb_XPlane->isChecked(), ui->rb_P3D->isChecked(), ui->rb_FG->isChecked(), ui->rb_MSFS->isChecked()); case ComboBox: return CSimulatorInfo(ui->cb_Simulators->currentText()); } } @@ -92,6 +94,7 @@ namespace swift::gui::components ui->cb_XPlane->setChecked(simulator.isXPlane()); ui->cb_P3D->setChecked(simulator.isP3D()); ui->cb_FG->setChecked(simulator.isFG()); + ui->cb_MSFS->setChecked(simulator.isMSFS()); // Combo ui->cb_Simulators->setCurrentText(simulator.toQString(true)); @@ -122,6 +125,11 @@ namespace swift::gui::components ui->rb_FG->setChecked(simulator.isFG()); return; } + if (simulator.isMSFS()) + { + ui->rb_MSFS->setChecked(simulator.isMSFS()); + return; + } } void CSimulatorSelector::setToLastSelection() @@ -202,6 +210,7 @@ namespace swift::gui::components ui->cb_XPlane->setChecked(true); ui->cb_P3D->setChecked(true); ui->cb_FG->setChecked(true); + ui->cb_MSFS->setChecked(true); // radio ui->rb_P3D->setChecked(true); @@ -215,6 +224,7 @@ namespace swift::gui::components ui->cb_XPlane->setChecked(false); ui->cb_P3D->setChecked(false); ui->cb_FG->setChecked(false); + ui->cb_MSFS->setChecked(false); } bool CSimulatorSelector::isUnselected() const @@ -224,10 +234,10 @@ namespace swift::gui::components { default: case CheckBoxes: - c = ui->cb_FSX->isChecked() || ui->cb_FS9->isChecked() || ui->cb_XPlane->isChecked() || ui->cb_P3D->isChecked() || ui->cb_FG->isChecked(); + c = ui->cb_FSX->isChecked() || ui->cb_FS9->isChecked() || ui->cb_XPlane->isChecked() || ui->cb_P3D->isChecked() || ui->cb_FG->isChecked() || ui->cb_MSFS->isChecked(); break; case RadioButtons: - c = ui->rb_FSX->isChecked() || ui->rb_FS9->isChecked() || ui->rb_XPlane->isChecked() || ui->rb_P3D->isChecked() || ui->rb_FG->isChecked(); + c = ui->rb_FSX->isChecked() || ui->rb_FS9->isChecked() || ui->rb_XPlane->isChecked() || ui->rb_P3D->isChecked() || ui->rb_FG->isChecked() || ui->rb_MSFS->isChecked(); break; case ComboBox: const int i = ui->cb_Simulators->currentIndex(); @@ -244,7 +254,7 @@ namespace swift::gui::components { default: case CheckBoxes: - c = ui->cb_FSX->isChecked() && ui->cb_FS9->isChecked() && ui->cb_XPlane->isChecked() && ui->cb_P3D->isChecked() && ui->cb_FG->isChecked(); + c = ui->cb_FSX->isChecked() && ui->cb_FS9->isChecked() && ui->cb_XPlane->isChecked() && ui->cb_P3D->isChecked() && ui->cb_FG->isChecked() && ui->cb_MSFS->isChecked(); break; case RadioButtons: // actually this should never be true @@ -296,6 +306,7 @@ namespace swift::gui::components ui->rb_XPlane->setEnabled(!readOnly); ui->rb_P3D->setEnabled(!readOnly); ui->rb_FG->setEnabled(!readOnly); + ui->rb_MSFS->setEnabled(!readOnly); ui->cb_Simulators->setEnabled(!readOnly); @@ -385,5 +396,6 @@ namespace swift::gui::components ui->cb_Simulators->insertItem(cbi++, CSimulatorInfo::p3d().toQString()); ui->cb_Simulators->insertItem(cbi++, CSimulatorInfo::xplane().toQString()); ui->cb_Simulators->insertItem(cbi++, CSimulatorInfo::fg().toQString()); + ui->cb_Simulators->insertItem(cbi++, CSimulatorInfo::msfs().toQString()); } } // ns diff --git a/src/gui/components/simulatorselector.ui b/src/gui/components/simulatorselector.ui index 8a026e05c..b309b86de 100644 --- a/src/gui/components/simulatorselector.ui +++ b/src/gui/components/simulatorselector.ui @@ -6,8 +6,8 @@ 0 0 - 188 - 66 + 271 + 74 @@ -88,6 +88,13 @@ + + + + MSFS2020 + + + @@ -159,6 +166,13 @@ + + + + MSFS2020 + + + diff --git a/src/misc/simulation/aircraftmodel.cpp b/src/misc/simulation/aircraftmodel.cpp index 76b6f8ff8..14c35e3b9 100644 --- a/src/misc/simulation/aircraftmodel.cpp +++ b/src/misc/simulation/aircraftmodel.cpp @@ -93,6 +93,8 @@ namespace swift::misc::simulation obj.insert("simp3d", QJsonValue(flag)); flag = CDatastoreUtility::boolToDbYN(sim.isFS9()); obj.insert("simfs9", QJsonValue(flag)); + flag = CDatastoreUtility::boolToDbYN(sim.isMSFS()); + obj.insert("simmsfs", QJsonValue(flag)); flag = CDatastoreUtility::boolToDbYN(sim.isXPlane()); obj.insert("simxplane", QJsonValue(flag)); flag = CDatastoreUtility::boolToDbYN(sim.isFG()); diff --git a/src/misc/simulation/aircraftmodellist.h b/src/misc/simulation/aircraftmodellist.h index 062139272..5f36e2f2c 100644 --- a/src/misc/simulation/aircraftmodellist.h +++ b/src/misc/simulation/aircraftmodellist.h @@ -256,10 +256,10 @@ namespace swift::misc //! Find duplicate model strings and return those models with at least 1 duplicate model string CAircraftModelList findDuplicateModelStrings() const; - //! All models of the FS (FSX, P3D, FS9) family + //! All models of the FS (FSX, P3D, FS9, MSFS) family CAircraftModelList findFsFamilyModels() const; - //! All models NOT of the FS (FSX, P3D, FS9) family + //! All models NOT of the FS (FSX, P3D, FS9, MSFS) family CAircraftModelList findNonFsFamilyModels() const; //! @{ @@ -296,10 +296,10 @@ namespace swift::misc //! Which simulators are supported in this model list CSimulatorInfo simulatorsSupported() const; - //! Is this here a FS family (P3D/FSX/FS9) model list? + //! Is this here a FS family (P3D/FSX/FS9/MSFS) model list? bool isLikelyFsFamilyModelList() const; - //! Is this here a FS family (P3D/FSX) model list? + //! Is this here a FSX family (P3D/FSX/MSFS) model list? bool isLikelyFsxFamilyModelList() const; //! Is this here a XPlane model list? @@ -357,12 +357,12 @@ namespace swift::misc //! \return number of elements removed int removeByAircraftAndAirline(const aviation::CAircraftIcaoCode &aircraftIcao, const aviation::CAirlineIcaoCode &airline); - //! Remove if NOT FS family model, ie. FSX/P3D/FS9 + //! Remove if NOT FS family model, ie. FSX/P3D/FS9/MSFS //! \return number of elements removed int removeIfNotFsFamily(); //! Remove those models of a particular file, but not in the given set - //! \remark mostly used for FSX/FS9/P3D consolidation + //! \remark mostly used for FSX/FS9/P3D/MSFS consolidation CAircraftModelList removeIfFileButNotInSet(const QString &fileName, const QSet &modelStrings); //! Replace or add based on model string diff --git a/src/misc/simulation/aircraftmodelloaderprovider.cpp b/src/misc/simulation/aircraftmodelloaderprovider.cpp index a44502cab..e135f46b2 100644 --- a/src/misc/simulation/aircraftmodelloaderprovider.cpp +++ b/src/misc/simulation/aircraftmodelloaderprovider.cpp @@ -62,6 +62,11 @@ namespace swift::misc::simulation if (!m_loaderFG) { m_loaderFG = this->initLoader(CSimulatorInfo::fg()); } return m_loaderFG; } + case CSimulatorInfo::MSFS: + { + if (!m_loaderMsfs) { m_loaderMsfs = this->initLoader(CSimulatorInfo::msfs()); } + return m_loaderMsfs; + } default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; diff --git a/src/misc/simulation/aircraftmodelloaderprovider.h b/src/misc/simulation/aircraftmodelloaderprovider.h index 758556d62..6bae8536b 100644 --- a/src/misc/simulation/aircraftmodelloaderprovider.h +++ b/src/misc/simulation/aircraftmodelloaderprovider.h @@ -34,6 +34,7 @@ namespace swift::misc::simulation IAircraftModelLoader *modelLoaderXP() const { return m_loaderXP; } IAircraftModelLoader *modelLoaderFS9() const { return m_loaderFS9; } IAircraftModelLoader *modelLoaderFG() const { return m_loaderFG; } + IAircraftModelLoader *modelLoaderMsfs() const { return m_loaderMsfs; } //! @} signals: @@ -55,6 +56,7 @@ namespace swift::misc::simulation IAircraftModelLoader *m_loaderXP = nullptr; IAircraftModelLoader *m_loaderFS9 = nullptr; IAircraftModelLoader *m_loaderFG = nullptr; + IAircraftModelLoader *m_loaderMsfs = nullptr; //! Init the loader IAircraftModelLoader *initLoader(const CSimulatorInfo &simulator); diff --git a/src/misc/simulation/aircraftmodelutils.cpp b/src/misc/simulation/aircraftmodelutils.cpp index 8e4ab714a..d5f28d91d 100644 --- a/src/misc/simulation/aircraftmodelutils.cpp +++ b/src/misc/simulation/aircraftmodelutils.cpp @@ -179,6 +179,11 @@ namespace swift::misc::simulation const CStatusMessageList specificTests2 = fscommon::CFsCommonUtil::validateFSXSimObjectsPath(models, validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, wasStopped, simulatorDir); specificTests.push_back(specificTests2); } + else if (simulator.isMSFS()) + { + const CStatusMessageList specificTests2 = fscommon::CFsCommonUtil::validateMSFSSimObjectsPath(models, validModels, invalidModels, ignoreEmpty, stopAtFailedFiles, wasStopped, simulatorDir); + specificTests.push_back(specificTests2); + } } else if (simulator.isXPlane() || models.isLikelyXPlaneModelList()) { diff --git a/src/misc/simulation/autopublishdata.cpp b/src/misc/simulation/autopublishdata.cpp index 0693fdd1e..eebf9bc6d 100644 --- a/src/misc/simulation/autopublishdata.cpp +++ b/src/misc/simulation/autopublishdata.cpp @@ -217,6 +217,7 @@ namespace swift::misc::simulation this->insert("testModelString4", CSimulatorInfo::p3d()); this->insert("testModelString5", CSimulatorInfo::fsx()); this->insert("testModelString6", CSimulatorInfo::fsx()); + this->insert("testModelString7", CSimulatorInfo::msfs()); } const QString &CAutoPublishData::fileBaseName() diff --git a/src/misc/simulation/data/modelcaches.cpp b/src/misc/simulation/data/modelcaches.cpp index 73c2c6309..f258796cb 100644 --- a/src/misc/simulation/data/modelcaches.cpp +++ b/src/misc/simulation/data/modelcaches.cpp @@ -34,8 +34,11 @@ namespace swift::misc::simulation::data QString IMultiSimulatorModelCaches::getInfoStringFsFamily() const { - static const QString is("FSX: %1 P3D: %2 FS9: %3"); - return is.arg(this->getCachedModelsCount(CSimulatorInfo::FSX)).arg(this->getCachedModelsCount(CSimulatorInfo::P3D)).arg(this->getCachedModelsCount(CSimulatorInfo::FS9)); + static const QString is("FSX: %1, P3D: %2, FS9: %3, MSFS: %4"); + return is.arg(this->getCachedModelsCount(CSimulatorInfo::FSX)) + .arg(this->getCachedModelsCount(CSimulatorInfo::P3D)) + .arg(this->getCachedModelsCount(CSimulatorInfo::FS9)) + .arg(this->getCachedModelsCount(CSimulatorInfo::MSFS)); } QString IMultiSimulatorModelCaches::getCacheCountAndTimestamp(const CSimulatorInfo &simulator) const @@ -59,6 +62,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: m_syncP3D = synchronized; break; case CSimulatorInfo::XPLANE: m_syncXPlane = synchronized; break; case CSimulatorInfo::FG: m_syncFG = synchronized; break; + case CSimulatorInfo::MSFS: m_syncMsfs = synchronized; break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); break; @@ -89,6 +93,7 @@ namespace swift::misc::simulation::data if (this->hasOtherVersionFile(info, CSimulatorInfo::fs9())) { sim.addSimulator(CSimulatorInfo::fs9()); } if (this->hasOtherVersionFile(info, CSimulatorInfo::fg())) { sim.addSimulator(CSimulatorInfo::fg()); } if (this->hasOtherVersionFile(info, CSimulatorInfo::xplane())) { sim.addSimulator(CSimulatorInfo::xplane()); } + if (this->hasOtherVersionFile(info, CSimulatorInfo::msfs())) { sim.addSimulator(CSimulatorInfo::msfs()); } return sim; } @@ -101,6 +106,7 @@ namespace swift::misc::simulation::data this->getFilename(CSimulatorInfo::P3D), this->getFilename(CSimulatorInfo::XPLANE), this->getFilename(CSimulatorInfo::FG), + this->getFilename(CSimulatorInfo::MSFS), }); } @@ -199,6 +205,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.get(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.get(); case CSimulatorInfo::FG: return m_modelCacheFG.get(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.get(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); return CAircraftModelList(); @@ -219,6 +226,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: msg = m_modelCacheP3D.set(setModels); break; case CSimulatorInfo::XPLANE: msg = m_modelCacheXP.set(setModels); break; case CSimulatorInfo::FG: msg = m_modelCacheFG.set(setModels); break; + case CSimulatorInfo::MSFS: msg = m_modelCacheMsfs.set(setModels); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); return CStatusMessage(); @@ -243,6 +251,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_syncP3D; case CSimulatorInfo::XPLANE: return m_syncXPlane; case CSimulatorInfo::FG: return m_syncFG; + case CSimulatorInfo::MSFS: return m_syncMsfs; default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); break; @@ -276,6 +285,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.getAvailableTimestamp(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.getAvailableTimestamp(); case CSimulatorInfo::FG: return m_modelCacheFG.getAvailableTimestamp(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.getAvailableTimestamp(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); return QDateTime(); @@ -293,6 +303,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.set(m_modelCacheP3D.get(), ts.toMSecsSinceEpoch()); case CSimulatorInfo::XPLANE: return m_modelCacheXP.set(m_modelCacheXP.get(), ts.toMSecsSinceEpoch()); case CSimulatorInfo::FG: return m_modelCacheFG.set(m_modelCacheFG.get(), ts.toMSecsSinceEpoch()); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.set(m_modelCacheMsfs.get(), ts.toMSecsSinceEpoch()); default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; @@ -320,6 +331,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.getFilename(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.getFilename(); case CSimulatorInfo::FG: return m_modelCacheFG.getFilename(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.getFilename(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); break; @@ -337,6 +349,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.isSaved(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.isSaved(); case CSimulatorInfo::FG: return m_modelCacheFG.isSaved(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.isSaved(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); break; @@ -356,6 +369,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: m_modelCacheP3D.synchronize(); break; case CSimulatorInfo::XPLANE: m_modelCacheXP.synchronize(); break; case CSimulatorInfo::FG: m_modelCacheFG.synchronize(); break; + case CSimulatorInfo::MSFS: m_modelCacheMsfs.synchronize(); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); break; @@ -376,6 +390,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: m_modelCacheP3D.admit(); break; case CSimulatorInfo::XPLANE: m_modelCacheXP.admit(); break; case CSimulatorInfo::FG: m_modelCacheFG.admit(); break; + case CSimulatorInfo::MSFS: m_modelCacheMsfs.admit(); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); break; @@ -418,6 +433,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.get(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.get(); case CSimulatorInfo::FG: return m_modelCacheFG.get(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.get(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); return CAircraftModelList(); @@ -455,6 +471,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: msg = m_modelCacheP3D.set(orderedModels); break; case CSimulatorInfo::XPLANE: msg = m_modelCacheXP.set(orderedModels); break; case CSimulatorInfo::FG: msg = m_modelCacheFG.set(orderedModels); break; + case CSimulatorInfo::MSFS: msg = m_modelCacheMsfs.set(orderedModels); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "wrong simulator"); return CStatusMessage(); @@ -473,6 +490,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.getAvailableTimestamp(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.getAvailableTimestamp(); case CSimulatorInfo::FG: return m_modelCacheFG.getAvailableTimestamp(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.getAvailableTimestamp(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); return QDateTime(); @@ -490,6 +508,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.set(m_modelCacheP3D.get(), ts.toMSecsSinceEpoch()); case CSimulatorInfo::XPLANE: return m_modelCacheXP.set(m_modelCacheXP.get(), ts.toMSecsSinceEpoch()); case CSimulatorInfo::FG: return m_modelCacheFG.set(m_modelCacheFG.get(), ts.toMSecsSinceEpoch()); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.set(m_modelCacheMsfs.get(), ts.toMSecsSinceEpoch()); default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; @@ -517,6 +536,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.getFilename(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.getFilename(); case CSimulatorInfo::FG: return m_modelCacheFG.getFilename(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.getFilename(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; @@ -534,6 +554,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: return m_modelCacheP3D.isSaved(); case CSimulatorInfo::XPLANE: return m_modelCacheXP.isSaved(); case CSimulatorInfo::FG: return m_modelCacheFG.isSaved(); + case CSimulatorInfo::MSFS: return m_modelCacheMsfs.isSaved(); default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; @@ -553,6 +574,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: m_modelCacheP3D.synchronize(); break; case CSimulatorInfo::XPLANE: m_modelCacheXP.synchronize(); break; case CSimulatorInfo::FG: m_modelCacheFG.synchronize(); break; + case CSimulatorInfo::MSFS: m_modelCacheMsfs.synchronize(); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; @@ -573,6 +595,7 @@ namespace swift::misc::simulation::data case CSimulatorInfo::P3D: m_modelCacheP3D.admit(); break; case CSimulatorInfo::XPLANE: m_modelCacheXP.admit(); break; case CSimulatorInfo::FG: m_modelCacheFG.admit(); break; + case CSimulatorInfo::MSFS: m_modelCacheMsfs.admit(); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; diff --git a/src/misc/simulation/data/modelcaches.h b/src/misc/simulation/data/modelcaches.h index 61599f38b..4b1feee83 100644 --- a/src/misc/simulation/data/modelcaches.h +++ b/src/misc/simulation/data/modelcaches.h @@ -66,6 +66,13 @@ namespace swift::misc::simulation::data static const char *key() { return "modelcachefg"; } }; + //! MSFS + struct TModelCacheMsfs : public TModelCache + { + //! Key in data cache + static const char *key() { return "modelcachemsfs"; } + }; + //! Last selection struct TModelCacheLastSelection : public TDataTrait { @@ -118,6 +125,13 @@ namespace swift::misc::simulation::data static const char *key() { return "modelsetfg"; } }; + //! MSFS + struct TModelSetCacheMsfs : public TModelCache + { + //! Key in data cache + static const char *key() { return "modelsetmsfs"; } + }; + //! Last selection struct TSimulatorLastSelection : public TDataTrait { @@ -281,6 +295,7 @@ namespace swift::misc::simulation::data void changedP3D() { this->emitCacheChanged(CSimulatorInfo::p3d()); } void changedXP() { this->emitCacheChanged(CSimulatorInfo::xplane()); } void changedFG() { this->emitCacheChanged(CSimulatorInfo::fg()); } + void changedMsfs() { this->emitCacheChanged(CSimulatorInfo::msfs()); } //! @} //! Is the cache already synchronized? @@ -297,6 +312,7 @@ namespace swift::misc::simulation::data std::atomic_bool m_syncFS9 { false }; std::atomic_bool m_syncFG { false }; std::atomic_bool m_syncXPlane { false }; + std::atomic_bool m_syncMsfs { false }; //! @} }; @@ -332,6 +348,7 @@ namespace swift::misc::simulation::data CData m_modelCacheP3D { this, &CModelCaches::changedP3D }; //!< P3D cache CData m_modelCacheXP { this, &CModelCaches::changedXP }; //!< XP cache CData m_modelCacheFG { this, &CModelCaches::changedFG }; //!< XP cache + CData m_modelCacheMsfs { this, &CModelCaches::changedMsfs }; //!< MSFS cache //! Non virtual version (can be used in ctor) void synchronizeCacheImpl(const CSimulatorInfo &simulator); @@ -373,6 +390,7 @@ namespace swift::misc::simulation::data CData m_modelCacheP3D { this, &CModelSetCaches::changedP3D }; //!< P3D cache CData m_modelCacheXP { this, &CModelSetCaches::changedXP }; //!< XP cache CData m_modelCacheFG { this, &CModelSetCaches::changedFG }; //!< FG cache + CData m_modelCacheMsfs { this, &CModelSetCaches::changedMsfs }; //!< MSFS cache //! Non virtual version (can be used in ctor) void synchronizeCacheImpl(const CSimulatorInfo &simulator); diff --git a/src/misc/simulation/distributor.cpp b/src/misc/simulation/distributor.cpp index cf934e280..6f2609e2f 100644 --- a/src/misc/simulation/distributor.cpp +++ b/src/misc/simulation/distributor.cpp @@ -221,7 +221,7 @@ namespace swift::misc::simulation const QSet &CDistributor::standardAllFsFamily() { - static const QSet fsFamily({ standardFS9(), standardFSX(), standardP3D() }); + static const QSet fsFamily({ standardFS9(), standardFSX(), standardP3D(), standardMsfs() }); return fsFamily; } @@ -243,6 +243,12 @@ namespace swift::misc::simulation return k; } + const QString &CDistributor::standardMsfs() + { + static const QString k("MSFS"); + return k; + } + QString CDistributor::unifyKeyOrAlias(const QString &value) { return removeChars(value.trimmed().toUpper(), [](QChar c) { return !c.isLetterOrNumber(); }); diff --git a/src/misc/simulation/distributor.h b/src/misc/simulation/distributor.h index 7e2ae9a3b..667b27cf5 100644 --- a/src/misc/simulation/distributor.h +++ b/src/misc/simulation/distributor.h @@ -130,6 +130,7 @@ namespace swift::misc::simulation static const QSet &xplaneMostPopular(); static const QString &xplaneBlueBell(); static const QString &xplaneXcsl(); + static const QString &standardMsfs(); //! @} private: diff --git a/src/misc/simulation/distributorlistpreferences.cpp b/src/misc/simulation/distributorlistpreferences.cpp index 2f49f2b35..eb252f5a1 100644 --- a/src/misc/simulation/distributorlistpreferences.cpp +++ b/src/misc/simulation/distributorlistpreferences.cpp @@ -21,6 +21,7 @@ namespace swift::misc::simulation case CSimulatorInfo::FS9: return m_distributorsFs9; case CSimulatorInfo::FG: return m_distributorsFG; case CSimulatorInfo::XPLANE: return m_distributorsXPlane; + case CSimulatorInfo::MSFS: return m_distributorsMsfs; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; @@ -49,6 +50,7 @@ namespace swift::misc::simulation case CSimulatorInfo::FS9: m_distributorsFs9 = d; break; case CSimulatorInfo::FG: m_distributorsFG = d; break; case CSimulatorInfo::XPLANE: m_distributorsXPlane = d; break; + case CSimulatorInfo::MSFS: m_distributorsMsfs = d; break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong simulator"); break; diff --git a/src/misc/simulation/distributorlistpreferences.h b/src/misc/simulation/distributorlistpreferences.h index a9daeb4f8..4ffb74ad0 100644 --- a/src/misc/simulation/distributorlistpreferences.h +++ b/src/misc/simulation/distributorlistpreferences.h @@ -52,6 +52,7 @@ namespace swift::misc::simulation CDistributorList m_distributorsFs9; CDistributorList m_distributorsXPlane; CDistributorList m_distributorsFG; + CDistributorList m_distributorsMsfs; CSimulatorInfo m_lastUpdatedSimulator; SWIFT_METACLASS( @@ -61,6 +62,7 @@ namespace swift::misc::simulation SWIFT_METAMEMBER(distributorsFs9), SWIFT_METAMEMBER(distributorsXPlane), SWIFT_METAMEMBER(distributorsFG), + SWIFT_METAMEMBER(distributorsMsfs), SWIFT_METAMEMBER(lastUpdatedSimulator)); }; } // namespace diff --git a/src/misc/simulation/fscommon/aircraftcfgparser.cpp b/src/misc/simulation/fscommon/aircraftcfgparser.cpp index 39780ab26..46ec5edd1 100644 --- a/src/misc/simulation/fscommon/aircraftcfgparser.cpp +++ b/src/misc/simulation/fscommon/aircraftcfgparser.cpp @@ -149,7 +149,8 @@ namespace swift::misc::simulation::fscommon // set directory with name filters, get aircraft.cfg and sub directories static const QString NoNameFilter; QDir dir(directory, NoNameFilter, QDir::Name, QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot); - dir.setNameFilters(fileNameFilters()); + // for MSFS we only need aircraft.cfg + dir.setNameFilters(fileNameFilters(getSimulator().isMSFS())); if (!dir.exists()) { return CAircraftCfgEntriesList(); // can happen if there are shortcuts or linked dirs not available @@ -469,9 +470,9 @@ namespace swift::misc::simulation::fscommon return content; } - const QStringList &CAircraftCfgParser::fileNameFilters() + const QStringList &CAircraftCfgParser::fileNameFilters(bool isMSFS) { - if (CBuildConfig::buildWordSize() == 32) + if (CBuildConfig::buildWordSize() == 32 || isMSFS) { static const QStringList f({ "aircraft.cfg" }); return f; diff --git a/src/misc/simulation/fscommon/aircraftcfgparser.h b/src/misc/simulation/fscommon/aircraftcfgparser.h index 1d5e4ee8f..676c896bf 100644 --- a/src/misc/simulation/fscommon/aircraftcfgparser.h +++ b/src/misc/simulation/fscommon/aircraftcfgparser.h @@ -89,7 +89,7 @@ namespace swift::misc static QString getFixedIniLineContent(const QString &line); //! Files to be used - static const QStringList &fileNameFilters(); + static const QStringList &fileNameFilters(bool isMSFS); //! Exclude the sub directories not to be parsed static bool isExcludedSubDirectory(const QString &excludeDirectory); diff --git a/src/misc/simulation/fscommon/fscommon.h b/src/misc/simulation/fscommon/fscommon.h index e0b7321a7..7b6c2b9ba 100644 --- a/src/misc/simulation/fscommon/fscommon.h +++ b/src/misc/simulation/fscommon/fscommon.h @@ -9,7 +9,7 @@ /*! * \namespace FsCommon - * \brief Utility classes for FSX, P3D and FS9, OS and driver independent code + * \brief Utility classes for FSX, P3D, MSFS and FS9, OS and driver independent code */ #endif // guard diff --git a/src/misc/simulation/fscommon/fscommonutil.cpp b/src/misc/simulation/fscommon/fscommonutil.cpp index 8e0a51eea..0ddd63949 100644 --- a/src/misc/simulation/fscommon/fscommonutil.cpp +++ b/src/misc/simulation/fscommon/fscommonutil.cpp @@ -182,6 +182,13 @@ namespace swift::misc::simulation::fscommon return CFsCommonUtil::validateSimObjectsPath(QSet(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, stopped); } + CStatusMessageList CFsCommonUtil::validateMSFSSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &stopped, const QString &simulatorDir) + { + Q_UNUSED(simulatorDir) + const QStringList simObjectPaths = CFsDirectories::msfsSimObjectsDirPlusAddOnXmlSimObjectsPaths(); + return CFsCommonUtil::validateSimObjectsPath(QSet(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, stopped); + } + CStatusMessageList CFsCommonUtil::validateSimObjectsPath( const QSet &simObjectDirs, const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, diff --git a/src/misc/simulation/fscommon/fscommonutil.h b/src/misc/simulation/fscommon/fscommonutil.h index 5801f5b07..a631d1acb 100644 --- a/src/misc/simulation/fscommon/fscommonutil.h +++ b/src/misc/simulation/fscommon/fscommonutil.h @@ -16,7 +16,7 @@ namespace swift::misc::simulation::fscommon { - //! FS9/FSX/P3D utils + //! FS9/FSX/P3D/MSFS utils class SWIFT_MISC_EXPORT CFsCommonUtil { public: @@ -36,7 +36,7 @@ namespace swift::misc::simulation::fscommon static int copyFsxTerrainProbeFiles(const QString &simObjectDir, CStatusMessageList &messages); //! Validate aircraft.cfg entries (sometimes also sim.cfg) - //! \remark only for FSX/P3D/FS9 models + //! \remark only for FSX/P3D/FS9/MSFS models static CStatusMessageList validateAircraftConfigFiles(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped); //! Validate if known SimObjects path are used @@ -47,6 +47,10 @@ namespace swift::misc::simulation::fscommon //! \remark only for FSX static CStatusMessageList validateFSXSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped, const QString &simulatorDir); + //! Validate if known SimObjects path are used + //! \remark only for MSFS + static CStatusMessageList validateMSFSSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped, const QString &simulatorDir); + private: //! Validate if known SimObjects path are used //! \remark only for P3D/FSX diff --git a/src/misc/simulation/fscommon/fsdirectories.cpp b/src/misc/simulation/fscommon/fsdirectories.cpp index e8836a0e9..0ddb20575 100644 --- a/src/misc/simulation/fscommon/fsdirectories.cpp +++ b/src/misc/simulation/fscommon/fsdirectories.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace swift::config; @@ -88,6 +89,54 @@ namespace swift::misc::simulation::fscommon return dir; } + QString msfsDirImpl() + { + const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + for (const QString &path : locations) + { + const QString msfsPackage = CFileUtils::appendFilePaths(CFileUtils::appendFilePaths(path, "Packages"), "Microsoft.FlightSimulator_8wekyb3d8bbwe"); + const QDir d(msfsPackage); + if (!d.exists()) { continue; } + return msfsPackage; + } + return {}; + } + + const QString &CFsDirectories::msfsDir() + { + static const QString dir(msfsDirImpl()); + return dir; + } + + QString msfsPackagesDirImpl() + { + QString msfsDirectory(CFsDirectories::msfsDir()); + const QString userCfg = CFileUtils::appendFilePaths(CFileUtils::appendFilePaths(msfsDirectory, "LocalCache"), "UserCfg.opt"); + QFile file(userCfg); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return {}; } + + QTextStream in(&file); + while (!in.atEnd()) + { + QString line = in.readLine(); + if (line.contains("InstalledPackagesPath")) + { + QStringList split = line.split(" "); + if (split.size() != 2) { return {}; } + QString packagePath = split[1].remove("\""); + const QDir dir(packagePath); + if (dir.exists()) { return packagePath; } + } + } + return {}; + } + + const QString &CFsDirectories::msfsPackagesDir() + { + static const QString dir(msfsPackagesDirImpl()); + return dir; + } + QString fsxSimObjectsDirFromRegistryImpl() { const QString fsxPath = CFileUtils::normalizeFilePathToQtStandard(CFsDirectories::fsxDirFromRegistry()); @@ -108,18 +157,37 @@ namespace swift::misc::simulation::fscommon return CFsDirectories::fsxSimObjectsDirFromSimDir(dir); } + QString msfsSimObjectsDirImpl() + { + QString dir(CFsDirectories::msfsDir()); + if (dir.isEmpty()) { return {}; } + return CFsDirectories::msfsSimObjectsDirFromSimDir(dir); + } + const QString &CFsDirectories::fsxSimObjectsDir() { static const QString dir(fsxSimObjectsDirImpl()); return dir; } + const QString &CFsDirectories::msfsSimObjectsDir() + { + static const QString dir(msfsSimObjectsDirImpl()); + return dir; + } + QString CFsDirectories::fsxSimObjectsDirFromSimDir(const QString &simDir) { if (simDir.isEmpty()) { return {}; } return CFileUtils::appendFilePaths(CFileUtils::normalizeFilePathToQtStandard(simDir), "SimObjects"); } + QString CFsDirectories::msfsSimObjectsDirFromSimDir(const QString &simDir) + { + if (simDir.isEmpty()) { return {}; } + return CFileUtils::appendFilePaths(CFileUtils::normalizeFilePathToQtStandard(simDir), "SimObjects"); + } + const QStringList &CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns() { static const QStringList exclude { @@ -131,6 +199,33 @@ namespace swift::misc::simulation::fscommon return exclude; } + const QStringList &CFsDirectories::msfs20SimObjectsExcludeDirectoryPatterns() + { + static const QStringList exclude { + "OneStore/asobo-discovery", + "OneStore/asobo-flight", + "OneStore/asobo-landingchallenge", + "OneStore/asobo-mission", + "OneStore/asobo-tutorials", + "OneStore/asobo-vcockpits", + "OneStore/asobo-simobjects", + "OneStore/asobo-services", + "OneStore/asobo-vcockpits", + "OneStore/asobo-l", + "OneStore/asobo-m", + "OneStore/asobo-vfx", + "OneStore/fs", + "OneStore/esd", + "OneStore/microsoft-airport", + "OneStore/microsoft-bushtrip", + "OneStore/microsoft-discovery", + "landingchallenge", + "tutorials", + + }; + return exclude; + } + QString p3dDirFromRegistryImpl() { QString p3dPath; @@ -226,6 +321,23 @@ namespace swift::misc::simulation::fscommon return allPaths; } + QStringList CFsDirectories::msfsSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir) + { + // finding the user settings only works on P3D machine + QStringList allPaths = CFsDirectories::allMsfsSimObjectPaths().values(); + const QString sod = CFileUtils::normalizeFilePathToQtStandard(simObjectsDir.isEmpty() ? CFsDirectories::msfsSimObjectsDir() : simObjectsDir); + if (!sod.isEmpty() && !allPaths.contains(sod, Qt::CaseInsensitive)) + { + // case insensitive is important here + allPaths.push_front(sod); + } + + allPaths.removeAll({}); // remove all empty + allPaths.removeDuplicates(); + allPaths.sort(Qt::CaseInsensitive); + return allPaths; + } + QStringList CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir, const QString &versionHint) { // finding the user settings only works on P3D machine @@ -490,6 +602,11 @@ namespace swift::misc::simulation::fscommon return CFsDirectories::fsxSimObjectsPaths(CFsDirectories::findFsxConfigFiles(), true); } + QSet CFsDirectories::allMsfsSimObjectPaths() + { + return CFsDirectories::msfsSimObjectsPaths(CFsDirectories::findMsfsConfigFiles(), true); + } + QStringList CFsDirectories::findFsxConfigFiles() { const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); @@ -507,6 +624,24 @@ namespace swift::misc::simulation::fscommon return files; } + QStringList CFsDirectories::findMsfsConfigFiles() + { + const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + QStringList files; + for (const QString &path : locations) + { + // TODO this acts as a placeholder. the file msfs.cfg doesn't exist + const QString file = CFileUtils::appendFilePaths(CFileUtils::pathUp(path), "Microsoft/MSFS/msfs.cfg"); + const QFileInfo fi(file); + if (fi.exists()) + { + files.push_back(fi.absoluteFilePath()); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"MSFS config file: '%1'") << fi.absoluteFilePath(); } + } + } + return files; + } + QSet CFsDirectories::fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked) { QSet paths; @@ -517,6 +652,16 @@ namespace swift::misc::simulation::fscommon return paths; } + QSet CFsDirectories::msfsSimObjectsPaths(const QStringList &msfsFiles, bool checked) + { + QSet paths; + for (const QString &msfsFile : msfsFiles) + { + paths.unite(CFsDirectories::msfsSimObjectsPaths(msfsFile, checked)); + } + return paths; + } + QSet CFsDirectories::fsxSimObjectsPaths(const QString &fsxFile, bool checked) { const QString fileContent = CFileUtils::readFileToString(fsxFile); @@ -565,6 +710,54 @@ namespace swift::misc::simulation::fscommon return paths; } + QSet CFsDirectories::msfsSimObjectsPaths(const QString &msfsFile, bool checked) + { + const QString fileContent = CFileUtils::readFileToString(msfsFile); + if (fileContent.isEmpty()) { return QSet(); } + const QList lines = splitLinesRefs(fileContent); + static const QString p("SimObjectPaths."); + + const QFileInfo fsxFileInfo(msfsFile); + const QString relPath = fsxFileInfo.absolutePath(); + + QSet paths; + for (const QStringRef &line : lines) + { + const int i1 = line.lastIndexOf(p, -1, Qt::CaseInsensitive); + if (i1 < 0) { continue; } + const int i2 = line.lastIndexOf('='); + if (i2 < 0 || i1 >= i2 || line.endsWith('=')) { continue; } + const QStringRef path = line.mid(i2 + 1); + QString soPath = QDir::fromNativeSeparators(path.toString()); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"MSFS SimObjects path checked: '%1' in '%2'") << line << msfsFile; } + + // ignore exclude patterns + if (containsAny(soPath, CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns(), Qt::CaseInsensitive)) { continue; } + + // make absolute + if (!QStringView(soPath).left(3).contains(':')) { soPath = CFileUtils::appendFilePaths(relPath, soPath); } + + const QDir dir(soPath); // always absolute path now + if (checked && !dir.exists()) + { + // skip, not existing + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path skipped, not existing: '%1' in '%2'") << dir.absolutePath() << msfsFile; } + continue; + } + + const QString afp = dir.absolutePath().toLower(); + if (!CDirectoryUtils::containsFileInDir(afp, airFileFilter(), true)) + { + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path: Skipping '%1' from '%2', no '%3' file") << afp << msfsFile << airFileFilter(); } + continue; + } + + paths.insert(afp); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path: '%1' from '%2'") << afp << msfsFile; } + } + return paths; + } + const QString &CFsDirectories::airFileFilter() { static const QString a("*.air"); diff --git a/src/misc/simulation/fscommon/fsdirectories.h b/src/misc/simulation/fscommon/fsdirectories.h index 0602a62b3..4c9cda198 100644 --- a/src/misc/simulation/fscommon/fsdirectories.h +++ b/src/misc/simulation/fscommon/fsdirectories.h @@ -37,15 +37,27 @@ namespace swift::misc::simulation::fscommon //! FSX's simobject dir, resolved from multiple sources static const QString &fsxSimObjectsDir(); + //! MSFS's simobject dir, resolved from multiple sources + static const QString &msfsSimObjectsDir(); + //! FSX aircraft dir, relative to simulator directory static QString fsxSimObjectsDirFromSimDir(const QString &simDir); + //! MSFS aircraft dir, relative to simulator directory + static QString msfsSimObjectsDirFromSimDir(const QString &simDir); + //! Exclude directories for simObjects static const QStringList &fsxSimObjectsExcludeDirectoryPatterns(); + //! Exclude directories for simObjects + static const QStringList &msfs20SimObjectsExcludeDirectoryPatterns(); + //! FSX's simObject dir and the add on dirs static QStringList fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir = ""); + //! MSFS's simObject dir and the add on dirs + static QStringList msfsSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir = ""); + //! P3D's simObject dir and the add on dirs static QStringList p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir, const QString &versionHint); @@ -70,6 +82,12 @@ namespace swift::misc::simulation::fscommon //! Exclude directories for simObjects static const QStringList &p3dSimObjectsExcludeDirectoryPatterns(); + //! MSFS directory from different sources + static const QString &msfsDir(); + + //! MSFS's packages dir + static const QString &msfsPackagesDir(); + //! FS9 directory obtained from registry static const QString &fs9DirFromRegistry(); @@ -110,18 +128,33 @@ namespace swift::misc::simulation::fscommon //! Get all the SimObjects paths from all config files static QSet allFsxSimObjectPaths(); + //! Get all the SimObjects paths from all config files + static QSet allMsfsSimObjectPaths(); + //! Find the config files (fsx.cfg) // C:/Users/Joe Doe/AppData/Roaming/Microsoft/FSX/fsx.cfg static QStringList findFsxConfigFiles(); + //! Find the config files (fsx.cfg) + // C:/Users/Joe Doe/AppData/Roaming/Microsoft/FSX/fsx.cfg + static QStringList findMsfsConfigFiles(); + //! Get all the SimObjects paths from fsx.cfg // SimObjectPaths.0=SimObjects\Airplanes static QSet fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked); + //! Get all the SimObjects paths from msfs.cfg + // SimObjectPaths.0=SimObjects\Airplanes + static QSet msfsSimObjectsPaths(const QStringList &msfsFiles, bool checked); + //! Get all the SimObjects files from fsx.cfg // SimObjectPaths.0=SimObjects\Airplanes static QSet fsxSimObjectsPaths(const QString &fsxFile, bool checked); + //! Get all the SimObjects files from fsx.cfg + // SimObjectPaths.0=SimObjects\Airplanes + static QSet msfsSimObjectsPaths(const QString &msfsFile, bool checked); + //! .air file filter static const QString &airFileFilter(); diff --git a/src/misc/simulation/settings/simulatorsettings.cpp b/src/misc/simulation/settings/simulatorsettings.cpp index 3ee28900e..889be3abd 100644 --- a/src/misc/simulation/settings/simulatorsettings.cpp +++ b/src/misc/simulation/settings/simulatorsettings.cpp @@ -207,6 +207,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FS9: return m_simSettingsFs9.get(); case CSimulatorInfo::FSX: return m_simSettingsFsx.get(); case CSimulatorInfo::P3D: return m_simSettingsP3D.get(); + case CSimulatorInfo::MSFS: return m_simSettingsMsfs.get(); case CSimulatorInfo::XPLANE: return m_simSettingsXP.get(); default: @@ -230,6 +231,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FS9: return m_simSettingsFs9.set(settings); case CSimulatorInfo::FSX: return m_simSettingsFsx.set(settings); case CSimulatorInfo::P3D: return m_simSettingsP3D.set(settings); + case CSimulatorInfo::MSFS: return m_simSettingsMsfs.set(settings); case CSimulatorInfo::XPLANE: return m_simSettingsXP.set(settings); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); @@ -265,6 +267,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FS9: break; case CSimulatorInfo::FSX: break; case CSimulatorInfo::P3D: break; + case CSimulatorInfo::MSFS: break; case CSimulatorInfo::XPLANE: { if (settings.hasModelDirectories()) @@ -290,6 +293,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FS9: return m_simSettingsFs9.setAndSave(settings); case CSimulatorInfo::FSX: return m_simSettingsFsx.setAndSave(settings); case CSimulatorInfo::P3D: return m_simSettingsP3D.setAndSave(settings); + case CSimulatorInfo::MSFS: return m_simSettingsMsfs.setAndSave(settings); case CSimulatorInfo::XPLANE: return m_simSettingsXP.setAndSave(settings); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); @@ -312,6 +316,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FS9: return m_simSettingsFs9.save(); case CSimulatorInfo::FSX: return m_simSettingsFsx.save(); case CSimulatorInfo::P3D: return m_simSettingsP3D.save(); + case CSimulatorInfo::MSFS: return m_simSettingsMsfs.save(); case CSimulatorInfo::XPLANE: return m_simSettingsXP.save(); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); @@ -389,6 +394,11 @@ namespace swift::misc::simulation::settings this->emitSettingsChanged(CSimulatorInfo::fs9()); } + void CMultiSimulatorSettings::onMsfsSettingsChanged() + { + this->emitSettingsChanged(CSimulatorInfo::msfs()); + } + void CMultiSimulatorSettings::onXPSettingsChanged() { this->emitSettingsChanged(CSimulatorInfo::xplane()); @@ -690,6 +700,13 @@ namespace swift::misc::simulation::settings static const QStringList md = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint); return md; } + case CSimulatorInfo::MSFS: + { + static const QString msfs = CFsDirectories::msfsPackagesDir(); + if (msfs.isEmpty()) { return e; } + static const QStringList md { msfs }; + return md; + } case CSimulatorInfo::XPLANE: { return CXPlaneUtil::xplaneModelDirectories(); @@ -711,6 +728,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FS9: return CFsDirectories::fs9Dir(); case CSimulatorInfo::FSX: return CFsDirectories::fsxDir(); case CSimulatorInfo::P3D: return CFsDirectories::p3dDir(); + case CSimulatorInfo::MSFS: return CFsDirectories::msfsDir(); case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneRootDir(); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); @@ -730,6 +748,7 @@ namespace swift::misc::simulation::settings case CSimulatorInfo::FSX: return CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns(); case CSimulatorInfo::P3D: return CFsDirectories::p3dSimObjectsExcludeDirectoryPatterns(); case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneModelExcludeDirectoryPatterns(); + case CSimulatorInfo::MSFS: return CFsDirectories::msfs20SimObjectsExcludeDirectoryPatterns(); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); break; diff --git a/src/misc/simulation/settings/simulatorsettings.h b/src/misc/simulation/settings/simulatorsettings.h index f26a9f67f..63200f51b 100644 --- a/src/misc/simulation/settings/simulatorsettings.h +++ b/src/misc/simulation/settings/simulatorsettings.h @@ -331,6 +331,20 @@ namespace swift::misc::simulation::settings } }; + //! Trait for simulator settings + struct TSimulatorMsfs : public TSettingTrait + { + //! \copydoc swift::misc::TSettingTrait::key + static const char *key() { return "settingssimulatormsfs"; } + + //! \copydoc swift::misc::TSettingTrait::humanReadable + static const QString &humanReadable() + { + static const QString name("MSFS settings"); + return name; + } + }; + //! Selected P3D version (64bit) struct TP3DVersion : public TSettingTrait { @@ -515,6 +529,7 @@ namespace swift::misc::simulation::settings CSetting m_simSettingsFsx { this, &CMultiSimulatorSettings::onFsxSettingsChanged }; //!< FSX settings CSetting m_simSettingsFs9 { this, &CMultiSimulatorSettings::onFs9SettingsChanged }; //!< FS9 settings CSetting m_simSettingsP3D { this, &CMultiSimulatorSettings::onP3DSettingsChanged }; //!< P3D settings + CSetting m_simSettingsMsfs { this, &CMultiSimulatorSettings::onMsfsSettingsChanged }; //!< MSFS settings CSetting m_simSettingsXP { this, &CMultiSimulatorSettings::onXPSettingsChanged }; //!< XP settings CSetting m_simSettingsFG { this, &CMultiSimulatorSettings::onFGSettingsChanged }; //!< FG settings @@ -523,6 +538,7 @@ namespace swift::misc::simulation::settings void onFsxSettingsChanged(); void onFs9SettingsChanged(); void onP3DSettingsChanged(); + void onMsfsSettingsChanged(); void onXPSettingsChanged(); void onFGSettingsChanged(); //! @} diff --git a/src/misc/simulation/simulatorinfo.cpp b/src/misc/simulation/simulatorinfo.cpp index b9f5cd1e0..efbda1971 100644 --- a/src/misc/simulation/simulatorinfo.cpp +++ b/src/misc/simulation/simulatorinfo.cpp @@ -40,7 +40,7 @@ namespace swift::misc::simulation CSimulatorInfo::CSimulatorInfo(Simulator simulator) : m_simulator(static_cast(simulator)) {} - CSimulatorInfo::CSimulatorInfo(bool fsx, bool fs9, bool xp, bool p3d, bool fg) : m_simulator(boolToFlag(fsx, fs9, xp, p3d, fg)) + CSimulatorInfo::CSimulatorInfo(bool fsx, bool fs9, bool xp, bool p3d, bool fg, bool msfs) : m_simulator(boolToFlag(fsx, fs9, xp, p3d, fg, msfs)) {} CSimulatorInfo::CSimulatorInfo(int flagsAsInt) : m_simulator(flagsAsInt) @@ -83,7 +83,7 @@ namespace swift::misc::simulation bool CSimulatorInfo::isAnySimulator() const { - return isFSX() || isFS9() || isXPlane() || isP3D() || isFG(); + return isFSX() || isFS9() || isXPlane() || isP3D() || isFG() || isMSFS(); } bool CSimulatorInfo::isSingleSimulator() const @@ -103,12 +103,12 @@ namespace swift::misc::simulation bool CSimulatorInfo::isAllSimulators() const { - return isFSX() && isFS9() && isXPlane() && isP3D() && isFG(); + return isFSX() && isFS9() && isXPlane() && isP3D() && isFG() && isMSFS(); } bool CSimulatorInfo::isMicrosoftSimulator() const { - return isFSX() || isFS9(); + return isFSX() || isFS9() || isMSFS(); } bool CSimulatorInfo::isMicrosoftOrPrepare3DSimulator() const @@ -118,7 +118,7 @@ namespace swift::misc::simulation bool CSimulatorInfo::isFsxP3DFamily() const { - return isFSX() || isP3D(); + return isFSX() || isP3D() || isMSFS(); } int CSimulatorInfo::numberSimulators() const @@ -128,6 +128,7 @@ namespace swift::misc::simulation if (isXPlane()) { c++; } if (isP3D()) { c++; } if (isFG()) { c++; } + if (isMSFS()) { c++; } return c; } @@ -162,7 +163,8 @@ namespace swift::misc::simulation (s.testFlag(FS9) ? QStringLiteral("FS9 ") : QString()) % (s.testFlag(P3D) ? QStringLiteral("P3D ") : QString()) % (s.testFlag(XPLANE) ? QStringLiteral("XPlane ") : QString()) % - (s.testFlag(FG) ? QStringLiteral("FG ") : QString()); + (s.testFlag(FG) ? QStringLiteral("FG ") : QString()) % + (s.testFlag(MSFS) ? QStringLiteral("MSFS ") : QString()); return str.trimmed(); } @@ -190,6 +192,7 @@ namespace swift::misc::simulation if (m_simulator & P3D) { set.insert(CSimulatorInfo(P3D)); } if (m_simulator & FG) { set.insert(CSimulatorInfo(FG)); } if (m_simulator & XPLANE) { set.insert(CSimulatorInfo(XPLANE)); } + if (m_simulator & MSFS) { set.insert(CSimulatorInfo(MSFS)); } return set; } @@ -208,13 +211,14 @@ namespace swift::misc::simulation return m.info(u"Simulators OK for model"); } - CSimulatorInfo::Simulator CSimulatorInfo::boolToFlag(bool fsx, bool fs9, bool xp, bool p3d, bool fg) + CSimulatorInfo::Simulator CSimulatorInfo::boolToFlag(bool fsx, bool fs9, bool xp, bool p3d, bool fg, bool msfs) { Simulator s = fsx ? FSX : None; if (fs9) { s |= FS9; } if (xp) { s |= XPLANE; } if (p3d) { s |= P3D; } if (fg) { s |= FG; } + if (msfs) { s |= MSFS; } return s; } @@ -275,6 +279,7 @@ namespace swift::misc::simulation bool fsx = false; bool p3d = false; bool fg = false; + bool msfs = false; if (CBuildConfig::isRunningOnWindowsNtPlatform()) { @@ -287,11 +292,14 @@ namespace swift::misc::simulation p3d = !CFsDirectories::p3dDir().isEmpty() && !CFsDirectories::p3dSimObjectsDir().isEmpty(); + msfs = + !CFsDirectories::msfsDir().isEmpty() && + !CFsDirectories::msfsPackagesDir().isEmpty(); } const bool xp = !CXPlaneUtil::xplaneRootDir().isEmpty(); - sim.setSimulator(CSimulatorInfo::boolToFlag(fsx, fs9, xp, p3d, fg)); + sim.setSimulator(CSimulatorInfo::boolToFlag(fsx, fs9, xp, p3d, fg, msfs)); return sim; } @@ -325,6 +333,7 @@ namespace swift::misc::simulation const QJsonValue jxp = json.value(prefix % u"simxplane"); const QJsonValue jp3d = json.value(prefix % u"simp3d"); const QJsonValue jfg = json.value(prefix % u"simfg"); + const QJsonValue jmsfs = json.value(prefix % u"simmsfs"); // we handle bool JSON values and bool as string const bool fsx = jfsx.isBool() ? jfsx.toBool() : CDatastoreUtility::dbBoolStringToBool(jfsx.toString()); @@ -332,8 +341,9 @@ namespace swift::misc::simulation const bool xp = jxp.isBool() ? jxp.toBool() : CDatastoreUtility::dbBoolStringToBool(jxp.toString()); const bool p3d = jp3d.isBool() ? jp3d.toBool() : CDatastoreUtility::dbBoolStringToBool(jp3d.toString()); const bool fg = jfg.isBool() ? jfg.toBool() : CDatastoreUtility::dbBoolStringToBool(jfg.toString()); + const bool msfs = jmsfs.isBool() ? jmsfs.toBool() : CDatastoreUtility::dbBoolStringToBool(jmsfs.toString()); - const CSimulatorInfo simInfo(fsx, fs9, xp, p3d, fg); + const CSimulatorInfo simInfo(fsx, fs9, xp, p3d, fg, msfs); return simInfo; } @@ -358,12 +368,12 @@ namespace swift::misc::simulation int CCountPerSimulator::getCountForFsFamilySimulators() const { - return this->getCount(CSimulatorInfo::fsx()) + this->getCount(CSimulatorInfo::p3d()) + this->getCount(CSimulatorInfo::fs9()); + return this->getCount(CSimulatorInfo::fsx()) + this->getCount(CSimulatorInfo::p3d()) + this->getCount(CSimulatorInfo::fs9()) + this->getCount(CSimulatorInfo::msfs()); } int CCountPerSimulator::getCountForFsxFamilySimulators() const { - return this->getCount(CSimulatorInfo::fsx()) + this->getCount(CSimulatorInfo::p3d()); + return this->getCount(CSimulatorInfo::fsx()) + this->getCount(CSimulatorInfo::p3d()) + this->getCount(CSimulatorInfo::msfs()); } int CCountPerSimulator::getMaximum() const @@ -402,7 +412,8 @@ namespace swift::misc::simulation u" P3D: " % QString::number(m_counts[1]) % u" FS9: " % QString::number(m_counts[2]) % u" XPlane: " % QString::number(m_counts[3]) % - u" FG: " % QString::number(m_counts[4]); + u" FG: " % QString::number(m_counts[4]) % + u" MSFS: " % QString::number(m_counts[5]); } void CCountPerSimulator::setCount(int count, const CSimulatorInfo &simulator) @@ -415,7 +426,7 @@ namespace swift::misc::simulation if (simulator.isNoSimulator() || simulator.isUnspecified()) { // unknown count - m_counts[5]++; + m_counts[6]++; return; } if (simulator.isFSX()) { m_counts[0]++; } @@ -423,6 +434,7 @@ namespace swift::misc::simulation if (simulator.isFS9()) { m_counts[2]++; } if (simulator.isXPlane()) { m_counts[3]++; } if (simulator.isFG()) { m_counts[4]++; } + if (simulator.isMSFS()) { m_counts[5]++; } } int CCountPerSimulator::internalIndex(const CSimulatorInfo &simulator) @@ -435,6 +447,7 @@ namespace swift::misc::simulation case CSimulatorInfo::FS9: return 2; case CSimulatorInfo::XPLANE: return 3; case CSimulatorInfo::FG: return 4; + case CSimulatorInfo::MSFS: return 5; default: return CSimulatorInfo::NumberOfSimulators; // unknown } } @@ -448,6 +461,7 @@ namespace swift::misc::simulation case 2: return CSimulatorInfo(CSimulatorInfo::FS9); case 3: return CSimulatorInfo(CSimulatorInfo::XPLANE); case 4: return CSimulatorInfo(CSimulatorInfo::FG); + case 5: return CSimulatorInfo(CSimulatorInfo::MSFS); default: return CSimulatorInfo(CSimulatorInfo::None); } } diff --git a/src/misc/simulation/simulatorinfo.h b/src/misc/simulation/simulatorinfo.h index 173ba883b..636168d06 100644 --- a/src/misc/simulation/simulatorinfo.h +++ b/src/misc/simulation/simulatorinfo.h @@ -57,7 +57,7 @@ namespace swift::misc::simulation Q_DECLARE_FLAGS(Simulator, SimulatorFlag) //! Number of known individual simulators - static constexpr int NumberOfSimulators = 5; + static constexpr int NumberOfSimulators = 6; //! Default constructor CSimulatorInfo(); @@ -75,7 +75,7 @@ namespace swift::misc::simulation CSimulatorInfo(int flagsAsInt); //! Constructor - CSimulatorInfo(bool isFSX, bool isFS9, bool xp, bool isP3D, bool fg); + CSimulatorInfo(bool isFSX, bool isFS9, bool xp, bool isP3D, bool fg, bool msfs); //! Unspecified simulator bool isUnspecified() const; @@ -172,7 +172,7 @@ namespace swift::misc::simulation CStatusMessage validateSimulatorsForModel() const; //! Bool flags to enum - static Simulator boolToFlag(bool isFSX, bool isFS9, bool xp, bool isP3D, bool fg); + static Simulator boolToFlag(bool isFSX, bool isFS9, bool xp, bool isP3D, bool fg, bool msfs); //! Identifer, as provided by plugin static Simulator identifierToSimulator(const QString &identifier); @@ -225,6 +225,11 @@ namespace swift::misc::simulation static const CSimulatorInfo s(XPLANE); return s; } + static const CSimulatorInfo &msfs() + { + static const CSimulatorInfo s(MSFS); + return s; + } //! @} private: @@ -248,10 +253,10 @@ namespace swift::misc::simulation //! Unknown count int getCountForUnknownSimulators() const; - //! P3D, FSX, or FS9 + //! P3D, FSX, MSFS or FS9 int getCountForFsFamilySimulators() const; - //! P3D or FSX + //! P3D, MSFS or FSX int getCountForFsxFamilySimulators() const; //! Set count diff --git a/src/misc/simulation/simulatorinfolist.cpp b/src/misc/simulation/simulatorinfolist.cpp index ff780eb84..382254a97 100644 --- a/src/misc/simulation/simulatorinfolist.cpp +++ b/src/misc/simulation/simulatorinfolist.cpp @@ -55,6 +55,7 @@ namespace swift::misc::simulation if (sim.isFS9()) { sims.push_back(CSimulatorInfo(CSimulatorInfo::FS9)); } if (sim.isFSX()) { sims.push_back(CSimulatorInfo(CSimulatorInfo::FSX)); } if (sim.isP3D()) { sims.push_back(CSimulatorInfo(CSimulatorInfo::P3D)); } + if (sim.isMSFS()) { sims.push_back(CSimulatorInfo(CSimulatorInfo::MSFS)); } if (sim.isXPlane()) { sims.push_back(CSimulatorInfo(CSimulatorInfo::XPLANE)); } return sims; } diff --git a/src/misc/simulation/simulatorplugininfo.cpp b/src/misc/simulation/simulatorplugininfo.cpp index 1f3352160..b7303da13 100644 --- a/src/misc/simulation/simulatorplugininfo.cpp +++ b/src/misc/simulation/simulatorplugininfo.cpp @@ -71,6 +71,7 @@ namespace swift::misc::simulation if (s.testFlag(CSimulatorInfo::P3D)) { return CSimulatorPluginInfo::p3dPluginIdentifier(); } if (s.testFlag(CSimulatorInfo::XPLANE)) { return CSimulatorPluginInfo::xplanePluginIdentifier(); } if (s.testFlag(CSimulatorInfo::FG)) { return CSimulatorPluginInfo::fgPluginIdentifier(); } + if (s.testFlag(CSimulatorInfo::MSFS)) { return CSimulatorPluginInfo::msfsPluginIdentifier(); } return e; } diff --git a/src/plugins/simulator/CMakeLists.txt b/src/plugins/simulator/CMakeLists.txt index eac6f8718..fc35574aa 100644 --- a/src/plugins/simulator/CMakeLists.txt +++ b/src/plugins/simulator/CMakeLists.txt @@ -26,7 +26,7 @@ if(SWIFT_BUILD_FSX_PLUGIN OR SWIFT_BUILD_P3D_PLUGIN OR SWIFT_BUILD_MSFS_PLUGIN) add_subdirectory(fsxcommon) endif() -if(SWIFT_WIN32 AND (SWIFT_BUILD_FS9_PLUGIN OR SWIFT_BUILD_FSX_PLUGIN OR SWIFT_BUILD_P3D_PLUGIN OR SWIFT_BUILD_MSFS_PLUGIN)) +if(SWIFT_WIN32 AND (SWIFT_BUILD_FS9_PLUGIN OR SWIFT_BUILD_FSX_PLUGIN OR SWIFT_BUILD_P3D_PLUGIN)) add_subdirectory(fsuipc32) endif() @@ -45,6 +45,7 @@ endif() if(SWIFT_BUILD_MSFS_PLUGIN) add_subdirectory(msfs) + add_subdirectory(msfsconfig) endif() if(SWIFT_BUILD_FSX_PLUGIN) diff --git a/src/plugins/simulator/fsxcommon/simconnectdatadefinition.cpp b/src/plugins/simulator/fsxcommon/simconnectdatadefinition.cpp index ecd5db14a..47331725c 100644 --- a/src/plugins/simulator/fsxcommon/simconnectdatadefinition.cpp +++ b/src/plugins/simulator/fsxcommon/simconnectdatadefinition.cpp @@ -13,6 +13,7 @@ using namespace swift::misc; using namespace swift::misc::aviation; +using namespace swift::misc::simulation; using namespace swift::simplugin::fscommon; namespace swift::simplugin::fsxcommon @@ -69,7 +70,7 @@ namespace swift::simplugin::fsxcommon CSimConnectDefinitions::CSimConnectDefinitions() {} - HRESULT CSimConnectDefinitions::initDataDefinitionsWhenConnected(const HANDLE hSimConnect) + HRESULT CSimConnectDefinitions::initDataDefinitionsWhenConnected(const HANDLE hSimConnect, const CSimulatorInfo &simInfo) { HRESULT hr = s_ok(); hr += initOwnAircraft(hSimConnect); @@ -78,6 +79,10 @@ namespace swift::simplugin::fsxcommon hr += initRemoteAircraftSimDataSet(hSimConnect); hr += initSimulatorEnvironment(hSimConnect); hr += initSbDataArea(hSimConnect); + if (simInfo.isMSFS()) + { + hr += initMSFSTransponder(hSimConnect); + } return hr; } @@ -289,6 +294,18 @@ namespace swift::simplugin::fsxcommon return hr; } + HRESULT CSimConnectDefinitions::initMSFSTransponder(const HANDLE hSimConnect) + { + HRESULT hr = s_ok(); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataTransponderModeMSFS, "TRANSPONDER STATE:1", "Enum"); + hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataTransponderModeMSFS, "TRANSPONDER IDENT:1", "Bool"); + if (isFailure(hr)) + { + CLogMessage(static_cast(nullptr)).error(u"SimConnect error: MSFS transponder data definitions %1") << hr; + } + return hr; + } + DataDefinitionRemoteAircraftPartsWithoutLights::DataDefinitionRemoteAircraftPartsWithoutLights() { this->resetToInvalid(); diff --git a/src/plugins/simulator/fsxcommon/simconnectdatadefinition.h b/src/plugins/simulator/fsxcommon/simconnectdatadefinition.h index 3c090d777..25ba99f8f 100644 --- a/src/plugins/simulator/fsxcommon/simconnectdatadefinition.h +++ b/src/plugins/simulator/fsxcommon/simconnectdatadefinition.h @@ -9,6 +9,7 @@ #include "plugins/simulator/fsxcommon/fsxcommonexport.h" #include "plugins/simulator/fsxcommon/simconnectwindows.h" #include "misc/aviation/aircraftlights.h" +#include "misc/simulation/simulatorinfo.h" #include #include @@ -255,6 +256,13 @@ namespace swift::simplugin::fsxcommon QString toQString() const; }; + //! Data structure for MSFS transponder mode information + struct DataDefinitionMSFSTransponderMode + { + double transponderMode = 1; //!< transponder state simvar + double ident = 0; //!< ident + }; + //! Client areas enum ClientAreaId { @@ -277,6 +285,7 @@ namespace swift::simplugin::fsxcommon DataRemoteAircraftModelData, //!< model data eventually used and reported back from simulator DataRemoteAircraftSetData, //!< set model data such as airline DataSimEnvironment, + DataTransponderModeMSFS, DataClientAreaSb, //!< whole SB area, see http://squawkbox.ca/doc/sdk/fsuipc.php DataClientAreaSbIdent, //!< SB ident single value 0x7b93/19 DataClientAreaSbStandby, //!< SB standby 0x7b91/17 @@ -291,6 +300,7 @@ namespace swift::simplugin::fsxcommon RequestOwnAircraftTitle, RequestSimEnvironment, RequestSbData, //!< SB client area / XPDR mode + RequestMSFSTransponder, //!< MSFS XPDR mode/ident RequestFacility, RequestEndMarker //!< free request ids can start here }; @@ -318,7 +328,7 @@ namespace swift::simplugin::fsxcommon CSimConnectDefinitions(); //! Initialize all data definitions - static HRESULT initDataDefinitionsWhenConnected(const HANDLE hSimConnect); + static HRESULT initDataDefinitionsWhenConnected(const HANDLE hSimConnect, const swift::misc::simulation::CSimulatorInfo &simInfo); private: //! Initialize data definition for our own aircraft @@ -338,6 +348,9 @@ namespace swift::simplugin::fsxcommon //! Initialize the SB data are static HRESULT initSbDataArea(const HANDLE hSimConnect); + + //! Initialize data definition for MSFS transponder + static HRESULT initMSFSTransponder(const HANDLE hSimConnect); }; } // namespace diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp index 1b36f7086..5c8c50ac2 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp @@ -194,6 +194,25 @@ namespace swift::simplugin::fsxcommon } changed = true; } + else if (this->getSimulatorPluginInfo().getSimulatorInfo().isMSFS()) + { + DataDefinitionMSFSTransponderMode t; + t.transponderMode = (newTransponder.isInStandby() ? 1 : 4); + t.ident = newTransponder.isIdentifying(); + + HRESULT hr = s_ok(); + + hr += SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataTransponderModeMSFS, + SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, + sizeof(DataDefinitionMSFSTransponderMode), &t); + + if (isFailure(hr)) + { + CLogMessage(this).warning(u"Setting transponder mode failed (MSFS)"); + } + + changed = true; + } } // avoid changes of cockpit back to old values due to an outdated read back value @@ -468,32 +487,48 @@ namespace swift::simplugin::fsxcommon const CFsxP3DSettings settings = m_detailsSettings.getSettings(this->getSimulatorInfo()); m_useAddSimulatedObj = settings.isAddingAsSimulatedObjectEnabled(); m_useSbOffsets = settings.isSbOffsetsEnabled(); + if (this->getSimulatorPluginInfo().getSimulatorInfo().isMSFS()) + { + m_useSbOffsets = false; // Always disable SbOffsets for MSFS. Using new transponder mode property directly + } - const HRESULT hr1 = this->logAndTraceSendId( + HRESULT hr = s_ok(); + hr += this->logAndTraceSendId( SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraft, CSimConnectDefinitions::DataOwnAircraft, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME), "Cannot request own aircraft data", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject"); - const HRESULT hr2 = this->logAndTraceSendId( + hr += this->logAndTraceSendId( SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraftTitle, CSimConnectDefinitions::DataOwnAircraftTitle, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED), "Cannot request title", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject"); - const HRESULT hr3 = this->logAndTraceSendId( + hr += this->logAndTraceSendId( SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestSimEnvironment, CSimConnectDefinitions::DataSimEnvironment, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED), "Cannot request sim.env.", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject"); - // Request the data from SB only when its changed and only ONCE so we don't have to run a 1sec event to get/set this info ;) - // there was a bug with SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, see https://www.prepar3d.com/forum/viewtopic.php?t=124789 - const HRESULT hr4 = this->logAndTraceSendId( - SimConnect_RequestClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::RequestSbData, - CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED), - "Cannot request client data", Q_FUNC_INFO, "SimConnect_RequestClientData"); + if (!this->getSimulatorPluginInfo().getSimulatorInfo().isMSFS()) + { + // Request the data from SB only when its changed and only ONCE so we don't have to run a 1sec event to get/set this info ;) + // there was a bug with SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, see https://www.prepar3d.com/forum/viewtopic.php?t=124789 + hr += this->logAndTraceSendId( + SimConnect_RequestClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::RequestSbData, + CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED), + "Cannot request client data", Q_FUNC_INFO, "SimConnect_RequestClientData"); + } + else + { + hr += this->logAndTraceSendId( + SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestMSFSTransponder, + CSimConnectDefinitions::DataTransponderModeMSFS, + SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED), + "Cannot request MSFS transponder data", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject"); + } - if (isFailure(hr1, hr2, hr3, hr4)) { return; } + if (isFailure(hr)) { return; } this->emitSimulatorCombinedStatus(); // force sending status } @@ -929,6 +964,27 @@ namespace swift::simplugin::fsxcommon this->updateCockpit(myAircraft.getCom1System(), myAircraft.getCom2System(), xpdr, this->identifier()); } + void CSimulatorFsxCommon::updateTransponderMode(const CTransponder::TransponderMode xpdrMode) + { + if (m_skipCockpitUpdateCycles > 0) { return; } + const CSimulatedAircraft myAircraft(this->getOwnAircraft()); + const bool changed = (myAircraft.getTransponderMode() != xpdrMode); + if (!changed) { return; } + CTransponder myXpdr = myAircraft.getTransponder(); + myXpdr.setTransponderMode(xpdrMode); + this->updateCockpit(myAircraft.getCom1System(), myAircraft.getCom2System(), myXpdr, this->identifier()); + } + + void CSimulatorFsxCommon::updateMSFSTransponderMode(const DataDefinitionMSFSTransponderMode transponderMode) + { + auto mode = CTransponder::StateIdent; + if (!transponderMode.ident) + { + qRound(transponderMode.transponderMode) >= 3 ? mode = CTransponder::ModeC : mode = CTransponder::StateStandby; + } + this->updateTransponderMode(mode); + } + bool CSimulatorFsxCommon::simulatorReportedObjectAdded(DWORD objectId) { if (this->isShuttingDownOrDisconnected()) { return true; } // pretend everything is fine @@ -1880,7 +1936,7 @@ namespace swift::simplugin::fsxcommon HRESULT CSimulatorFsxCommon::initDataDefinitionsWhenConnected() { - return CSimConnectDefinitions::initDataDefinitionsWhenConnected(m_hSimConnect); + return CSimConnectDefinitions::initDataDefinitionsWhenConnected(m_hSimConnect, this->getSimulatorPluginInfo().getSimulatorInfo()); } HRESULT CSimulatorFsxCommon::initWhenConnected() diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h index a223fe0aa..b49b84844 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h @@ -478,6 +478,13 @@ namespace swift::simplugin::fsxcommon //! \threadsafe void updateOwnAircraftFromSimulator(const DataDefinitionClientAreaSb &sbDataArea); + //! Update transponder mode + //! \threadsafe + void updateTransponderMode(const misc::aviation::CTransponder::TransponderMode xpdrMode); + + //! Update transponder mode from MSFS + void updateMSFSTransponderMode(const DataDefinitionMSFSTransponderMode transponderMode); + //! An AI aircraft was added in the simulator bool simulatorReportedObjectAdded(DWORD objectId); diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp index ab3f068e7..8ec92f361 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp +++ b/src/plugins/simulator/fsxcommon/simulatorfsxsimconnectproc.cpp @@ -254,6 +254,12 @@ namespace swift::simplugin::fsxcommon simulatorFsxP3D->synchronizeTime(simEnv); break; } + case CSimConnectDefinitions::RequestMSFSTransponder: + { + const DataDefinitionMSFSTransponderMode *transponderMode = reinterpret_cast(&pObjData->dwData); + simulatorFsxP3D->updateMSFSTransponderMode(*transponderMode); + break; + } default: { const DWORD objectId = pObjData->dwObjectID; diff --git a/src/plugins/simulator/msfs/simulatormsfs.cpp b/src/plugins/simulator/msfs/simulatormsfs.cpp index 0af17224d..e5f6d5577 100644 --- a/src/plugins/simulator/msfs/simulatormsfs.cpp +++ b/src/plugins/simulator/msfs/simulatormsfs.cpp @@ -31,19 +31,11 @@ namespace swift::simplugin::msfs bool CSimulatorMsFs::connectTo() { -#ifdef Q_OS_WIN64 if (!loadAndResolveMSFSimConnect()) { return false; } return CSimulatorFsxCommon::connectTo(); -#else - if (!loadAndResolveFsxSimConnect(true)) - { - return false; - } - return CSimulatorFsxCommon::connectTo(); -#endif } void CSimulatorMsFs::setTrueAltitude(CAircraftSituation &aircraftSituation, const DataDefinitionOwnAircraft &simulatorOwnAircraft) @@ -54,19 +46,11 @@ namespace swift::simplugin::msfs void CSimulatorMsFsListener::startImpl() { -#ifdef Q_OS_WIN64 if (!loadAndResolveMSFSimConnect()) { return; } CSimulatorFsxCommonListener::startImpl(); -#else - if (!loadAndResolveFsxSimConnect(true)) - { - return; - } - CSimulatorFsxCommonListener::startImpl(); -#endif } } // ns diff --git a/src/plugins/simulator/msfs/simulatormsfs.json b/src/plugins/simulator/msfs/simulatormsfs.json index 56ed59434..2cf116d54 100644 --- a/src/plugins/simulator/msfs/simulatormsfs.json +++ b/src/plugins/simulator/msfs/simulatormsfs.json @@ -1,6 +1,7 @@ { "identifier" : "org.swift-project.plugins.simulator.msfs", "name" : "Flight Simulator 2020", - "simulator" : "fsx", - "description" : "Microsoft Flight Simulator 2020" + "simulator" : "msfs", + "description" : "Microsoft Flight Simulator 2020", + "config" : "org.swift-project.plugins.simulator.msfs.config" } diff --git a/src/plugins/simulator/msfsconfig/CMakeLists.txt b/src/plugins/simulator/msfsconfig/CMakeLists.txt new file mode 100644 index 000000000..a416ab811 --- /dev/null +++ b/src/plugins/simulator/msfsconfig/CMakeLists.txt @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: Copyright (C) swift Project Community / Contributors +# SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1 + +add_library(simulatormsfsconfig SHARED + simulatormsfsconfig.cpp + simulatormsfsconfig.h + simulatormsfsconfig.json +) + +set_target_properties(simulatormsfsconfig PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out/bin/plugins/simulator) +set_target_properties(simulatormsfsconfig PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/out/bin/plugins/simulator) + +target_include_directories(simulatormsfsconfig PUBLIC ${PROJECT_SOURCE_DIR}/src) + +target_link_libraries(simulatormsfsconfig + PUBLIC + gui + misc + Qt::Core + PRIVATE + fsxcommon +) + +install(TARGETS simulatormsfsconfig + LIBRARY DESTINATION bin/plugins/simulator + RUNTIME DESTINATION bin/plugins/simulator +) diff --git a/src/plugins/simulator/msfsconfig/simulatormsfsconfig.cpp b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.cpp new file mode 100644 index 000000000..e5e0a674f --- /dev/null +++ b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.cpp @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: Copyright (C) 2017 swift Project Community / Contributors +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1 + +#include "simulatormsfsconfig.h" +#include "../fsxcommon/simulatorfsxconfigwindow.h" + +namespace swift::simplugin::msfs +{ + CSimulatorMsfsConfig::CSimulatorMsfsConfig(QObject *parent) : QObject(parent) + { + // void + } + + swift::gui::CPluginConfigWindow *CSimulatorMsfsConfig::createConfigWindow(QWidget *parent) + { + return new fsxcommon::CSimulatorFsxConfigWindow("MSFS", parent); + } +} diff --git a/src/plugins/simulator/msfsconfig/simulatormsfsconfig.h b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.h new file mode 100644 index 000000000..fa5ea819d --- /dev/null +++ b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.h @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: Copyright (C) 2017 swift Project Community / Contributors +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1 + +//! \file + +#ifndef SWIFT_SIMPLUGIN_MSFS_SIMULATORMSFSCONFIG_H +#define SWIFT_SIMPLUGIN_MSFS_SIMULATORMSFSCONFIG_H + +#include "gui/pluginconfig.h" + +namespace swift::simplugin::msfs +{ + /*! + * Window for setting up the MSFS plugin. + */ + class CSimulatorMsfsConfig : public QObject, public swift::gui::IPluginConfig + { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.swift-project.swiftgui.pluginconfiginterface" FILE "simulatormsfsconfig.json") + Q_INTERFACES(swift::gui::IPluginConfig) + + public: + //! Ctor + CSimulatorMsfsConfig(QObject *parent = nullptr); + + //! Dtor + virtual ~CSimulatorMsfsConfig() {} + + //! \copydoc swift::gui::IPluginConfig::createConfigWindow() + swift::gui::CPluginConfigWindow *createConfigWindow(QWidget *parent) override; + }; +} + +#endif // guard diff --git a/src/plugins/simulator/msfsconfig/simulatormsfsconfig.json b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.json new file mode 100644 index 000000000..9e2ce2e6e --- /dev/null +++ b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.json @@ -0,0 +1,3 @@ +{ + "identifier" : "org.swift-project.plugins.simulator.msfs.config" +} diff --git a/src/plugins/simulator/msfsconfig/simulatormsfsconfig.json.license b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.json.license new file mode 100644 index 000000000..4eaf3369b --- /dev/null +++ b/src/plugins/simulator/msfsconfig/simulatormsfsconfig.json.license @@ -0,0 +1,3 @@ +Copyright (C) swift Project Community / Contributors + +SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1