feat: Add MSFS support

Co-Authored-By: Roland Rossgotterer <roland.rossgotterer@gmail.com>
Co-Authored-By: tzobler <tzobler@t-online.de>
This commit is contained in:
Lars Toenning
2024-11-12 17:27:07 +01:00
parent 7b6568f3b9
commit 528b0cc255
50 changed files with 735 additions and 78 deletions

View File

@@ -93,6 +93,9 @@ This plugin acts as the interface between swift and MSFS.</detailedDescription>
<distributionFile>
<origin>../../dist/bin/plugins/simulator/simulatormsfs.dll</origin>
</distributionFile>
<distributionFile>
<origin>../../dist/bin/plugins/simulator/simulatormsfsconfig.dll</origin>
</distributionFile>
</distributionFileList>
</folder>
</folderList>

View File

@@ -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

View File

@@ -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()

View File

@@ -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};

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -85,6 +85,13 @@
</property>
</widget>
</item>
<item row="1" column="5" alignment="Qt::AlignHCenter">
<widget class="QCheckBox" name="cb_MSFS">
<property name="text">
<string>MSFS (64-bit)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -309,7 +309,7 @@ namespace swift::gui::components
QPointer<CDbOwnModelsComponent> ownModelsComp(qobject_cast<CDbOwnModelsComponent *>(this->parent()));
Q_ASSERT_X(ownModelsComp, Q_FUNC_INFO, "Cannot access parent");
if (m_loadActions.isEmpty()) { m_loadActions = QList<QAction *>({ nullptr, nullptr, nullptr, nullptr, nullptr }); }
if (m_loadActions.isEmpty()) { m_loadActions = QList<QAction *>({ 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<QAction *>({ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }); }
if (m_reloadActions.isEmpty()) { m_reloadActions = QList<QAction *>({ 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<QAction *>({ nullptr, nullptr, nullptr, nullptr, nullptr }); }
if (m_clearCacheActions.isEmpty()) { m_clearCacheActions = QList<QAction *>({ 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)
{

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>188</width>
<height>66</height>
<width>271</width>
<height>74</height>
</rect>
</property>
<property name="windowTitle">
@@ -88,6 +88,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cb_MSFS">
<property name="text">
<string>MSFS2020</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -159,6 +166,13 @@
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rb_MSFS">
<property name="text">
<string>MSFS2020</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -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());

View File

@@ -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<QString> &modelStrings);
//! Replace or add based on model string

View File

@@ -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;

View File

@@ -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);

View File

@@ -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())
{

View File

@@ -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()

View File

@@ -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;

View File

@@ -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<CSimulatorInfo>
{
@@ -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<CSimulatorInfo>
{
@@ -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<TModelCacheP3D> m_modelCacheP3D { this, &CModelCaches::changedP3D }; //!< P3D cache
CData<TModelCacheXP> m_modelCacheXP { this, &CModelCaches::changedXP }; //!< XP cache
CData<TModelCacheFG> m_modelCacheFG { this, &CModelCaches::changedFG }; //!< XP cache
CData<TModelCacheMsfs> 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<TModelSetCacheP3D> m_modelCacheP3D { this, &CModelSetCaches::changedP3D }; //!< P3D cache
CData<TModelSetCacheXP> m_modelCacheXP { this, &CModelSetCaches::changedXP }; //!< XP cache
CData<TModelSetCacheFG> m_modelCacheFG { this, &CModelSetCaches::changedFG }; //!< FG cache
CData<TModelSetCacheMsfs> m_modelCacheMsfs { this, &CModelSetCaches::changedMsfs }; //!< MSFS cache
//! Non virtual version (can be used in ctor)
void synchronizeCacheImpl(const CSimulatorInfo &simulator);

View File

@@ -221,7 +221,7 @@ namespace swift::misc::simulation
const QSet<QString> &CDistributor::standardAllFsFamily()
{
static const QSet<QString> fsFamily({ standardFS9(), standardFSX(), standardP3D() });
static const QSet<QString> 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(); });

View File

@@ -130,6 +130,7 @@ namespace swift::misc::simulation
static const QSet<QString> &xplaneMostPopular();
static const QString &xplaneBlueBell();
static const QString &xplaneXcsl();
static const QString &standardMsfs();
//! @}
private:

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -182,6 +182,13 @@ namespace swift::misc::simulation::fscommon
return CFsCommonUtil::validateSimObjectsPath(QSet<QString>(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<QString>(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, stopped);
}
CStatusMessageList CFsCommonUtil::validateSimObjectsPath(
const QSet<QString> &simObjectDirs, const CAircraftModelList &models,
CAircraftModelList &validModels, CAircraftModelList &invalidModels,

View File

@@ -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

View File

@@ -22,6 +22,7 @@
#include <QDomNodeList>
#include <QSettings>
#include <QStringBuilder>
#include <QTextStream>
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<QString> 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<CFsDirectories *>(nullptr)).info(u"MSFS config file: '%1'") << fi.absoluteFilePath(); }
}
}
return files;
}
QSet<QString> CFsDirectories::fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked)
{
QSet<QString> paths;
@@ -517,6 +652,16 @@ namespace swift::misc::simulation::fscommon
return paths;
}
QSet<QString> CFsDirectories::msfsSimObjectsPaths(const QStringList &msfsFiles, bool checked)
{
QSet<QString> paths;
for (const QString &msfsFile : msfsFiles)
{
paths.unite(CFsDirectories::msfsSimObjectsPaths(msfsFile, checked));
}
return paths;
}
QSet<QString> 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<QString> CFsDirectories::msfsSimObjectsPaths(const QString &msfsFile, bool checked)
{
const QString fileContent = CFileUtils::readFileToString(msfsFile);
if (fileContent.isEmpty()) { return QSet<QString>(); }
const QList<QStringRef> lines = splitLinesRefs(fileContent);
static const QString p("SimObjectPaths.");
const QFileInfo fsxFileInfo(msfsFile);
const QString relPath = fsxFileInfo.absolutePath();
QSet<QString> 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<CFsDirectories *>(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<CFsDirectories *>(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<CFsDirectories *>(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<CFsDirectories *>(nullptr)).info(u"FSX SimObjects path: '%1' from '%2'") << afp << msfsFile; }
}
return paths;
}
const QString &CFsDirectories::airFileFilter()
{
static const QString a("*.air");

View File

@@ -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<QString> allFsxSimObjectPaths();
//! Get all the SimObjects paths from all config files
static QSet<QString> 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<QString> fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked);
//! Get all the SimObjects paths from msfs.cfg
// SimObjectPaths.0=SimObjects\Airplanes
static QSet<QString> msfsSimObjectsPaths(const QStringList &msfsFiles, bool checked);
//! Get all the SimObjects files from fsx.cfg
// SimObjectPaths.0=SimObjects\Airplanes
static QSet<QString> fsxSimObjectsPaths(const QString &fsxFile, bool checked);
//! Get all the SimObjects files from fsx.cfg
// SimObjectPaths.0=SimObjects\Airplanes
static QSet<QString> msfsSimObjectsPaths(const QString &msfsFile, bool checked);
//! .air file filter
static const QString &airFileFilter();

View File

@@ -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;

View File

@@ -331,6 +331,20 @@ namespace swift::misc::simulation::settings
}
};
//! Trait for simulator settings
struct TSimulatorMsfs : public TSettingTrait<CSimulatorSettings>
{
//! \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<QString>
{
@@ -515,6 +529,7 @@ namespace swift::misc::simulation::settings
CSetting<TSimulatorFsx> m_simSettingsFsx { this, &CMultiSimulatorSettings::onFsxSettingsChanged }; //!< FSX settings
CSetting<TSimulatorFs9> m_simSettingsFs9 { this, &CMultiSimulatorSettings::onFs9SettingsChanged }; //!< FS9 settings
CSetting<TSimulatorP3D> m_simSettingsP3D { this, &CMultiSimulatorSettings::onP3DSettingsChanged }; //!< P3D settings
CSetting<TSimulatorMsfs> m_simSettingsMsfs { this, &CMultiSimulatorSettings::onMsfsSettingsChanged }; //!< MSFS settings
CSetting<TSimulatorXP> m_simSettingsXP { this, &CMultiSimulatorSettings::onXPSettingsChanged }; //!< XP settings
CSetting<TSimulatorFG> 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();
//! @}

View File

@@ -40,7 +40,7 @@ namespace swift::misc::simulation
CSimulatorInfo::CSimulatorInfo(Simulator simulator) : m_simulator(static_cast<int>(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);
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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<CSimConnectDefinitions *>(nullptr)).error(u"SimConnect error: MSFS transponder data definitions %1") << hr;
}
return hr;
}
DataDefinitionRemoteAircraftPartsWithoutLights::DataDefinitionRemoteAircraftPartsWithoutLights()
{
this->resetToInvalid();

View File

@@ -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 <algorithm>
#include <QtGlobal>
@@ -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

View File

@@ -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()

View File

@@ -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);

View File

@@ -254,6 +254,12 @@ namespace swift::simplugin::fsxcommon
simulatorFsxP3D->synchronizeTime(simEnv);
break;
}
case CSimConnectDefinitions::RequestMSFSTransponder:
{
const DataDefinitionMSFSTransponderMode *transponderMode = reinterpret_cast<const DataDefinitionMSFSTransponderMode *>(&pObjData->dwData);
simulatorFsxP3D->updateMSFSTransponderMode(*transponderMode);
break;
}
default:
{
const DWORD objectId = pObjData->dwObjectID;

View File

@@ -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

View File

@@ -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"
}

View File

@@ -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
)

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,3 @@
{
"identifier" : "org.swift-project.plugins.simulator.msfs.config"
}

View File

@@ -0,0 +1,3 @@
Copyright (C) swift Project Community / Contributors
SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1