From 5d8ed66931e0465d7bcdbde75407a04080ffbba5 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 28 Feb 2017 04:33:34 +0100 Subject: [PATCH] refs #891, FSX using common base class --- src/plugins/simulator/fsx/fsx.pro | 2 +- .../fsx/simconnectdatadefinition.cpp | 223 --- .../simulator/fsx/simconnectdatadefinition.h | 230 --- .../simulator/fsx/simconnectobject.cpp | 108 -- src/plugins/simulator/fsx/simconnectobject.h | 161 -- src/plugins/simulator/fsx/simulatorfsx.cpp | 1306 +---------------- src/plugins/simulator/fsx/simulatorfsx.h | 279 +--- .../fsx/simulatorfsxsimconnectproc.cpp | 316 ---- src/plugins/simulator/fsxconfig/fsxconfig.pro | 3 +- .../fsxconfig/simconnectsettingscomponent.cpp | 175 --- .../fsxconfig/simconnectsettingscomponent.h | 60 - .../fsxconfig/simconnectsettingscomponent.ui | 246 ---- .../fsxconfig/simulatorfsxconfig.cpp | 13 +- .../fsxconfig/simulatorfsxconfigwindow.cpp | 24 - .../fsxconfig/simulatorfsxconfigwindow.h | 45 - .../fsxconfig/simulatorfsxconfigwindow.ui | 46 - 16 files changed, 24 insertions(+), 3213 deletions(-) delete mode 100644 src/plugins/simulator/fsx/simconnectdatadefinition.cpp delete mode 100644 src/plugins/simulator/fsx/simconnectdatadefinition.h delete mode 100644 src/plugins/simulator/fsx/simconnectobject.cpp delete mode 100644 src/plugins/simulator/fsx/simconnectobject.h delete mode 100644 src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp delete mode 100644 src/plugins/simulator/fsxconfig/simconnectsettingscomponent.cpp delete mode 100644 src/plugins/simulator/fsxconfig/simconnectsettingscomponent.h delete mode 100644 src/plugins/simulator/fsxconfig/simconnectsettingscomponent.ui delete mode 100644 src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.cpp delete mode 100644 src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.h delete mode 100644 src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.ui diff --git a/src/plugins/simulator/fsx/fsx.pro b/src/plugins/simulator/fsx/fsx.pro index 28350c141..5e560da58 100644 --- a/src/plugins/simulator/fsx/fsx.pro +++ b/src/plugins/simulator/fsx/fsx.pro @@ -10,7 +10,7 @@ TEMPLATE = lib CONFIG += plugin shared CONFIG += blackmisc blackcore -LIBS += -lsimulatorfscommon -lSimConnect -lFSUIPC_User +LIBS += -lsimulatorfscommon -lsimulatorfsxcommon -lSimConnect -lFSUIPC_User # required for FSUIPC win32:!win32-g++*: QMAKE_LFLAGS += /NODEFAULTLIB:LIBC.lib diff --git a/src/plugins/simulator/fsx/simconnectdatadefinition.cpp b/src/plugins/simulator/fsx/simconnectdatadefinition.cpp deleted file mode 100644 index 52a928279..000000000 --- a/src/plugins/simulator/fsx/simconnectdatadefinition.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (C) 2013 - * swift Project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -#include "simconnectdatadefinition.h" -#include "blackmisc/logmessage.h" -#include - -using namespace BlackMisc; -using namespace BlackMisc::Aviation; - -namespace BlackSimPlugin -{ - namespace Fsx - { - CSimConnectDefinitions::CSimConnectDefinitions() { } - - HRESULT CSimConnectDefinitions::initDataDefinitionsWhenConnected(const HANDLE hSimConnect) - { - HRESULT hr = S_OK; - hr += initOwnAircraft(hSimConnect); - hr += initRemoteAircraft(hSimConnect); - hr += initRemoteAircraftSimData(hSimConnect); - hr += initSimulatorEnvironment(hSimConnect); - hr += initSbDataArea(hSimConnect); - return hr; - } - - HRESULT CSimConnectDefinitions::initOwnAircraft(const HANDLE hSimConnect) - { - HRESULT hr = S_OK; - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE LATITUDE", "Degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE LONGITUDE", "Degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE ALTITUDE", "Feet"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE ALT ABOVE GROUND", "Feet"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "STATIC CG TO GROUND", "Feet"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE HEADING DEGREES TRUE", "Degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE PITCH DEGREES", "Degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "PLANE BANK DEGREES", "Degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GROUND VELOCITY", "Knots"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GROUND ALTITUDE", "Feet"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "SIM ON GROUND", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT STROBE", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT LANDING", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT TAXI", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT BEACON", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT NAV", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "LIGHT LOGO", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "TRANSPONDER CODE:1", NULL); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM ACTIVE FREQUENCY:1", "MHz"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM ACTIVE FREQUENCY:2", "MHz"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM STANDBY FREQUENCY:1", "MHz"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "COM STANDBY FREQUENCY:2", "MHz"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "FLAPS HANDLE PERCENT", "Percent Over 100"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "SPOILERS HANDLE POSITION", "Percent Over 100"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GEAR HANDLE POSITION", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "NUMBER OF ENGINES", "Number"); - // Simconnect supports index 1 - 4 - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:1", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:2", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:3", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraft, "GENERAL ENG COMBUSTION:4", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataOwnAircraftTitle, "TITLE", NULL, SIMCONNECT_DATATYPE_STRING256); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: initOwnAircraft %1") << hr; - } - return hr; - } - - HRESULT CSimConnectDefinitions::initRemoteAircraft(const HANDLE hSimConnect) - { - HRESULT hr = S_OK; - // Position - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftPosition, "Initial Position", NULL, SIMCONNECT_DATATYPE_INITPOSITION); - - // Hint: "Bool" and "Percent .." are units name - // default data type is SIMCONNECT_DATATYPE_FLOAT64 -> double - - // Flaps - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "LEADING EDGE FLAPS LEFT PERCENT", "Percent Over 100"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "LEADING EDGE FLAPS RIGHT PERCENT", "Percent Over 100"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "TRAILING EDGE FLAPS LEFT PERCENT", "Percent Over 100"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "TRAILING EDGE FLAPS RIGHT PERCENT", "Percent Over 100"); - - // Gear & Spoiler - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GEAR HANDLE POSITION", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "SPOILERS HANDLE POSITION", "Percent Over 100"); - - // Engines - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:1", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:2", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:3", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, "GENERAL ENG COMBUSTION:4", "Bool"); - - // Lights (other definition) - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT STROBE", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT LANDING", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT TAXI", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT BEACON", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT NAV", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT LOGO", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT NAV", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT RECOGNITION", "Bool"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftLights, "LIGHT CABIN", "Bool"); - - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: initRemoteAircraftSituation %1") << hr; - } - return hr; - } - - HRESULT CSimConnectDefinitions::initRemoteAircraftSimData(const HANDLE hSimConnect) - { - HRESULT hr = S_OK; - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSimData, "PLANE LATITUDE", "degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSimData, "PLANE LONGITUDE", "degrees"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSimData, "PLANE ALTITUDE", "Feet"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSimData, "GROUND ALTITUDE", "Feet"); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataRemoteAircraftSimData, "STATIC CG TO GROUND", "Feet"); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: initRemoteAircraftSimData %1") << hr; - } - return hr; - } - - HRESULT CSimConnectDefinitions::initSimulatorEnvironment(const HANDLE hSimConnect) - { - HRESULT hr = S_OK; - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataSimEnvironment, "ZULU TIME", "", SIMCONNECT_DATATYPE_INT32); - hr += SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDefinitions::DataSimEnvironment, "LOCAL TIME", "", SIMCONNECT_DATATYPE_INT32); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: initSimulatorEnvironment %1") << hr; - } - return hr; - } - - HRESULT CSimConnectDefinitions::initSbDataArea(const HANDLE hSimConnect) - { - HRESULT hr = S_OK; - DWORD sbSize = sizeof(DataDefinitionClientAreaSb); - - // We need to know the client area 'name' and map it to a client ID - hr += SimConnect_MapClientDataNameToID(hSimConnect, "SquawkBox Data", ClientAreaSquawkBox); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_MapClientDataNameToID %1") << hr; - return hr; - } - - // Mapping needs to be first - hr += SimConnect_CreateClientData(hSimConnect, ClientAreaSquawkBox, sbSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_CreateClientData %1") << hr; - return hr; - } - - hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSb, 0, sbSize); - hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbStandby, 17, 1); - hr += SimConnect_AddToClientDataDefinition(hSimConnect, CSimConnectDefinitions::DataClientAreaSbIdent, 19, 1); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: SB data area data definitions %1") << hr; - return hr; - } - - // write a default client area so we are not suddenly squawking ident or so - DataDefinitionClientAreaSb sbArea; - sbArea.setDefaultValues(); - hr += SimConnect_SetClientData(hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT, 0, sbSize, &sbArea); - if (hr != S_OK) - { - CLogMessage(static_cast(nullptr)).error("SimConnect error: SimConnect_SetClientData %1") << hr; - } - return hr; - } - - bool DataDefinitionRemoteAircraftParts::operator==(const DataDefinitionRemoteAircraftParts &rhs) const - { - return std::tie(flapsLeadingEdgeLeftPercent, flapsLeadingEdgeRightPercent, flapsTrailingEdgeLeftPercent, flapsTrailingEdgeRightPercent, - gearHandlePosition, spoilersHandlePosition, - engine1Combustion, engine2Combustion, engine3Combustion, engine4Combustion) == - std::tie(rhs.flapsLeadingEdgeLeftPercent, rhs.flapsLeadingEdgeRightPercent, rhs.flapsTrailingEdgeLeftPercent, rhs.flapsTrailingEdgeRightPercent, - rhs.gearHandlePosition, rhs.spoilersHandlePosition, - rhs.engine1Combustion, rhs.engine2Combustion, rhs.engine3Combustion, rhs.engine4Combustion); - } - - void DataDefinitionRemoteAircraftParts::setAllEngines(bool on) - { - engine1Combustion = on ? 1 : 0; - engine2Combustion = on ? 1 : 0; - engine3Combustion = on ? 1 : 0; - engine4Combustion = on ? 1 : 0; - } - - void DataDefinitionRemoteAircraftParts::resetAllFlaps() - { - flapsLeadingEdgeLeftPercent = 0; - flapsLeadingEdgeRightPercent = 0; - flapsTrailingEdgeLeftPercent = 0; - flapsTrailingEdgeRightPercent = 0; - } - - void DataDefinitionRemoteAircraftParts::resetSpoilers() - { - spoilersHandlePosition = 0; - } - - CAircraftLights DataDefinitionRemoteAircraftLights::toLights() const - { - return CAircraftLights(lightStrobe, lightLanding, lightTaxi, lightBeacon, lightNav, lightLogo, lightRecognition, lightCabin); - } - } // namespace -} // namespace diff --git a/src/plugins/simulator/fsx/simconnectdatadefinition.h b/src/plugins/simulator/fsx/simconnectdatadefinition.h deleted file mode 100644 index 75b0be457..000000000 --- a/src/plugins/simulator/fsx/simconnectdatadefinition.h +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright (C) 2013 - * swift project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -//! \file - -#ifndef BLACKSIMPLUGIN_FSX_SIMCONNECT_DATADEFINITION_H -#define BLACKSIMPLUGIN_FSX_SIMCONNECT_DATADEFINITION_H - -#include - -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include "blackmisc/aviation/aircraftlights.h" -#include -#include -#include -#include - -namespace BlackSimPlugin -{ - namespace Fsx - { - //! Data struct of our own aircraft - //! \sa SimConnect variables http://msdn.microsoft.com/en-us/library/cc526981.aspx - //! \sa SimConnect events http://msdn.microsoft.com/en-us/library/cc526980.aspx - struct DataDefinitionOwnAircraft - { - double latitude; //!< Latitude (deg) - double longitude; //!< Longitude (deg) - double altitude; //!< Altitude (ft) - double altitudeAGL; //!< Altitude above ground (ft) - double cgToGround; //!< Static CG to ground (ft) - double trueHeading; //!< True heading (deg) - double pitch; //!< Pitch (deg) - double bank; //!< Bank (deg) - double velocity; //!< Ground velocity - double elevation; //!< Elevation (ft) - double simOnGround; //!< Is aircraft on ground? - - double lightStrobe; //!< Is strobe light on? - double lightLanding; //!< Is landing light on? - double lightTaxi; //!< Is taxi light on? - double lightBeacon; //!< Is beacon light on? - double lightNav; //!< Is nav light on? - double lightLogo; //!< Is logo light on? - - double transponderCode; //!< Transponder Code - double com1ActiveMHz; //!< COM1 active frequency - double com2ActiveMHz; //!< COM2 active frequency - double com1StandbyMHz; //!< COM1 standby frequency - double com2StandbyMHz; //!< COM1 standby frequency - - double flapsHandlePosition; //!< Flaps handle position in percent - double spoilersHandlePosition; //!< Spoilers out? - double gearHandlePosition; //!< Gear handle position - - double numberOfEngines; //!< Number of engines - double engine1Combustion; //!< Engine 1 combustion flag - double engine2Combustion; //!< Engine 2 combustion flag - double engine3Combustion; //!< Engine 3 combustion flag - double engine4Combustion; //!< Engine 4 combustion flag - }; - - //! Data struct of aircraft position - struct DataDefinitionOwnAircraftModel - { - char title[256]; //!< Aircraft model string - }; - - //! Data struct of remote aircraft parts - struct DataDefinitionRemoteAircraftParts - { - double flapsLeadingEdgeLeftPercent; //!< Leading edge left in percent - double flapsLeadingEdgeRightPercent; //!< Leading edge right in percent - double flapsTrailingEdgeLeftPercent; //!< Trailing edge left in percent - double flapsTrailingEdgeRightPercent; //!< Trailing edge right in percent - double gearHandlePosition; //!< Gear handle position - double spoilersHandlePosition; //!< Spoilers out? - double engine1Combustion; //!< Engine 1 combustion flag - double engine2Combustion; //!< Engine 2 combustion flag - double engine3Combustion; //!< Engine 3 combustion flag - double engine4Combustion; //!< Engine 4 combustion flag - - //! Equal to other parts - bool operator==(const DataDefinitionRemoteAircraftParts &rhs) const; - - //! All engines on/off - void setAllEngines(bool on); - - //! Reset all flaps - void resetAllFlaps(); - - //! Reset spoilers - void resetSpoilers(); - }; - - //! Data for aircraft lighs - struct DataDefinitionRemoteAircraftLights - { - double lightStrobe; //!< Is strobe light on? - double lightLanding; //!< Is landing light on? - double lightTaxi; //!< Is taxi light on? - double lightBeacon; //!< Is beacon light on? - double lightNav; //!< Is nav light on? - double lightLogo; //!< Is logo light on? - double lightRecognition; //!< Is recognition light on - double lightCabin; //!< Is cabin light on - - //! Convert to lights - BlackMisc::Aviation::CAircraftLights toLights() const; - }; - - //! Data for AI object sent back from simulator - struct DataDefinitionRemoteAircraftSimData - { - double latitude; //!< Latitude (deg) - double longitude; //!< Longitude (deg) - double altitude; //!< Altitude (ft) - double elevation; //!< Elevation (ft) - double cgToGround; //!< Static CG to ground (ft) - - //! Above ground ft - double aboveGround() const { return altitude - elevation; } - }; - - //! Data struct simulator environment - struct DataDefinitionSimEnvironment - { - qint32 zuluTimeSeconds; //!< Simulator zulu (GMT) ime in secs. - qint32 localTimeSeconds; //!< Simulator local time in secs. - }; - - //! The whole SB data area - struct DataDefinitionClientAreaSb - { - byte data[128] {}; //!< 128 bytes of data, offsets http://www.squawkbox.ca/doc/sdk/fsuipc.php - - //! Standby = 1, else 0 - byte getTransponderMode() const { return data[17]; } - - //! Ident = 1, else 0 - byte getIdent() const { return data[19]; } - - //! Ident? - bool isIdent() const { return getIdent() != 0; } - - //! Standby - bool isStandby() const { return getTransponderMode() != 0; } - - //! Set default values - void setDefaultValues() - { - std::fill(data, data + 128, static_cast(0)); - data[17] = 1; // standby - data[19] = 0; // no ident - } - }; - - //! Client areas - enum ClientAreaId - { - ClientAreaSquawkBox - }; - - //! Handles SimConnect data definitions - class CSimConnectDefinitions - { - public: - //! SimConnect definiton IDs - enum DataDefiniton - { - DataOwnAircraft, - DataOwnAircraftTitle, - DataRemoteAircraftLights, - DataRemoteAircraftParts, - DataRemoteAircraftPosition, - DataRemoteAircraftSimData, - DataSimEnvironment, - DataClientAreaSb, //!< whole SB area - DataClientAreaSbIdent, //!< ident single value - DataClientAreaSbStandby //!< standby - }; - - //! SimConnect request IDs - enum Request - { - RequestOwnAircraft, - RequestRemoveAircraft, - RequestOwnAircraftTitle, - RequestSimEnvironment, - RequestSbData, //!< SB client area / XPDR mode - RequestEndMarker //!< free request ids can start here - }; - - //! Constructor - CSimConnectDefinitions(); - - //! Initialize all data definitions - static HRESULT initDataDefinitionsWhenConnected(const HANDLE hSimConnect); - - //! Log message category - static QString getLogCategory() { return "swift.fsx.simconnect"; } - - private: - //! Initialize data definition for our own aircraft - static HRESULT initOwnAircraft(const HANDLE hSimConnect); - - //! Initialize data definition for remote aircraft - static HRESULT initRemoteAircraft(const HANDLE hSimConnect); - - //! Initialize data for remote aircraft queried from simulator - static HRESULT initRemoteAircraftSimData(const HANDLE hSimConnect); - - //! Initialize data definition for Simulator environment - static HRESULT initSimulatorEnvironment(const HANDLE hSimConnect); - - //! Initialize the SB data are - static HRESULT initSbDataArea(const HANDLE hSimConnect); - }; - } // namespace -} // namespace - -#endif // guard diff --git a/src/plugins/simulator/fsx/simconnectobject.cpp b/src/plugins/simulator/fsx/simconnectobject.cpp deleted file mode 100644 index 8d19458e9..000000000 --- a/src/plugins/simulator/fsx/simconnectobject.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (C) 2013 - * swift Project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -#include "simconnectobject.h" -#include "blackmisc/simulation/interpolatorlinear.h" - -using namespace BlackMisc::Aviation; -using namespace BlackMisc::Simulation; - -namespace BlackSimPlugin -{ - namespace Fsx - { - CSimConnectObject::CSimConnectObject() - { } - - CSimConnectObject::CSimConnectObject(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, DWORD requestId, - BlackMisc::Simulation::CInterpolationLogger *logger) : - m_aircraft(aircraft), m_requestId(requestId), m_validRequestId(true), - m_interpolator(QSharedPointer::create(aircraft.getCallsign())) - { - m_interpolator->attachLogger(logger); - } - - bool CSimConnectObject::isPendingAdded() const - { - return !this->hasValidRequestAndObjectId() || !this->m_confirmedAdded; - } - - bool CSimConnectObject::isConfirmedAdded() const - { - Q_ASSERT_X(!m_confirmedAdded || this->hasValidRequestAndObjectId(), Q_FUNC_INFO, "confirmed but invalid ids"); - return m_confirmedAdded; - } - - void CSimConnectObject::setConfirmedAdded(bool confirm) - { - m_confirmedAdded = confirm; - m_aircraft.setRendered(true); - } - - void CSimConnectObject::setPendingRemoved(bool pending) - { - m_pendingRemoved = pending; - m_aircraft.setRendered(false); - } - - bool CSimConnectObject::hasValidRequestAndObjectId() const - { - return this->hasValidRequestId() && this->hasValidObjectId(); - } - - bool CSimConnectObjects::setSimConnectObjectIdForRequestId(DWORD requestId, DWORD objectId) - { - // First check, if this request id belongs to us - auto it = std::find_if(this->begin(), this->end(), [requestId](const CSimConnectObject & obj) { return obj.getRequestId() == requestId; }); - if (it == this->end()) { return false; } - - // belongs to us - it->setObjectId(objectId); - return true; - } - - CCallsign CSimConnectObjects::getCallsignForObjectId(DWORD objectId) const - { - return getSimObjectForObjectId(objectId).getCallsign(); - } - - CSimConnectObject CSimConnectObjects::getSimObjectForObjectId(DWORD objectId) const - { - for (const CSimConnectObject &simObject : this->values()) - { - if (simObject.getObjectId() == objectId) { return simObject; } - } - return CSimConnectObject(); - } - - CSimConnectObject CSimConnectObjects::getSimObjectForRequestId(DWORD requestId) const - { - for (const CSimConnectObject &simObject : this->values()) - { - if (simObject.getRequestId() == requestId) { return simObject; } - } - return CSimConnectObject(); - } - - bool CSimConnectObjects::isKnownSimObjectId(DWORD objectId) const - { - const CSimConnectObject simObject(getSimObjectForObjectId(objectId)); - return simObject.hasValidRequestAndObjectId() && objectId == simObject.getObjectId(); - } - - bool CSimConnectObjects::containsPendingAdd() const - { - for (const CSimConnectObject &simObject : this->values()) - { - if (simObject.isPendingAdded()) { return true; } - } - return false; - } - } // namespace -} // namespace diff --git a/src/plugins/simulator/fsx/simconnectobject.h b/src/plugins/simulator/fsx/simconnectobject.h deleted file mode 100644 index cd0ccf536..000000000 --- a/src/plugins/simulator/fsx/simconnectobject.h +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (C) 2013 - * swift project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -//! \file - -#ifndef BLACKSIMPLUGIN_SIMCONNECT_OBJECT_H -#define BLACKSIMPLUGIN_SIMCONNECT_OBJECT_H - -#include "blackmisc/simulation/simulatedaircraft.h" -#include "simconnectdatadefinition.h" -#include - -namespace BlackMisc -{ - namespace Simulation - { - class CInterpolatorLinear; - class CInterpolationLogger; - } -} -namespace BlackSimPlugin -{ - namespace Fsx - { - //! Class representing a SimConnect object - class CSimConnectObject - { - public: - //! Constructor - CSimConnectObject(); - - //! Constructor - CSimConnectObject(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, DWORD requestId, - BlackMisc::Simulation::CInterpolationLogger *logger); - - //! Destructor - ~CSimConnectObject() {} - - //! Get Callsign - const BlackMisc::Aviation::CCallsign &getCallsign() const { return m_aircraft.getCallsign(); } - - //! Simulated aircraft (as added) - const BlackMisc::Simulation::CSimulatedAircraft &getAircraft() const { return m_aircraft; } - - //! Simulated aircraft model string - const QString &getAircraftModelString() const { return m_aircraft.getModelString(); } - - //! Interpolator - BlackMisc::Simulation::CInterpolatorLinear *getInterpolator() const { return m_interpolator.data(); } - - //! Get current lights (requested from simulator) - const BlackMisc::Aviation::CAircraftLights &getCurrentLightsInSimulator() const { return m_currentLightsInSim; } - - //! Set current lights when received from simulator - void setCurrentLightsInSimulator(const BlackMisc::Aviation::CAircraftLights &lights) { m_currentLightsInSim = lights; } - - //! Parts as sent to simulator - const DataDefinitionRemoteAircraftParts &getPartsAsSent() const { return m_partsAsSent; } - - //! Parts as sent to simulator - void setPartsAsSent(const DataDefinitionRemoteAircraftParts &parts) { m_partsAsSent = parts; } - - //! Lights as sent to simulator - const BlackMisc::Aviation::CAircraftLights &getLightsAsSent() const { return m_lightsAsSent; } - - //! Lights as sent to simulator - void setLightsAsSent(const BlackMisc::Aviation::CAircraftLights &lights) { m_lightsAsSent = lights; } - - //! How often do we request data from simulator for this remote aircraft - SIMCONNECT_PERIOD getSimDataPeriod() const { return m_requestSimDataPeriod; } - - //! How often do we request data from simulator for this remote aircraft - void setSimDataPeriod(SIMCONNECT_PERIOD period) { m_requestSimDataPeriod = period; } - - //! Set Simconnect request id - void setRequestId(DWORD id) { m_requestId = id; m_validRequestId = true; } - - //! Get Simconnect request id - DWORD getRequestId() const { return m_requestId; } - - //! Set Simconnect object id - void setObjectId(DWORD id) { m_objectId = id; m_validObjectId = true; } - - //! Set Simconnect object id - DWORD getObjectId() const { return m_objectId; } - - //! Valid request id? - bool hasValidRequestId() const { return this->m_validRequestId; } - - //! Valid object id? - bool hasValidObjectId() const { return this->m_validObjectId; } - - //! Object is requested, not yet added - bool isPendingAdded() const; - - //! Adding is confirmed - bool isConfirmedAdded() const; - - //! Marked as confirmed - void setConfirmedAdded(bool confirm); - - //! Removing is pending - bool isPendingRemoved() const { return m_pendingRemoved; } - - //! Marked as confirmed - void setPendingRemoved(bool pending); - - //! VTOL? - bool isVtol() const { return m_aircraft.isVtol(); } - - //! Was the object really added to SIM - bool hasValidRequestAndObjectId() const; - - private: - BlackMisc::Simulation::CSimulatedAircraft m_aircraft; //!< corresponding aircraft - DWORD m_requestId = 0; - DWORD m_objectId = 0; - bool m_validRequestId = false; - bool m_validObjectId = false; - bool m_confirmedAdded = false; - bool m_pendingRemoved = false; - int m_lightsRequestedAt = -1; - DataDefinitionRemoteAircraftParts m_partsAsSent {}; //!< parts as sent - BlackMisc::Aviation::CAircraftLights m_currentLightsInSim { nullptr }; //!< current lights to know state for toggling - BlackMisc::Aviation::CAircraftLights m_lightsAsSent { nullptr }; //!< lights as sent to simulator - SIMCONNECT_PERIOD m_requestSimDataPeriod = SIMCONNECT_PERIOD_NEVER; //!< how often do we query ground elevation - QSharedPointer m_interpolator; //!< shared pointer because CSimConnectObject can be copied - }; - - //! Simulator objects (aka AI aircraft) - class CSimConnectObjects : public QHash - { - public: - //! Set ID of a SimConnect object, so far we only have an request id in the object - bool setSimConnectObjectIdForRequestId(DWORD requestId, DWORD objectId); - - //! Find which callsign belongs to the object id - BlackMisc::Aviation::CCallsign getCallsignForObjectId(DWORD objectId) const; - - //! Get object per object id - CSimConnectObject getSimObjectForObjectId(DWORD objectId) const; - - //! Get object per request id - CSimConnectObject getSimObjectForRequestId(DWORD requestId) const; - - //! Is the object id one of our AI objects? - bool isKnownSimObjectId(DWORD objectId) const; - - //! Pending add condition - bool containsPendingAdd() const; - }; - } // namespace -} // namespace - -#endif // guard diff --git a/src/plugins/simulator/fsx/simulatorfsx.cpp b/src/plugins/simulator/fsx/simulatorfsx.cpp index d4deeb125..1dbd955ec 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.cpp +++ b/src/plugins/simulator/fsx/simulatorfsx.cpp @@ -8,23 +8,6 @@ */ #include "simulatorfsx.h" -#include "blackcore/application.h" -#include "blackmisc/network/textmessage.h" -#include "blackmisc/simulation/fscommon/bcdconversions.h" -#include "blackmisc/simulation/fsx/simconnectutilities.h" -#include "blackmisc/simulation/aircraftmodel.h" -#include "blackmisc/simulation/interpolatorlinear.h" -#include "blackmisc/simulation/interpolationhints.h" -#include "blackmisc/simulation/simulatorplugininfo.h" -#include "blackmisc/aviation/airportlist.h" -#include "blackmisc/geo/elevationplane.h" -#include "blackmisc/logmessage.h" -#include "blackmisc/threadutils.h" -#include "blackmisc/verify.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" - -#include -#include using namespace BlackMisc; using namespace BlackMisc::Aviation; @@ -33,7 +16,6 @@ using namespace BlackMisc::Geo; using namespace BlackMisc::Network; using namespace BlackMisc::Simulation; using namespace BlackMisc::Simulation::FsCommon; -using namespace BlackMisc::Simulation::Fsx; using namespace BlackMisc::Weather; using namespace BlackCore; @@ -46,15 +28,8 @@ namespace BlackSimPlugin IRemoteAircraftProvider *remoteAircraftProvider, IWeatherGridProvider *weatherGridProvider, QObject *parent) : - CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, weatherGridProvider, parent) + CSimulatorFsxCommon(info, ownAircraftProvider, remoteAircraftProvider, weatherGridProvider, parent) { - Q_ASSERT_X(ownAircraftProvider, Q_FUNC_INFO, "Missing provider"); - Q_ASSERT_X(remoteAircraftProvider, Q_FUNC_INFO, "Missing provider"); - Q_ASSERT_X(sApp, Q_FUNC_INFO, "Missing global object"); - m_realityBubbleTimer.setInterval(20 * 1000); - connect(&m_realityBubbleTimer, &QTimer::timeout, this, &CSimulatorFsx::ps_addAircraftCurrentlyOutOfBubble); - - m_useFsuipc = false; // Temporarily enabled until Simconnect Weather is implemented. m_defaultModel = { "Boeing 737-800 Paint1", @@ -63,1280 +38,5 @@ namespace BlackSimPlugin CAircraftIcaoCode("B738", "L2J") }; } - - CSimulatorFsx::~CSimulatorFsx() - { - disconnectFrom(); - // fsuipc is disconnected in CSimulatorFsCommon - } - - bool CSimulatorFsx::isConnected() const - { - return m_simConnected; - } - - bool CSimulatorFsx::isSimulating() const - { - return m_simSimulating; - } - - bool CSimulatorFsx::connectTo() - { - if (this->isConnected()) { return true; } - this->reset(); - if (FAILED(SimConnect_Open(&m_hSimConnect, sApp->swiftVersionChar(), nullptr, 0, 0, 0))) - { - // reset state as expected for unconnected - return false; - } - if (m_useFsuipc) { this->m_fsuipc->connect(); } // FSUIPC too - - // set structures and move on - initEvents(); - initDataDefinitionsWhenConnected(); - m_simConnectTimerId = startTimer(10); - m_realityBubbleTimer.start(); - return true; - } - - bool CSimulatorFsx::disconnectFrom() - { - if (!m_simConnected) { return true; } - if (m_simConnectTimerId >= 0) { killTimer(m_simConnectTimerId); } - m_simConnectTimerId = -1; - if (m_hSimConnect) - { - SimConnect_Close(m_hSimConnect); - m_hSimConnect = nullptr; - } - - reset(); - - // emit status and disconnect FSUIPC - CSimulatorFsCommon::disconnectFrom(); - return true; - } - - bool CSimulatorFsx::physicallyAddRemoteAircraft(const CSimulatedAircraft &newRemoteAircraft) - { - const CCallsign callsign(newRemoteAircraft.getCallsign()); - - Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread"); - Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); - Q_ASSERT_X(newRemoteAircraft.hasModelString(), Q_FUNC_INFO, "missing model string"); - if (callsign.isEmpty()) { return false; } - - // check if we have to do something - m_outOfRealityBubble.removeByCallsign(callsign); - if (m_simConnectObjects.contains(callsign)) - { - const CSimConnectObject simObj = m_simConnectObjects[callsign]; - if (simObj.isPendingAdded()) - { - return true; // already pending - } - else - { - // same model, nothing will change, otherwise add again when removed - if (simObj.getAircraft().getModel() != newRemoteAircraft.getModel()) - { - m_aircraftToAddAgainWhenRemoved.push_back(newRemoteAircraft); - } - return false; - } - } - - // create AI - bool adding = false; - const CAircraftModel aircraftModel = newRemoteAircraft.getModel(); - CSimulatedAircraft addedAircraft(newRemoteAircraft); - if (isConnected()) - { - const DWORD requestId = obtainRequestIdSimData(); - SIMCONNECT_DATA_INITPOSITION initialPosition = aircraftSituationToFsxPosition(addedAircraft.getSituation()); - const QString modelString(addedAircraft.getModelString()); - - if (m_interpolationRenderingSetup.showSimulatorDebugMessages()) - { - CLogMessage(this).debug() << "physicallyAddRemoteAircraft" << callsign.toQString() << "request" << requestId << "model" << modelString; - CLogMessage(this).debug() << "initial position" << fsxPositionToString(initialPosition); - } - - HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(callsign.toQString().left(12)), initialPosition, static_cast(requestId)); - if (hr != S_OK) - { - const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create AI traffic: '%1' '%2'") << callsign.toQString() << aircraftModel.getModelString(); - CLogMessage::preformatted(msg); - emit physicallyAddingRemoteModelFailed(addedAircraft, msg); - } - else - { - // we will request a new aircraft by request ID, later we will receive its object id - // so far this object id is -1 - addedAircraft.setRendered(false); - const CSimConnectObject simObject(addedAircraft, requestId, &m_interpolationLogger); - m_simConnectObjects.insert(callsign, simObject); - adding = true; - } - } - else - { - CLogMessage(this).warning("FSX: Not connected, not added aircraft '%1' '%2'") << callsign.toQString() << aircraftModel.getModelString(); - } - return adding; - } - - bool CSimulatorFsx::updateOwnSimulatorCockpit(const CSimulatedAircraft &ownAircraft, const CIdentifier &originator) - { - if (originator == this->identifier()) { return false; } - if (!this->isSimulating()) { return false; } - - // actually those data should be the same as ownAircraft - const CComSystem newCom1 = ownAircraft.getCom1System(); - const CComSystem newCom2 = ownAircraft.getCom2System(); - const CTransponder newTransponder = ownAircraft.getTransponder(); - - bool changed = false; - if (newCom1.getFrequencyActive() != this->m_simCom1.getFrequencyActive()) - { - const CFrequency newFreq = newCom1.getFrequencyActive(); - SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom1Active, - CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - changed = true; - - } - if (newCom1.getFrequencyStandby() != this->m_simCom1.getFrequencyStandby()) - { - const CFrequency newFreq = newCom1.getFrequencyStandby(); - SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom1Standby, - CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - changed = true; - } - - if (newCom2.getFrequencyActive() != this->m_simCom2.getFrequencyActive()) - { - const CFrequency newFreq = newCom2.getFrequencyActive(); - SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom2Active, - CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - changed = true; - } - if (newCom2.getFrequencyStandby() != this->m_simCom2.getFrequencyStandby()) - { - const CFrequency newFreq = newCom2.getFrequencyStandby(); - SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetCom2Standby, - CBcdConversions::comFrequencyToBcdHz(newFreq), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - changed = true; - } - - if (newTransponder.getTransponderCode() != this->m_simTransponder.getTransponderCode()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetTransponderCode, - CBcdConversions::transponderCodeToBcd(newTransponder), SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - changed = true; - } - - if (newTransponder.getTransponderMode() != this->m_simTransponder.getTransponderMode()) - { - if (m_useSbOffsets) - { - byte ident = newTransponder.isIdentifying() ? 1U : 0U; // 1 is ident - byte standby = newTransponder.isInStandby() ? 1U : 0U; // 1 is standby - HRESULT hr = S_OK; - - hr += SimConnect_SetClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSbIdent, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT, 0, 1, &ident); - hr += SimConnect_SetClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::DataClientAreaSbStandby, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT, 0, 1, &standby); - if (hr != S_OK) - { - CLogMessage(this).warning("Setting transponder mode failed (SB offsets)"); - } - } - changed = true; - } - - // avoid changes of cockpit back to old values due to an outdated read back value - if (changed) { m_skipCockpitUpdateCycles = SkipUpdateCyclesForCockpit; } - - // bye - return changed; - } - - void CSimulatorFsx::displayStatusMessage(const BlackMisc::CStatusMessage &message) const - { - QByteArray m = message.getMessage().toLocal8Bit().constData(); - m.append('\0'); - - SIMCONNECT_TEXT_TYPE type = SIMCONNECT_TEXT_TYPE_PRINT_BLACK; - switch (message.getSeverity()) - { - case CStatusMessage::SeverityDebug: return; - case CStatusMessage::SeverityInfo: type = SIMCONNECT_TEXT_TYPE_PRINT_GREEN; break; - case CStatusMessage::SeverityWarning: type = SIMCONNECT_TEXT_TYPE_PRINT_YELLOW; break; - case CStatusMessage::SeverityError: type = SIMCONNECT_TEXT_TYPE_PRINT_RED; break; - } - HRESULT hr = SimConnect_Text(m_hSimConnect, type, 7.5, EventTextMessage, - static_cast(m.size()), m.data()); - Q_UNUSED(hr); - } - - void CSimulatorFsx::displayTextMessage(const BlackMisc::Network::CTextMessage &message) const - { - this->displayStatusMessage(message.asStatusMessage(true, true)); - } - - bool CSimulatorFsx::isPhysicallyRenderedAircraft(const CCallsign &callsign) const - { - return this->m_simConnectObjects.contains(callsign); - } - - CCallsignSet CSimulatorFsx::physicallyRenderedAircraft() const - { - CCallsignSet callsigns(this->m_simConnectObjects.keys()); - callsigns.push_back(m_aircraftToAddAgainWhenRemoved.getCallsigns()); // not really rendered right now, but very soon - callsigns.push_back(m_outOfRealityBubble.getCallsigns()); // not really rendered, but for the logic it should look like it is - return CCallsignSet(this->m_simConnectObjects.keys()); - } - - bool CSimulatorFsx::stillDisplayReceiveExceptions() - { - m_receiveExceptionCount++; - return m_receiveExceptionCount < IgnoreReceiveExceptions; - } - - void CSimulatorFsx::setSimConnected() - { - m_simConnected = true; - this->initSimulatorInternals(); - emitSimulatorCombinedStatus(); - - // Internals depends on sim data which take a while to be read - // this is a trich and I re-init again after a while (which is not really expensive) - QTimer::singleShot(1000, this, [this] { this->initSimulatorInternals(); }); - } - - void CSimulatorFsx::onSimRunning() - { - if (m_simSimulating) { return; } - m_simSimulating = true; // only place where this should be set to true - m_simConnected = true; - HRESULT hr = SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraft, - CSimConnectDefinitions::DataOwnAircraft, - SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME); - - hr += SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraftTitle, - CSimConnectDefinitions::DataOwnAircraftTitle, - SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, - SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); - - hr += SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestSimEnvironment, - CSimConnectDefinitions::DataSimEnvironment, - SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, - SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); - - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin: SimConnect_RequestDataOnSimObject failed"); - return; - } - - // 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 ;) - hr += SimConnect_RequestClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::RequestSbData, - CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED); - - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin: SimConnect_RequestClientData failed"); - return; - } - - emitSimulatorCombinedStatus(); - } - - void CSimulatorFsx::onSimStopped() - { - const int oldStatus = getSimulatorStatus(); - m_simSimulating = false; - emitSimulatorCombinedStatus(oldStatus); - } - - void CSimulatorFsx::onSimFrame() - { - updateRemoteAircraft(); - } - - void CSimulatorFsx::onSimExit() - { - // reset complete state, we are going down - disconnectFrom(); - } - - DWORD CSimulatorFsx::obtainRequestIdSimData() - { - const DWORD id = m_requestIdSimData++; - if (id > RequestSimDataEnd) { m_requestIdSimData = RequestSimDataStart; } - return id; - } - - void CSimulatorFsx::updateOwnAircraftFromSimulator(const DataDefinitionOwnAircraft &simulatorOwnAircraft) - { - CSimulatedAircraft myAircraft(getOwnAircraft()); - BlackMisc::Geo::CCoordinateGeodetic position; - position.setLatitude(CLatitude(simulatorOwnAircraft.latitude, CAngleUnit::deg())); - position.setLongitude(CLongitude(simulatorOwnAircraft.longitude, CAngleUnit::deg())); - - if (simulatorOwnAircraft.pitch < -90.0 || simulatorOwnAircraft.pitch >= 90.0) - { - CLogMessage(this).warning("FSX: Pitch value out of limits: %1") << simulatorOwnAircraft.pitch; - } - BlackMisc::Aviation::CAircraftSituation aircraftSituation; - aircraftSituation.setPosition(position); - // MSFS has inverted pitch and bank angles - aircraftSituation.setPitch(CAngle(-simulatorOwnAircraft.pitch, CAngleUnit::deg())); - aircraftSituation.setBank(CAngle(-simulatorOwnAircraft.bank, CAngleUnit::deg())); - aircraftSituation.setHeading(CHeading(simulatorOwnAircraft.trueHeading, CHeading::True, CAngleUnit::deg())); - aircraftSituation.setGroundSpeed(CSpeed(simulatorOwnAircraft.velocity, CSpeedUnit::kts())); - aircraftSituation.setGroundElevation(CAltitude(simulatorOwnAircraft.elevation, CAltitude::MeanSeaLevel, CLengthUnit::ft())); - aircraftSituation.setAltitude(CAltitude(simulatorOwnAircraft.altitude, CAltitude::MeanSeaLevel, CLengthUnit::ft())); - - const CAircraftLights lights(simulatorOwnAircraft.lightStrobe, - simulatorOwnAircraft.lightLanding, - simulatorOwnAircraft.lightTaxi, - simulatorOwnAircraft.lightBeacon, - simulatorOwnAircraft.lightNav, - simulatorOwnAircraft.lightLogo); - - CAircraftEngineList engines; - const QList helperList - { - simulatorOwnAircraft.engine1Combustion != 0, simulatorOwnAircraft.engine2Combustion != 0, - simulatorOwnAircraft.engine3Combustion != 0, simulatorOwnAircraft.engine4Combustion != 0 - }; - - for (int index = 0; index < simulatorOwnAircraft.numberOfEngines; ++index) - { - engines.push_back(CAircraftEngine(index + 1, helperList.at(index))); - } - - const CAircraftParts parts(lights, simulatorOwnAircraft.gearHandlePosition, - simulatorOwnAircraft.flapsHandlePosition * 100, - simulatorOwnAircraft.spoilersHandlePosition, - engines, - simulatorOwnAircraft.simOnGround); - - // set values - updateOwnSituation(aircraftSituation); - updateOwnParts(parts); - - // When I change cockpit values in the sim (from GUI to simulator, not originating from simulator) - // it takes a little while before these values are set in the simulator. - // To avoid jitters, I wait some update cylces to stabilize the values - if (m_skipCockpitUpdateCycles < 1) - { - // defaults - CComSystem com1(myAircraft.getCom1System()); // set defaults - CComSystem com2(myAircraft.getCom2System()); - CTransponder transponder(myAircraft.getTransponder()); - - // updates - com1.setFrequencyActive(CFrequency(simulatorOwnAircraft.com1ActiveMHz, CFrequencyUnit::MHz())); - com1.setFrequencyStandby(CFrequency(simulatorOwnAircraft.com1StandbyMHz, CFrequencyUnit::MHz())); - const bool changedCom1 = myAircraft.getCom1System() != com1; - this->m_simCom1 = com1; - - com2.setFrequencyActive(CFrequency(simulatorOwnAircraft.com2ActiveMHz, CFrequencyUnit::MHz())); - com2.setFrequencyStandby(CFrequency(simulatorOwnAircraft.com2StandbyMHz, CFrequencyUnit::MHz())); - const bool changedCom2 = myAircraft.getCom2System() != com2; - this->m_simCom2 = com2; - - transponder.setTransponderCode(simulatorOwnAircraft.transponderCode); - const bool changedXpr = (myAircraft.getTransponderCode() != transponder.getTransponderCode()); - - if (changedCom1 || changedCom2 || changedXpr) - { - this->updateCockpit(com1, com2, transponder, identifier()); - } - } - else - { - --m_skipCockpitUpdateCycles; - } - - if (m_isWeatherActivated) - { - const auto currentPosition = CCoordinateGeodetic { aircraftSituation.latitude(), aircraftSituation.longitude(), {0} }; - if (CWeatherScenario::isRealWeatherScenario(m_weatherScenarioSettings.get()) && - calculateGreatCircleDistance(m_lastWeatherPosition, currentPosition).value(CLengthUnit::mi()) > 20) - { - m_lastWeatherPosition = currentPosition; - const auto weatherGrid = CWeatherGrid { { "GLOB", currentPosition } }; - requestWeatherGrid(weatherGrid, { this, &CSimulatorFsx::injectWeatherGrid }); - } - } - } - - void CSimulatorFsx::updateRemoteAircraftFromSimulator(const CSimConnectObject &simObject, const DataDefinitionRemoteAircraftSimData &remoteAircraftData) - { - // Near ground we use faster updates - if (remoteAircraftData.aboveGround() <= 100.0) - { - // switch to fast updates - if (simObject.getSimDataPeriod() != SIMCONNECT_PERIOD_VISUAL_FRAME) - { - this->requestDataForSimObject(simObject, SIMCONNECT_PERIOD_VISUAL_FRAME); - } - } - else - { - // switch to slow updates - if (simObject.getSimDataPeriod() != SIMCONNECT_PERIOD_SECOND) - { - this->requestDataForSimObject(simObject, SIMCONNECT_PERIOD_SECOND); - } - } - - CElevationPlane elevation(remoteAircraftData.latitude, remoteAircraftData.longitude, remoteAircraftData.elevation); - elevation.setSinglePointRadius(); - - // const QString debug(hints.debugInfo(elevation)); - CInterpolationHints &hints = m_hints[simObject.getCallsign()]; - hints.setElevationPlane(elevation); // update elevation - hints.setCGAboveGround({ remoteAircraftData.cgToGround, CLengthUnit::ft() }); // normally never changing, but if user changes ModelMatching - - // set it in the remote aircraft provider - this->updateAircraftGroundElevation(simObject.getCallsign(), elevation); - } - - void CSimulatorFsx::updateOwnAircraftFromSimulator(const DataDefinitionClientAreaSb &sbDataArea) - { - CTransponder::TransponderMode newMode; - if (sbDataArea.isIdent()) - { - newMode = CTransponder::StateIdent; - } - else - { - newMode = sbDataArea.isStandby() ? CTransponder::StateStandby : CTransponder::ModeC; - } - const CSimulatedAircraft myAircraft(this->getOwnAircraft()); - const bool changed = (myAircraft.getTransponderMode() != newMode); - if (!changed) { return; } - CTransponder xpdr = myAircraft.getTransponder(); - xpdr.setTransponderMode(newMode); - this->updateCockpit(myAircraft.getCom1System(), myAircraft.getCom2System(), xpdr, this->identifier()); - } - - bool CSimulatorFsx::simulatorReportedObjectAdded(DWORD objectID) - { - const CSimConnectObject simObject = this->m_simConnectObjects.getSimObjectForObjectId(objectID); - const CCallsign callsign(simObject.getCallsign()); - if (!simObject.hasValidRequestAndObjectId() || callsign.isEmpty()) { return false; } - - // we know the object has been created. But it can happen it is directly removed afterwards - QTimer::singleShot(500, this, [ = ] { this->ps_deferredSimulatorReportedObjectAdded(callsign); }); - return true; - } - - bool CSimulatorFsx::ps_deferredSimulatorReportedObjectAdded(const CCallsign &callsign) - { - if (callsign.isEmpty()) { return false; } - if (!m_simConnectObjects.contains(callsign)) { return false; } // removed in mean time - - CSimConnectObject &simObject = m_simConnectObjects[callsign]; - if (!simObject.hasValidRequestAndObjectId() || simObject.isPendingRemoved()) { return false; } - - Q_ASSERT_X(simObject.isPendingAdded(), Q_FUNC_INFO, "already confirmed"); - simObject.setConfirmedAdded(true); - const DWORD objectId = simObject.getObjectId(); - - if (m_interpolationRenderingSetup.showSimulatorDebugMessages()) - { - CLogMessage(this).debug() << "Adding AI" << callsign.toQString() << "confirmed" << "id" << objectId << "model" << simObject.getAircraftModelString(); - } - - // P3D also has SimConnect_AIReleaseControlEx; - const DWORD requestId = obtainRequestIdSimData(); - HRESULT hr = SimConnect_AIReleaseControl(m_hSimConnect, objectId, static_cast(requestId)); - if (hr == S_OK) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeLat, 1, - SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeAlt, 1, - SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventFreezeAtt, 1, - SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - else - { - CLogMessage(this).error("Adding AI %1 failed") << callsign.toQString(); - return false; - } - - const bool updated = this->updateAircraftRendered(callsign, true); - if (updated) - { - emit aircraftRenderingChanged(simObject.getAircraft()); - } - return true; - } - - void CSimulatorFsx::ps_addAircraftCurrentlyOutOfBubble() - { - if (m_outOfRealityBubble.isEmpty()) { return; } - const CCallsignSet aircraftCallsignsInRange(getAircraftInRangeCallsigns()); - CSimulatedAircraftList toBeAddedAircraft; - CCallsignSet toBeRemovedCallsigns; - for (const CSimulatedAircraft &aircraft : as_const(m_outOfRealityBubble)) - { - Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign"); - if (aircraftCallsignsInRange.contains(aircraft.getCallsign())) - { - toBeAddedAircraft.push_back(aircraft); - } - else - { - toBeRemovedCallsigns.push_back(aircraft.getCallsign()); - } - } - m_outOfRealityBubble.removeByCallsigns(toBeRemovedCallsigns); - - // add aircraft, but non blocking - int t = 100; - for (const CSimulatedAircraft &aircraft : as_const(toBeAddedAircraft)) - { - QTimer::singleShot(t, this, [ = ] - { - this->physicallyAddRemoteAircraft(aircraft); - }); - t += 100; - } - } - - bool CSimulatorFsx::simulatorReportedObjectRemoved(DWORD objectID) - { - const CSimConnectObject simObject = this->m_simConnectObjects.getSimObjectForObjectId(objectID); - if (!simObject.hasValidRequestAndObjectId()) { return false; } // object id from somewhere else - const CCallsign callsign(simObject.getCallsign()); - Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "missing callsign"); - - bool ok = false; - if (simObject.isPendingRemoved()) - { - // good case, object has been removed - // we can remove the sim object - } - else - { - // object was removed, but removal was not requested by us - // this means we are out of the reality bubble (or something else went wrong) - if (!simObject.getAircraftModelString().isEmpty()) - { - this->m_outOfRealityBubble.push_back(simObject.getAircraft()); - CLogMessage(this).info("Aircraft removed, '%1' '%2' object id '%3' out of reality bubble") << callsign.toQString() << simObject.getAircraftModelString() << objectID; - } - else - { - CLogMessage(this).warning("Removed %1 from simulator, but was not initiated by us: %1 '%2' object id %3") << callsign.toQString() << simObject.getAircraftModelString() << objectID; - } - } - - // in all cases we remove - const int c = m_simConnectObjects.remove(callsign); - ok = c > 0; - const bool updated = this->updateAircraftRendered(simObject.getCallsign(), false); - if (updated) - { - emit aircraftRenderingChanged(simObject.getAircraft()); - } - - // models we have to add again after removing - if (m_aircraftToAddAgainWhenRemoved.containsCallsign(callsign)) - { - const CSimulatedAircraft aircraftAddAgain = m_aircraftToAddAgainWhenRemoved.findFirstByCallsign(callsign); - QTimer::singleShot(1000, this, [ = ] { this->physicallyAddRemoteAircraft(aircraftAddAgain); }); - } - return ok; - } - - bool CSimulatorFsx::setSimConnectObjectId(DWORD requestID, DWORD objectID) - { - return this->m_simConnectObjects.setSimConnectObjectIdForRequestId(requestID, objectID); - } - - bool CSimulatorFsx::setCurrentLights(const CCallsign &callsign, const CAircraftLights &lights) - { - if (!m_simConnectObjects.contains(callsign)) { return false; } - m_simConnectObjects[callsign].setCurrentLightsInSimulator(lights); - return true; - } - - bool CSimulatorFsx::setLightsAsSent(const CCallsign &callsign, const CAircraftLights &lights) - { - if (!m_simConnectObjects.contains(callsign)) { return false; } - m_simConnectObjects[callsign].setLightsAsSent(lights); - return true; - } - - void CSimulatorFsx::timerEvent(QTimerEvent *event) - { - Q_UNUSED(event); - ps_dispatch(); - } - - void CSimulatorFsx::ps_dispatch() - { - HRESULT hr = SimConnect_CallDispatch(m_hSimConnect, SimConnectProc, this); - if (hr != S_OK) - { - m_dispatchErrors++; - if (m_dispatchErrors == 2) - { - // 2nd time, an error / avoid multiple messages - // idea: if it happens once ignore - CLogMessage(this).error("FSX: Dispatch error"); - } - else if (m_dispatchErrors > 5) - { - // this normally happens during a FSX crash or shutdown - this->disconnectFrom(); - } - return; - } - m_dispatchErrors = 0; - if (m_useFsuipc && m_fsuipc) - { - CSimulatedAircraft fsuipcAircraft(getOwnAircraft()); - //! \fixme split in high / low frequency reads - bool ok = m_fsuipc->read(fsuipcAircraft, true, true, true); - if (ok) - { - // do whatever is required - Q_UNUSED(fsuipcAircraft); - } - } - } - - bool CSimulatorFsx::physicallyRemoveRemoteAircraft(const CCallsign &callsign) - { - // only remove from sim - Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "wrong thread"); - if (callsign.isEmpty()) { return false; } // can happen if an object is not an aircraft - - m_outOfRealityBubble.removeByCallsign(callsign); - if (!m_simConnectObjects.contains(callsign)) { return false; } // already fully removed or not yet added - - CSimConnectObject &simObject = m_simConnectObjects[callsign]; - if (simObject.isPendingRemoved()) { return true; } - if (simObject.isPendingAdded()) - { - // problem: we try to delete an aircraft just requested to be added - return false; //! \fixme improve, since this scenario is not really covered - } - - simObject.setPendingRemoved(true); - if (m_interpolationRenderingSetup.showSimulatorDebugMessages()) - { - CLogMessage(this).debug() << "physicallyRemoveRemoteAircraft" << callsign.toQString(); - } - - // call in SIM - SimConnect_AIRemoveObject(m_hSimConnect, static_cast(simObject.getObjectId()), static_cast(m_requestIdSimData++)); - m_hints.remove(simObject.getCallsign()); - - // mark in provider - bool updated = updateAircraftRendered(callsign, false); - if (updated) - { - CSimulatedAircraft aircraft(simObject.getAircraft()); - aircraft.setRendered(false); - emit aircraftRenderingChanged(aircraft); - } - - // cleanup function, actually this should not be needed - QTimer::singleShot(100, this, &CSimulatorFsx::ps_physicallyRemoveAircraftNotInProvider); - - // bye - return true; - } - - int CSimulatorFsx::physicallyRemoveAllRemoteAircraft() - { - if (m_simConnectObjects.isEmpty()) { return 0; } - const QList callsigns(m_simConnectObjects.keys()); - int r = 0; - for (const CCallsign &cs : callsigns) - { - if (physicallyRemoveRemoteAircraft(cs)) { r++; } - } - clearAllAircraft(); - return r; - } - - HRESULT CSimulatorFsx::initEvents() - { - HRESULT hr = S_OK; - // System events, see http://msdn.microsoft.com/en-us/library/cc526983.aspx#SimConnect_SubscribeToSystemEvent - hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventSimStatus, "Sim"); - hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventObjectAdded, "ObjectAdded"); - hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventObjectRemoved, "ObjectRemoved"); - hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventFrame, "Frame"); - hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventPause, "Pause"); - hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, SystemEventFlightLoaded, "FlightLoaded"); - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin error: %1") << "SimConnect_SubscribeToSystemEvent failed"; - return hr; - } - - // Mapped events, see event ids here: http://msdn.microsoft.com/en-us/library/cc526980.aspx - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventPauseToggle, "PAUSE_TOGGLE"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, SystemEventSlewToggle, "SLEW_TOGGLE"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventFreezeLat, "FREEZE_LATITUDE_LONGITUDE_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventFreezeAlt, "FREEZE_ALTITUDE_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventFreezeAtt, "FREEZE_ATTITUDE_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetCom1Active, "COM_RADIO_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetCom1Standby, "COM_STBY_RADIO_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetCom2Active, "COM2_RADIO_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetCom2Standby, "COM2_STBY_RADIO_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetTransponderCode, "XPNDR_SET"); - - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetTimeZuluYear, "ZULU_YEAR_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetTimeZuluDay, "ZULU_DAY_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetTimeZuluHours, "ZULU_HOURS_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventSetTimeZuluMinutes, "ZULU_MINUTES_SET"); - - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventLandingLightsOff, "LANDING_LIGHTS_OFF"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventLandinglightsOn, "LANDING_LIGHTS_ON"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventLandingLightsSet, "LANDING_LIGHTS_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventLandingLightsToggle, "LANDING_LIGHTS_TOGGLE"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventPanelLightsOff, "PANEL_LIGHTS_OFF"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventPanelLightsOn, "PANEL_LIGHTS_ON"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventPanelLightsSet, "PANEL_LIGHTS_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventStrobesOff, "STROBES_OFF"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventStrobesOn, "STROBES_ON"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventStrobesSet, "STROBES_SET"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventStrobesToggle, "STROBES_TOGGLE"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleBeaconLights, "TOGGLE_BEACON_LIGHTS"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleCabinLights, "TOGGLE_CABIN_LIGHTS"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleLogoLights, "TOGGLE_LOGO_LIGHTS"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleNavLights, "TOGGLE_NAV_LIGHTS"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleRecognitionLights, "TOGGLE_RECOGNITION_LIGHTS"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleTaxiLights, "TOGGLE_TAXI_LIGHTS"); - hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EventToggleWingLights, "TOGGLE_WING_LIGHTS"); - - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin error: %1") << "SimConnect_MapClientEventToSimEvent failed"; - return hr; - } - - // facility - hr += SimConnect_SubscribeToFacilities(m_hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, static_cast(m_requestIdSimData++)); - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin error: %1") << "SimConnect_SubscribeToFacilities failed"; - return hr; - } - return hr; - } - - HRESULT CSimulatorFsx::initDataDefinitionsWhenConnected() - { - return CSimConnectDefinitions::initDataDefinitionsWhenConnected(m_hSimConnect); - } - - HRESULT CSimulatorFsx::initWhenConnected() - { - // called when connected - - HRESULT hr = initEvents(); - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin: initEvents failed"); - return hr; - } - - // inti data definitions and SB data area - hr += initDataDefinitionsWhenConnected(); - if (hr != S_OK) - { - CLogMessage(this).error("FSX plugin: initDataDefinitionsWhenConnected failed"); - return hr; - } - - return hr; - } - - void CSimulatorFsx::updateRemoteAircraft() - { - static_assert(sizeof(DataDefinitionRemoteAircraftParts) == sizeof(double) * 10, "DataDefinitionRemoteAircraftParts has an incorrect size."); - Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread"); - - // nothing to do, reset request id and exit - if (this->isPaused() && this->m_pausedSimFreezesInterpolation) { return; } // no interpolation while paused - const int remoteAircraftNo = this->getAircraftInRangeCount(); - if (remoteAircraftNo < 1) { m_interpolationRequest = 0; return; } - - // interpolate and send to simulator - this->m_interpolationRequest++; - const bool enableAircraftParts = this->m_interpolationRenderingSetup.isAircraftPartsEnabled(); - const CCallsignSet aircraftWithParts = enableAircraftParts ? this->remoteAircraftSupportingParts() : CCallsignSet(); // optimization, fetch all parts supporting aircraft in one step (one lock) - - // values used for position and parts - const qint64 currentTimestamp = QDateTime::currentMSecsSinceEpoch(); - const QList simObjects(m_simConnectObjects.values()); - const CCallsignSet callsignsToLog(this->m_interpolationRenderingSetup.getLogCallsigns()); - - // interpolation for all remote aircraft - for (const CSimConnectObject &simObj : simObjects) - { - // happening if aircraft is not yet added to simulator or to be deleted - if (simObj.isPendingAdded()) { continue; } - if (simObj.isPendingRemoved()) { continue; } - - const CCallsign callsign(simObj.getCallsign()); - Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "missing callsign"); - Q_ASSERT_X(simObj.hasValidRequestAndObjectId(), Q_FUNC_INFO, "Missing ids"); - - // fetch parts, as they are needed for ground interpolation - const bool useAircraftParts = enableAircraftParts && aircraftWithParts.contains(callsign); - const bool logInterpolationAndParts = callsignsToLog.contains(callsign); - CPartsStatus partsStatus; - partsStatus.setSupportsParts(useAircraftParts); - - const CInterpolationAndRenderingSetup setup(getInterpolationAndRenderingSetup()); - const CAircraftParts parts = useAircraftParts ? simObj.getInterpolator()->getInterpolatedParts(-1, setup, partsStatus, logInterpolationAndParts) : CAircraftParts(); - - // get interpolated situation - CInterpolationStatus interpolatorStatus; - CInterpolationHints hints(m_hints[simObj.getCallsign()]); - hints.setAircraftParts(useAircraftParts ? parts : CAircraftParts(), useAircraftParts); - hints.setLoggingInterpolation(logInterpolationAndParts); - const CAircraftSituation interpolatedSituation = simObj.getInterpolator()->getInterpolatedSituation(currentTimestamp, setup, hints, interpolatorStatus); - - if (interpolatorStatus.allTrue()) - { - // update situation - SIMCONNECT_DATA_INITPOSITION position = this->aircraftSituationToFsxPosition(interpolatedSituation); - HRESULT hr = S_OK; - hr += SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftPosition, - static_cast(simObj.getObjectId()), 0, 0, - sizeof(SIMCONNECT_DATA_INITPOSITION), &position); - if (hr != S_OK) - { - CLogMessage(this).warning("Failed so set position on SimObject '%1' callsign: '%2'") << simObj.getObjectId() << callsign; - } - - } // interpolation data - - if (useAircraftParts) - { - this->updateRemoteAircraftParts(simObj, parts, partsStatus); - } - else - { - // guess on position, but not every frame - if (m_interpolationRequest % GuessRemoteAircraftPartsCycle == 0) - { - this->guessAndUpdateRemoteAircraftParts(simObj, interpolatedSituation, interpolatorStatus); - } - } - } // all callsigns - const qint64 dt = QDateTime::currentMSecsSinceEpoch() - currentTimestamp; - m_statsUpdateAircraftTimeTotalMs += dt; - m_statsUpdateAircraftCountMs++; - m_statsUpdateAircraftTimeAvgMs = m_statsUpdateAircraftTimeTotalMs / m_statsUpdateAircraftCountMs; - } - - bool CSimulatorFsx::guessAndUpdateRemoteAircraftParts(const CSimConnectObject &simObj, const CAircraftSituation &interpolatedSituation, const CInterpolationStatus &interpolationStatus) - { - if (!simObj.hasValidRequestAndObjectId()) { return false; } - if (!interpolationStatus.didInterpolationSucceed()) { return false; } - - CAircraftLights lights; - DataDefinitionRemoteAircraftParts ddRemoteAircraftParts = {}; // init members - const bool isOnGround = interpolatedSituation.isOnGround() == CAircraftSituation::OnGround; - const double gsKts = interpolatedSituation.getGroundSpeed().value(CSpeedUnit::kts()); - ddRemoteAircraftParts.setAllEngines(true); - lights.setCabinOn(true); - lights.setRecognitionOn(true); - - // when first detected moving, lights on - if (isOnGround) - { - ddRemoteAircraftParts.gearHandlePosition = 1; - lights.setTaxiOn(true); - lights.setBeaconOn(true); - lights.setNavOn(true); - - if (gsKts > 5) - { - // mode taxi - lights.setTaxiOn(true); - lights.setLandingOn(false); - } - else if (gsKts > 30) - { - // mode accelaration for takeoff - lights.setTaxiOn(false); - lights.setLandingOn(true); - } - else - { - // slow movements or parking - lights.setTaxiOn(false); - lights.setLandingOn(false); - ddRemoteAircraftParts.setAllEngines(false); - } - } - else - { - // not on ground - ddRemoteAircraftParts.gearHandlePosition = 0; - lights.setTaxiOn(false); - lights.setBeaconOn(true); - lights.setNavOn(true); - // landing lights for < 10000ft (normally MSL, here ignored) - lights.setLandingOn(interpolatedSituation.getAltitude().value(CLengthUnit::ft()) < 10000); - - if (!simObj.isVtol() && interpolatedSituation.hasGroundElevation()) - { - if (interpolatedSituation.getHeightAboveGround().value(CLengthUnit::ft()) < 1000) - { - ddRemoteAircraftParts.gearHandlePosition = 1; - ddRemoteAircraftParts.flapsTrailingEdgeRightPercent = 25; - ddRemoteAircraftParts.flapsTrailingEdgeLeftPercent = 25; - } - else if (interpolatedSituation.getHeightAboveGround().value(CLengthUnit::ft()) < 2000) - { - ddRemoteAircraftParts.gearHandlePosition = 1; - ddRemoteAircraftParts.flapsTrailingEdgeRightPercent = 10; - ddRemoteAircraftParts.flapsTrailingEdgeLeftPercent = 10; - } - } - } - - return this->sendRemoteAircraftPartsToSimulator(simObj, ddRemoteAircraftParts, lights); - } - - bool CSimulatorFsx::updateRemoteAircraftParts(const CSimConnectObject &simObj, const CAircraftParts &parts, const CPartsStatus &partsStatus) - { - if (!simObj.hasValidRequestAndObjectId()) { return false; } - if (!partsStatus.isSupportingParts()) { return false; } - - DataDefinitionRemoteAircraftParts ddRemoteAircraftParts; // no init, all values will be set - ddRemoteAircraftParts.flapsLeadingEdgeLeftPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraftParts.flapsLeadingEdgeRightPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraftParts.flapsTrailingEdgeLeftPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraftParts.flapsTrailingEdgeRightPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraftParts.spoilersHandlePosition = parts.isSpoilersOut() ? 1 : 0; - ddRemoteAircraftParts.gearHandlePosition = parts.isGearDown() ? 1 : 0; - ddRemoteAircraftParts.engine1Combustion = parts.isEngineOn(1) ? 1 : 0; - ddRemoteAircraftParts.engine2Combustion = parts.isEngineOn(2) ? 1 : 0; - ddRemoteAircraftParts.engine3Combustion = parts.isEngineOn(3) ? 1 : 0; - ddRemoteAircraftParts.engine4Combustion = parts.isEngineOn(4) ? 1 : 0; - - CAircraftLights lights = parts.getLights(); - lights.setRecognitionOn(parts.isAnyEngineOn()); - lights.setCabinOn(parts.isAnyEngineOn()); - - return this->sendRemoteAircraftPartsToSimulator(simObj, ddRemoteAircraftParts, parts.getLights()); - } - - bool CSimulatorFsx::sendRemoteAircraftPartsToSimulator(const CSimConnectObject &simObj, DataDefinitionRemoteAircraftParts &ddRemoteAircraftParts, const CAircraftLights &lights) - { - Q_ASSERT(m_hSimConnect); - const DWORD objectId = simObj.getObjectId(); - - // same as in simulator or same as already send to simulator? - const CAircraftLights sentLights(simObj.getLightsAsSent()); - if (simObj.getPartsAsSent() == ddRemoteAircraftParts && sentLights == lights) { return true; } - - // in case we sent, we sent everything - const HRESULT hr = SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, - objectId, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, - sizeof(DataDefinitionRemoteAircraftParts), &ddRemoteAircraftParts); - - if (hr == S_OK) - { - // Update data - CSimConnectObject &objUdpate = m_simConnectObjects[simObj.getCallsign()]; - objUdpate.setPartsAsSent(ddRemoteAircraftParts); - } - else - { - CLogMessage(this).warning("Failed so set parts on SimObject '%1' callsign: '%2'") << simObj.getObjectId() << simObj.getCallsign(); - } - - // lights we can set directly - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventLandingLightsSet, lights.isLandingOn() ? 1.0 : 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventStrobesSet, lights.isStrobeOn() ? 1.0 : 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - - // lights we need to toggle (risk with quickly changing values that we accidentally toggle back) - sendToggledLightsToSimulator(simObj, lights); - - // done - return hr == S_OK; - } - - void CSimulatorFsx::sendToggledLightsToSimulator(const CSimConnectObject &simObj, const CAircraftLights &lightsWanted, bool force) - { - if (!simObj.hasValidRequestAndObjectId()) { return; } // stale - const CAircraftLights lightsIsState = simObj.getCurrentLightsInSimulator(); - if (lightsWanted == lightsIsState) { return; } - if (!force && lightsWanted == simObj.getLightsAsSent()) { return; } - const CCallsign callsign(simObj.getCallsign()); - - // Update data - CSimConnectObject &simObjToUpdate = m_simConnectObjects[callsign]; - simObjToUpdate.setLightsAsSent(lightsWanted); - - // state available, then I can toggle - if (!lightsIsState.isNull()) - { - const DWORD objectId = simObj.getObjectId(); - if (lightsWanted.isTaxiOn() != lightsIsState.isTaxiOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleTaxiLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (lightsWanted.isNavOn() != lightsIsState.isNavOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleNavLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (lightsWanted.isBeaconOn() != lightsIsState.isBeaconOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleBeaconLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (lightsWanted.isLogoOn() != lightsIsState.isLogoOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleLogoLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (lightsWanted.isRecognitionOn() != lightsIsState.isRecognitionOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleRecognitionLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (lightsWanted.isCabinOn() != lightsIsState.isCabinOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleCabinLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - return; - } - - // missing lights info from simulator - CLogMessage(this).info("Missing light state for '%1'") << callsign; - QTimer::singleShot(2500, this, [ = ] - { - const CSimConnectObject currentSimObj = m_simConnectObjects[callsign]; - if (!currentSimObj.hasValidRequestAndObjectId()) { return; } // stale - if (lightsWanted != currentSimObj.getLightsAsSent()) { return; } // changed in between - sendToggledLightsToSimulator(currentSimObj, lightsWanted, true); - }); - } - - SIMCONNECT_DATA_INITPOSITION CSimulatorFsx::aircraftSituationToFsxPosition(const CAircraftSituation &situation) - { - SIMCONNECT_DATA_INITPOSITION position; - position.Latitude = situation.latitude().value(CAngleUnit::deg()); - position.Longitude = situation.longitude().value(CAngleUnit::deg()); - position.Altitude = situation.getAltitude().value(CLengthUnit::ft()); // already corrected in interpolator if there is an underflow - position.Heading = situation.getHeading().value(CAngleUnit::deg()); - position.Airspeed = situation.getGroundSpeed().value(CSpeedUnit::kts()); - - // MSFS has inverted pitch and bank angles - position.Pitch = -situation.getPitch().value(CAngleUnit::deg()); - position.Bank = -situation.getBank().value(CAngleUnit::deg()); - position.OnGround = 0U; - - if (situation.isOnGroundInfoAvailable()) - { - const bool onGround = situation.isOnGround() == CAircraftSituation::OnGround; - position.OnGround = onGround ? 1U : 0U; - } - return position; - } - - void CSimulatorFsx::synchronizeTime(const CTime &zuluTimeSim, const CTime &localTimeSim) - { - if (!this->m_simTimeSynced) { return; } - if (!this->isConnected()) { return; } - if (m_syncDeferredCounter > 0) - { - --m_syncDeferredCounter; - } - Q_UNUSED(localTimeSim); - - QDateTime myDateTime = QDateTime::currentDateTimeUtc(); - if (!this->m_syncTimeOffset.isZeroEpsilonConsidered()) - { - int offsetSeconds = this->m_syncTimeOffset.valueRounded(CTimeUnit::s(), 0); - myDateTime = myDateTime.addSecs(offsetSeconds); - } - const QTime myTime = myDateTime.time(); - const DWORD h = static_cast(myTime.hour()); - const DWORD m = static_cast(myTime.minute()); - const int targetMins = myTime.hour() * 60 + myTime.minute(); - const int simMins = zuluTimeSim.valueRounded(CTimeUnit::min()); - const int diffMins = qAbs(targetMins - simMins); - if (diffMins < 2) { return; } - HRESULT hr = S_OK; - hr += SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetTimeZuluHours, h, SIMCONNECT_GROUP_PRIORITY_STANDARD, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - hr += SimConnect_TransmitClientEvent(m_hSimConnect, 0, EventSetTimeZuluMinutes, m, SIMCONNECT_GROUP_PRIORITY_STANDARD, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - - if (hr != S_OK) - { - CLogMessage(this).warning("Sending time sync failed!"); - } - else - { - m_syncDeferredCounter = 5; // allow some time to sync - CLogMessage(this).info("Synchronized time to UTC: '%1'") << myTime.toString(); - } - } - - void CSimulatorFsx::injectWeatherGrid(const Weather::CWeatherGrid &weatherGrid) - { - // So far, there is only global weather - auto glob = weatherGrid.frontOrDefault(); - glob.setIdentifier("GLOB"); - QString metar = CSimConnectUtilities::convertToSimConnectMetar(glob); - SimConnect_WeatherSetModeCustom(m_hSimConnect); - SimConnect_WeatherSetModeGlobal(m_hSimConnect); - SimConnect_WeatherSetObservation(m_hSimConnect, 0, qPrintable(metar)); - } - - bool CSimulatorFsx::requestDataForSimObject(const CSimConnectObject &simObject, SIMCONNECT_PERIOD period) - { - if (!simObject.hasValidRequestAndObjectId()) { return false; } - if (simObject.getSimDataPeriod() == period) { return true; } // already queried like this - - // always request, not only when something has changed - const HRESULT result = SimConnect_RequestDataOnSimObject( - m_hSimConnect, simObject.getRequestId() + RequestSimDataOffset, - CSimConnectDefinitions::DataRemoteAircraftSimData, - simObject.getObjectId(), period); - if (result == S_OK) - { - m_simConnectObjects[simObject.getCallsign()].setSimDataPeriod(period); - return true; - } - CLogMessage(this).error("Cannot request sim data on object '%1'") << simObject.getObjectId(); - return false; - } - - bool CSimulatorFsx::requestLightsForSimObject(const CSimConnectObject &simObject) - { - if (!simObject.hasValidRequestAndObjectId()) { return false; } - - // always request, not only when something has changed - const HRESULT result = SimConnect_RequestDataOnSimObject( - m_hSimConnect, simObject.getRequestId() + RequestLightsOffset, - CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(), - SIMCONNECT_PERIOD_SECOND); - if (result == S_OK) { return true; } - CLogMessage(this).error("Cannot request lights data on object '%1'") << simObject.getObjectId(); - return false; - } - - void CSimulatorFsx::initSimulatorInternals() - { - CSimulatorFsCommon::initSimulatorInternals(); - CSimulatorInternals s = this->m_simulatorInternals; - const QString fsxPath = CFsCommonUtil::fsxDirFromRegistry(); // can be empty for remote FSX - if (!fsxPath.isEmpty()) { s.setSimulatorInstallationDirectory(fsxPath); } - - s.setValue("fsx/simConnectCfgFilename", CSimConnectUtilities::getLocalSimConnectCfgFilename()); - s.setValue("fsx/simConnectVersion", this->m_simConnectVersion); - this->m_simulatorInternals = s; - } - - void CSimulatorFsx::reset() - { - if (m_simConnectTimerId >= 0) { killTimer(m_simConnectTimerId); } - m_simConnectTimerId = -1; - m_simConnected = false; - m_simSimulating = false; - m_syncDeferredCounter = 0; - m_skipCockpitUpdateCycles = 0; - m_interpolationRequest = 0; - m_requestIdSimData = RequestSimDataStart; - m_dispatchErrors = 0; - m_receiveExceptionCount = 0; - CSimulatorFsCommon::reset(); - } - - void CSimulatorFsx::clearAllAircraft() - { - m_simConnectObjects.clear(); - m_outOfRealityBubble.clear(); - CSimulatorFsCommon::clearAllAircraft(); - } - - void CSimulatorFsx::ps_remoteProviderAddAircraftSituation(const CAircraftSituation &situation) - { - if (!m_simConnectObjects.contains(situation.getCallsign())) { return; } - m_simConnectObjects[situation.getCallsign()].getInterpolator()->addAircraftSituation(situation); - } - - void CSimulatorFsx::ps_remoteProviderAddAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const CAircraftParts &parts) - { - if (!m_simConnectObjects.contains(callsign)) { return; } - m_simConnectObjects[callsign].getInterpolator()->addAircraftParts(parts); - } - - QString CSimulatorFsx::fsxPositionToString(const SIMCONNECT_DATA_INITPOSITION &position) - { - const QString positionStr("Lat: %1 lng: %2 alt: %3ft pitch: %4 bank: %5 hdg: %6 airspeed: %7kts onGround: %8"); - return positionStr. - arg(position.Latitude).arg(position.Longitude).arg(position.Altitude). - arg(position.Pitch).arg(position.Bank).arg(position.Heading).arg(position.Airspeed).arg(position.OnGround); - } - - CCallsignSet CSimulatorFsx::getCallsignsMissingInProvider() const - { - CCallsignSet simObjectCallsigns(m_simConnectObjects.keys()); - CCallsignSet providerCallsigns(this->getAircraftInRangeCallsigns()); - return simObjectCallsigns.difference(providerCallsigns); - } - - CCallsignSet CSimulatorFsx::ps_physicallyRemoveAircraftNotInProvider() - { - const CCallsignSet toBeRemoved(getCallsignsMissingInProvider()); - if (toBeRemoved.isEmpty()) { return toBeRemoved; } - for (const CCallsign &callsign : toBeRemoved) - { - physicallyRemoveRemoteAircraft(callsign); - } - return toBeRemoved; - } - - CSimulatorFsxListener::CSimulatorFsxListener(const CSimulatorPluginInfo &info) : - ISimulatorListener(info), - m_timer(new QTimer(this)) - { - constexpr int QueryInterval = 5 * 1000; // 5 seconds - m_timer->setInterval(QueryInterval); - m_timer->setObjectName(this->objectName().append(":m_timer")); - connect(m_timer, &QTimer::timeout, this, &CSimulatorFsxListener::ps_checkConnection); - } - - void CSimulatorFsxListener::start() - { - m_timer->start(); - } - - void CSimulatorFsxListener::stop() - { - m_timer->stop(); - } - - void CSimulatorFsxListener::ps_checkConnection() - { - Q_ASSERT_X(!CThreadUtils::isCurrentThreadApplicationThread(), Q_FUNC_INFO, "Expect to run in background"); - HANDLE hSimConnect; - HRESULT result = SimConnect_Open(&hSimConnect, sApp->swiftVersionChar(), nullptr, 0, 0, 0); - SimConnect_Close(hSimConnect); - if (result == S_OK) - { - emit simulatorStarted(this->getPluginInfo()); - } - } - } // namespace -} // namespace + } // ns +} // ns diff --git a/src/plugins/simulator/fsx/simulatorfsx.h b/src/plugins/simulator/fsx/simulatorfsx.h index 48da9f532..d859de607 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.h +++ b/src/plugins/simulator/fsx/simulatorfsx.h @@ -9,85 +9,17 @@ //! \file -#ifndef BLACKSIMPLUGIN_SIMULATOR_FSX_H -#define BLACKSIMPLUGIN_SIMULATOR_FSX_H +#ifndef BLACKSIMPLUGIN_FSX_SIMULATORFSX_H +#define BLACKSIMPLUGIN_FSX_SIMULATORFSX_H -#include "simconnectdatadefinition.h" -#include "simconnectobject.h" -#include "../fscommon/simulatorfscommon.h" -#include "blackcore/simulator.h" -#include "blackmisc/simulation/interpolatorlinear.h" -#include "blackmisc/simulation/simulatorplugininfo.h" -#include "blackmisc/simulation/simulatorsettings.h" -#include "blackmisc/simulation/aircraftmodel.h" -#include "blackmisc/simulation/simulatedaircraft.h" -#include "blackmisc/aviation/airportlist.h" -#include "blackmisc/statusmessage.h" -#include "blackmisc/network/client.h" -#include "blackmisc/pixmap.h" - -#include -#include -#include -#include -#include - -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include +#include "../fsxcommon/simulatorfsxcommon.h" namespace BlackSimPlugin { namespace Fsx { - //! SimConnect Event IDs - enum EventIds - { - SystemEventSimStatus, - SystemEventObjectAdded, - SystemEventObjectRemoved, - SystemEventSlewToggle, - SystemEventFrame, - SystemEventPause, - SystemEventFlightLoaded, - EventPauseToggle, - EventFreezeLat, - EventFreezeAlt, - EventFreezeAtt, - EventSetCom1Active, - EventSetCom2Active, - EventSetCom1Standby, - EventSetCom2Standby, - EventSetTransponderCode, - EventTextMessage, - EventSetTimeZuluYear, - EventSetTimeZuluDay, - EventSetTimeZuluHours, - EventSetTimeZuluMinutes, - // ------------ lights ------------- - EventLandingLightsOff, - EventLandinglightsOn, - EventLandingLightsSet, - EventLandingLightsToggle, - EventPanelLightsOff, - EventPanelLightsOn, - EventPanelLightsSet, - EventStrobesOff, - EventStrobesOn, - EventStrobesSet, - EventStrobesToggle, - EventToggleBeaconLights, - EventToggleCabinLights, - EventToggleLogoLights, - EventToggleNavLights, - EventToggleRecognitionLights, - EventToggleTaxiLights, - EventToggleWingLights - }; - //! FSX Simulator Implementation - class CSimulatorFsx : public BlackSimPlugin::FsCommon::CSimulatorFsCommon + class CSimulatorFsx : public BlackSimPlugin::FsxCommon::CSimulatorFsxCommon { Q_OBJECT @@ -99,213 +31,18 @@ namespace BlackSimPlugin BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, BlackMisc::Weather::IWeatherGridProvider *weatherGridProvider, QObject *parent = nullptr); - - //! Destructor - virtual ~CSimulatorFsx(); - - //! SimConnect Callback - static void CALLBACK SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext); - - //! \name ISimulator implementations - //! @{ - virtual bool connectTo() override; - virtual bool disconnectFrom() override; - virtual bool physicallyAddRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &newRemoteAircraft) override; - virtual bool physicallyRemoveRemoteAircraft(const BlackMisc::Aviation::CCallsign &callsign) override; - virtual int physicallyRemoveAllRemoteAircraft() override; - virtual bool updateOwnSimulatorCockpit(const BlackMisc::Simulation::CSimulatedAircraft &ownAircraft, const BlackMisc::CIdentifier &originator) override; - virtual void displayStatusMessage(const BlackMisc::CStatusMessage &message) const override; - virtual void displayTextMessage(const BlackMisc::Network::CTextMessage &message) const override; - virtual bool isPhysicallyRenderedAircraft(const BlackMisc::Aviation::CCallsign &callsign) const override; - virtual BlackMisc::Aviation::CCallsignSet physicallyRenderedAircraft() const override; - //! @} - - protected: - //! \name Interface implementations - //! @{ - virtual bool isConnected() const override; - virtual bool isSimulating() const override; - //! @} - - //! \name Base class overrides - //! @{ - virtual void reset() override; - virtual void clearAllAircraft() override; - virtual void initSimulatorInternals() override; - virtual void injectWeatherGrid(const BlackMisc::Weather::CWeatherGrid &weatherGrid) override; - virtual void ps_remoteProviderAddAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) override; - virtual void ps_remoteProviderAddAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftParts &parts) override; - //! @} - - //! Timer event (our SimConnect event loop), runs ps_dispatch - //! \sa m_simconnectTimerId - virtual void timerEvent(QTimerEvent *event) override; - - private slots: - //! Dispatch SimConnect messages - void ps_dispatch(); - - //! Remove aircraft not in provider anymore - //! \remark kind of cleanup function, in an ideal this should never need to cleanup something - BlackMisc::Aviation::CCallsignSet ps_physicallyRemoveAircraftNotInProvider(); - - //! Handle that an object has been added in simulator - //! \remark checks if the object was really added after an add request and not directly removed again - bool ps_deferredSimulatorReportedObjectAdded(const BlackMisc::Aviation::CCallsign &callsign); - - //! Try to add the aircraft currently out of bubble - void ps_addAircraftCurrentlyOutOfBubble(); - - private: - //! Call this method to declare the simulator connected - void setSimConnected(); - - //! Called when sim has started - void onSimRunning(); - - //! Slot called every visual frame - void onSimFrame(); - - //! Called when simulator has stopped, e.g. by selecting the "select aircraft screen" - void onSimStopped(); - - //! Simulator is going down - void onSimExit(); - - //! Get new request id, overflow safe - DWORD obtainRequestIdSimData(); - - //! Init when connected - HRESULT initWhenConnected(); - - //! Initialize SimConnect system events - HRESULT initEvents(); - - //! Initialize SimConnect data definitions - HRESULT initDataDefinitionsWhenConnected(); - - //! Update remote aircraft - void updateRemoteAircraft(); - - //! Update remote aircraft parts (send to FSX) - bool updateRemoteAircraftParts(const CSimConnectObject &simObj, - const BlackMisc::Aviation::CAircraftParts &parts, const BlackMisc::Simulation::CPartsStatus &partsStatus); - - //! Update remote aircraft parts by guessing (send to FSX) - bool guessAndUpdateRemoteAircraftParts(const CSimConnectObject &simObj, - const BlackMisc::Aviation::CAircraftSituation &interpolatedSituation, const BlackMisc::Simulation::CInterpolationStatus &interpolationStatus); - - //! Send parts to simulator - bool sendRemoteAircraftPartsToSimulator(const CSimConnectObject &simObj, DataDefinitionRemoteAircraftParts &ddRemoteAircraftParts, const BlackMisc::Aviation::CAircraftLights &lights); - - //! Send lights to simulator (those which have to be toggled) - //! \remark challenge here is that I can only sent those value if I have already obtained the current light state from simulator - void sendToggledLightsToSimulator(const CSimConnectObject &simObj, const BlackMisc::Aviation::CAircraftLights &lightsWanted, bool force = false); - - //! Called when data about our own aircraft are received - void updateOwnAircraftFromSimulator(const DataDefinitionOwnAircraft &simulatorOwnAircraft); - - //! Remote aircraft data sent from simulator - void updateRemoteAircraftFromSimulator(const CSimConnectObject &simObject, const DataDefinitionRemoteAircraftSimData &remoteAircraftData); - - //! Update from SB client area - void updateOwnAircraftFromSimulator(const DataDefinitionClientAreaSb &sbDataArea); - - //! An AI aircraft was added in the simulator - bool simulatorReportedObjectAdded(DWORD objectID); - - //! Simulator reported that AI aircraft was removed - bool simulatorReportedObjectRemoved(DWORD objectID); - - //! Set ID of a SimConnect object, so far we only have an request id in the object - bool setSimConnectObjectId(DWORD requestID, DWORD objectID); - - //! Remember current lights - bool setCurrentLights(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftLights &lights); - - //! Remember lights sent - bool setLightsAsSent(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftLights &lights); - - //! Display receive exceptions? - bool stillDisplayReceiveExceptions(); - - //! The simconnect related objects - const CSimConnectObjects &getSimConnectObjects() const { return m_simConnectObjects; } - - //! Format conversion - SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation); - - //! Sync time with user's computer - void synchronizeTime(const BlackMisc::PhysicalQuantities::CTime &zuluTimeSim, const BlackMisc::PhysicalQuantities::CTime &localTimeSim); - - //! Request data for a simObject (aka remote aircraft) - bool requestDataForSimObject(const CSimConnectObject &simObject, SIMCONNECT_PERIOD period = SIMCONNECT_PERIOD_SECOND); - - //! Request lights for a simObject - bool requestLightsForSimObject(const CSimConnectObject &simObject); - - //! FSX position as string - static QString fsxPositionToString(const SIMCONNECT_DATA_INITPOSITION &position); - - //! Get the callsigns which are no longer in the provider, but still in m_simConnectObjects - BlackMisc::Aviation::CCallsignSet getCallsignsMissingInProvider() const; - - //! Request for sim data? - static bool isRequestForSimData(DWORD requestId) { return requestId >= (RequestSimDataStart + RequestSimDataOffset) && requestId < (RequestSimDataStart + RequestSimDataOffset + SimObjectNumber); } - - //! Request for sim data? - static bool isRequestForLights(DWORD requestId) { return requestId >= (RequestSimDataStart + RequestLightsOffset) && requestId < (RequestSimDataStart + RequestLightsOffset + SimObjectNumber); } - - static constexpr int GuessRemoteAircraftPartsCycle = 20; //!< guess every n-th cycle - static constexpr int SkipUpdateCyclesForCockpit = 10; //!< skip x cycles before updating cockpit again - static constexpr int IgnoreReceiveExceptions = 10; //!< skip exceptions when displayed more than x times - static constexpr int SimObjectNumber = 10000; //!< max. SimObjects at the same time - static constexpr int RequestSimDataStart = static_cast(CSimConnectDefinitions::RequestEndMarker); - static constexpr int RequestSimDataEnd = RequestSimDataStart + SimObjectNumber - 1; - static constexpr int RequestSimDataOffset = 0 * SimObjectNumber; - static constexpr int RequestLightsOffset = 1 * SimObjectNumber; - - QString m_simConnectVersion; //!< SimConnect version - bool m_simConnected = false; //!< Is simulator connected? - bool m_simSimulating = false; //!< Simulator running? - bool m_useSbOffsets = true; //!< with SB offsets - int m_syncDeferredCounter = 0; //!< Set when synchronized, used to wait some time - int m_simConnectTimerId = -1; //!< Timer identifier - int m_skipCockpitUpdateCycles = 0; //!< skip some update cycles to allow changes in simulator cockpit to be set - int m_interpolationRequest = 0; //!< current interpolation request - int m_dispatchErrors = 0; //!< number of dispatched failed, \sa ps_dispatch - int m_receiveExceptionCount = 0; //!< exceptions - HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object - CSimConnectObjects m_simConnectObjects; //!< AI objects and their object / request ids - QTimer m_realityBubbleTimer { this }; //!< updating of aircraft out of reality bubble - DWORD m_requestIdSimData = RequestSimDataStart; //!< request id, use obtainRequestId() to get id - BlackMisc::Simulation::CSimulatedAircraftList m_outOfRealityBubble; //!< aircraft removed by FSX because they are out of reality bubble }; //! Listener for FSX - class CSimulatorFsxListener : public BlackCore::ISimulatorListener + class CSimulatorFsxListener : public BlackSimPlugin::FsxCommon::CSimulatorFsxCommonListener { Q_OBJECT public: //! Constructor - CSimulatorFsxListener(const BlackMisc::Simulation::CSimulatorPluginInfo &info); - - public slots: - //! \copydoc BlackCore::ISimulatorListener::start - virtual void start() override; - - //! \copydoc BlackCore::ISimulatorListener::stop - virtual void stop() override; - - private slots: - //! Test if connection can be established - void ps_checkConnection(); - - private: - QTimer *m_timer { nullptr }; + using CSimulatorFsxCommonListener::CSimulatorFsxCommonListener; }; - } -} // namespace + } // ns +} // ns #endif // guard diff --git a/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp b/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp deleted file mode 100644 index bb3fda20a..000000000 --- a/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* Copyright (C) 2013 - * swift Project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -#include "simulatorfsx.h" -#include "blackcore/application.h" -#include "simconnectdatadefinition.h" -#include "blackmisc/simulation/fscommon/bcdconversions.h" -#include "blackmisc/simulation/fsx/simconnectutilities.h" -#include "blackmisc/simulation/simulatorplugininfo.h" -#include "blackmisc/aviation/airportlist.h" -#include "blackmisc/logmessage.h" - -using namespace BlackCore; -using namespace BlackMisc; -using namespace BlackMisc::Simulation; -using namespace BlackMisc::Aviation; -using namespace BlackMisc::PhysicalQuantities; -using namespace BlackMisc::Geo; -using namespace BlackMisc::Network; -using namespace BlackMisc::Simulation; -using namespace BlackMisc::Simulation::FsCommon; -using namespace BlackMisc::Simulation::Fsx; - -namespace BlackSimPlugin -{ - namespace Fsx - { - void CALLBACK CSimulatorFsx::SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext) - { - CSimulatorFsx *simulatorFsx = static_cast(pContext); - switch (pData->dwID) - { - case SIMCONNECT_RECV_ID_OPEN: - { - SIMCONNECT_RECV_OPEN *event = (SIMCONNECT_RECV_OPEN *)pData; - simulatorFsx->m_simulatorVersion = QString("%1.%2.%3.%4").arg(event->dwApplicationVersionMajor).arg(event->dwApplicationVersionMinor).arg(event->dwApplicationBuildMajor).arg(event->dwApplicationBuildMinor); - simulatorFsx->m_simConnectVersion = QString("%1.%2.%3.%4").arg(event->dwSimConnectVersionMajor).arg(event->dwSimConnectVersionMinor).arg(event->dwSimConnectBuildMajor).arg(event->dwSimConnectBuildMinor); - simulatorFsx->m_simulatorName = QString(event->szApplicationName); - simulatorFsx->m_simulatorDetails = QString("Open: AppName=\"%1\" AppVersion=%2 SimConnectVersion=%3").arg(simulatorFsx->m_simulatorName, simulatorFsx->m_simulatorVersion, simulatorFsx->m_simConnectVersion); - CLogMessage(static_cast(nullptr)).info("Connect to FSX: %1") << sApp->swiftVersionString(); - simulatorFsx->setSimConnected(); - break; - } - case SIMCONNECT_RECV_ID_EXCEPTION: - { - if (!simulatorFsx->stillDisplayReceiveExceptions()) { break; } - SIMCONNECT_RECV_EXCEPTION *exception = (SIMCONNECT_RECV_EXCEPTION *)pData; - const DWORD exceptionId = exception->dwException; - const DWORD sendId = exception->dwSendID; - const DWORD index = exception->dwIndex; - const DWORD data = cbData; - const QString exStr(CSimConnectUtilities::simConnectExceptionToString((SIMCONNECT_EXCEPTION)exception->dwException)); - QString ex; - ex.sprintf("Exception=%lu | SendID=%lu | Index=%lu | cbData=%lu", exceptionId, sendId, index, data); - switch (exceptionId) - { - case SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE: - break; - case SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID: - break; - default: - break; - } - CLogMessage(simulatorFsx).warning("Caught FSX simConnect exception: %1 %2") << exStr << ex; - break; - } - case SIMCONNECT_RECV_ID_QUIT: - { - simulatorFsx->onSimExit(); - break; - } - case SIMCONNECT_RECV_ID_EVENT: - { - SIMCONNECT_RECV_EVENT *event = static_cast(pData); - switch (event->uEventID) - { - case SystemEventSimStatus: - { - const bool running = event->dwData ? true : false; - if (running) - { - simulatorFsx->onSimRunning(); - } - else - { - simulatorFsx->onSimStopped(); - } - break; - } - case SystemEventPause: - { - const bool p = event->dwData ? true : false; - if (simulatorFsx->m_simPaused != p) - { - simulatorFsx->m_simPaused = p; - simulatorFsx->emitSimulatorCombinedStatus(); - } - break; - } - default: - break; - } - break; - } - case SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE: - { - const SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE *event = static_cast(pData); - const DWORD objectID = event->dwData; - const SIMCONNECT_SIMOBJECT_TYPE objectType = event->eObjType; - if (objectType != SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT && objectType != SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER) - { - break; - } - - // such an object is not necessarily one of ours - // for instance, I always see object 5 when I start the simulator - if (!simulatorFsx->getSimConnectObjects().isKnownSimObjectId(objectID)) break; - switch (event->uEventID) - { - case SystemEventObjectAdded: - // added in SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID - break; - case SystemEventObjectRemoved: - simulatorFsx->simulatorReportedObjectRemoved(objectID); - break; - default: - break; - } - break; - } - case SIMCONNECT_RECV_ID_EVENT_FRAME: - { - SIMCONNECT_RECV_EVENT_FRAME *event = (SIMCONNECT_RECV_EVENT_FRAME *) pData; - switch (event->uEventID) - { - case SystemEventFrame: - // doing interpolation - simulatorFsx->onSimFrame(); - break; - default: - break; - } - break; - } - case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID: - { - SIMCONNECT_RECV_ASSIGNED_OBJECT_ID *event = static_cast(pData); - const DWORD requestId = event->dwRequestID; - const DWORD objectId = event->dwObjectID; - bool success = simulatorFsx->setSimConnectObjectId(requestId, objectId); - if (!success) { break; } // not an request ID of ours - - success = simulatorFsx->simulatorReportedObjectAdded(objectId); - if (success) - { - const CSimConnectObject simObject = simulatorFsx->getSimConnectObjects().getSimObjectForObjectId(objectId); - HRESULT result = S_OK; - result += simulatorFsx->requestDataForSimObject(simObject); - result += simulatorFsx->requestLightsForSimObject(simObject); - Q_UNUSED(result); - } - else - { - const CSimulatedAircraft remoteAircraft(simulatorFsx->getSimConnectObjects().getSimObjectForObjectId(objectId).getAircraft()); - const CStatusMessage msgAdd = CStatusMessage(simulatorFsx).error("Cannot add object %1") << objectId; - CLogMessage::preformatted(msgAdd); - emit simulatorFsx->physicallyAddingRemoteModelFailed(remoteAircraft, msgAdd); - } - break; - } - case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE: - { - // SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE *)pData; - break; - } - case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: - { - SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA *) pData; - const DWORD requestId = pObjData->dwRequestID; - switch (requestId) - { - case CSimConnectDefinitions::RequestOwnAircraft: - { - static_assert(sizeof(DataDefinitionOwnAircraft) == 30 * sizeof(double), "DataDefinitionOwnAircraft has an incorrect size."); - const DataDefinitionOwnAircraft *ownAircaft = (DataDefinitionOwnAircraft *)&pObjData->dwData; - simulatorFsx->updateOwnAircraftFromSimulator(*ownAircaft); - break; - } - case CSimConnectDefinitions::RequestOwnAircraftTitle: - { - const DataDefinitionOwnAircraftModel *dataDefinitionModel = (DataDefinitionOwnAircraftModel *) &pObjData->dwData; - CAircraftModel model; - model.setModelString(dataDefinitionModel->title); - model.setModelType(CAircraftModel::TypeOwnSimulatorModel); - simulatorFsx->reverseLookupAndUpdateOwnAircraftModel(model); - break; - } - case CSimConnectDefinitions::RequestSimEnvironment: - { - const DataDefinitionSimEnvironment *simEnv = (DataDefinitionSimEnvironment *) &pObjData->dwData; - if (simulatorFsx->isTimeSynchronized()) - { - const int zh = simEnv->zuluTimeSeconds / 3600; - const int zm = (simEnv->zuluTimeSeconds - (zh * 3600)) / 60; - const CTime zulu(zh, zm); - const int lh = simEnv->localTimeSeconds / 3600; - const int lm = (simEnv->localTimeSeconds - (lh * 3600)) / 60; - const CTime local(lh, lm); - simulatorFsx->synchronizeTime(zulu, local); - } - break; - } - default: - { - const DWORD objectId = pObjData->dwObjectID; - if (isRequestForSimData(requestId)) - { - static_assert(sizeof(DataDefinitionRemoteAircraftSimData) == 5 * sizeof(double), "DataDefinitionRemoteAircraftSimData has an incorrect size."); - const CSimConnectObject simObj = simulatorFsx->getSimConnectObjects().getSimObjectForObjectId(objectId); - if (!simObj.hasValidRequestAndObjectId()) break; - const DataDefinitionRemoteAircraftSimData *remoteAircraftSimData = (DataDefinitionRemoteAircraftSimData *)&pObjData->dwData; - // extra check, but ids should be the same - if (objectId == simObj.getObjectId()) - { - simulatorFsx->updateRemoteAircraftFromSimulator(simObj, *remoteAircraftSimData); - } - } - else if (isRequestForLights(requestId)) - { - static_assert(sizeof(DataDefinitionRemoteAircraftLights) == 8 * sizeof(double), "DataDefinitionRemoteAircraftLights has an incorrect size."); - const CSimConnectObject simObj = simulatorFsx->getSimConnectObjects().getSimObjectForObjectId(objectId); - if (!simObj.hasValidRequestAndObjectId()) break; - const DataDefinitionRemoteAircraftLights *remoteAircraftLights = (DataDefinitionRemoteAircraftLights *)&pObjData->dwData; - // extra check, but ids should be the same - if (objectId == simObj.getObjectId()) - { - const CCallsign callsign(simObj.getCallsign()); - const CAircraftLights lights = remoteAircraftLights->toLights(); // as in simulator - simulatorFsx->setCurrentLights(callsign, lights); - if (simObj.getLightsAsSent().isNull()) - { - // allows to compare for toggle - simulatorFsx->setLightsAsSent(callsign, lights); - } - } - } - break; - } - break; - } - break; - } - case SIMCONNECT_RECV_ID_AIRPORT_LIST: - { - static const CLength maxDistance(200.0, CLengthUnit::NM()); - const CCoordinateGeodetic posAircraft(simulatorFsx->getOwnAircraftPosition()); - SIMCONNECT_RECV_AIRPORT_LIST *pAirportList = (SIMCONNECT_RECV_AIRPORT_LIST *) pData; - for (unsigned i = 0; i < pAirportList->dwArraySize; ++i) - { - SIMCONNECT_DATA_FACILITY_AIRPORT *pFacilityAirport = pAirportList->rgData + i; - if (!pFacilityAirport) { break; } - const QString icao(pFacilityAirport->Icao); - if (icao.isEmpty()) { continue; } // airfield without ICAO code - if (!CAirportIcaoCode::isValidIcaoDesignator(icao)) { continue; } // tiny airfields/strips in simulator - if (CAirportIcaoCode::containsNumbers(icao)) { continue; } // tiny airfields/strips in simulator - const CCoordinateGeodetic pos(pFacilityAirport->Latitude, pFacilityAirport->Longitude, pFacilityAirport->Altitude); - CAirport airport(CAirportIcaoCode(icao), pos); - const CLength d = airport.calculcateAndUpdateRelativeDistanceAndBearing(posAircraft); - if (d > maxDistance) { continue; } - airport.updateMissingParts(simulatorFsx->getWebServiceAirport(icao)); - simulatorFsx->m_airportsInRangeFromSimulator.replaceOrAddByIcao(airport); - } - - if (simulatorFsx->m_airportsInRangeFromSimulator.size() > simulatorFsx->maxAirportsInRange()) - { - simulatorFsx->m_airportsInRangeFromSimulator.sortByDistanceToOwnAircraft(); - simulatorFsx->m_airportsInRangeFromSimulator.truncate(simulatorFsx->maxAirportsInRange()); - } - break; - } - case SIMCONNECT_RECV_ID_CLIENT_DATA: - { - if (!simulatorFsx->m_useSbOffsets) { break; } - SIMCONNECT_RECV_CLIENT_DATA *clientData = (SIMCONNECT_RECV_CLIENT_DATA *)pData; - if (simulatorFsx->m_useSbOffsets && clientData->dwRequestID == CSimConnectDefinitions::RequestSbData) - { - //! \fixme FSUIPC vs SimConnect why is offset 19 ident 2/0? In FSUIPC it is 0/1, according to documentation it is 0/1 but I receive 2/0 here. Whoever knows, add comment or fix if wrong - DataDefinitionClientAreaSb *sbData = (DataDefinitionClientAreaSb *) &clientData->dwData; - simulatorFsx->updateOwnAircraftFromSimulator(*sbData); - } - break; - } - case SIMCONNECT_RECV_ID_EVENT_FILENAME: - { - SIMCONNECT_RECV_EVENT_FILENAME *event = static_cast(pData); - switch (event->uEventID) - { - case SystemEventFlightLoaded: - break; - default: - break; - } - break; - } - default: - break; - } // main switch - } // method - } // namespace -} // namespace diff --git a/src/plugins/simulator/fsxconfig/fsxconfig.pro b/src/plugins/simulator/fsxconfig/fsxconfig.pro index b358a0334..96ee474d1 100644 --- a/src/plugins/simulator/fsxconfig/fsxconfig.pro +++ b/src/plugins/simulator/fsxconfig/fsxconfig.pro @@ -12,9 +12,8 @@ INCLUDEPATH += . $$SourceRoot/src SOURCES += *.cpp HEADERS += *.h -FORMS += *.ui DISTFILES += simulatorfsxconfig.json - +LIBS += -lsimulatorfsxcommon DESTDIR = $$DestRoot/bin/plugins/simulator win32 { diff --git a/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.cpp b/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.cpp deleted file mode 100644 index 5f7dc1c7f..000000000 --- a/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright (C) 2015 - * swift project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -#include "simconnectsettingscomponent.h" -#include "ui_simconnectsettingscomponent.h" -#include "blackgui/guiapplication.h" -#include "blackcore/context/contextapplication.h" -#include "blackcore/context/contextsimulator.h" -#include "blackmisc/network/networkutils.h" -#include "blackmisc/logmessage.h" -#include "blackmisc/simulation/fsx/simconnectutilities.h" -#include -#include -#include -#include -#include - -using namespace BlackMisc; -using namespace BlackMisc::Simulation::Fsx; -using namespace BlackMisc::Network; - -namespace BlackSimPlugin -{ - namespace Fsx - { - CSimConnectSettingsComponent::CSimConnectSettingsComponent(QWidget *parent) : - QFrame(parent), - ui(new Ui::CSimConnectSettingsComponent) - { - ui->setupUi(this); - - connect(ui->pb_SettingsFsxOpenSimconnectCfg, &QPushButton::clicked, this, &CSimConnectSettingsComponent::openSimConnectCfgFile); - connect(ui->pb_SettingsFsxDeleteSimconnectCfg, &QPushButton::clicked, this, &CSimConnectSettingsComponent::deleteSimConnectCfgFile); - connect(ui->pb_SettingsFsxExistsSimconncetCfg, &QPushButton::clicked, this, &CSimConnectSettingsComponent::checkSimConnectCfgFile); - connect(ui->pb_SettingsFsxSaveSimconnectCfg, &QPushButton::clicked, this, &CSimConnectSettingsComponent::saveSimConnectCfgFile); - connect(ui->pb_SettingsFsxTestConnection, &QPushButton::clicked, this, &CSimConnectSettingsComponent::testSimConnectConnection); - } - - CSimConnectSettingsComponent::~CSimConnectSettingsComponent() - { - // void - } - - void CSimConnectSettingsComponent::openSimConnectCfgFile() - { - const QFileInfo info(CSimConnectUtilities::getLocalSimConnectCfgFilename()); - const QString path = QDir::toNativeSeparators(info.absolutePath()); - QDesktopServices::openUrl(QUrl(QStringLiteral("file:///") % path)); - } - - void CSimConnectSettingsComponent::deleteSimConnectCfgFile() - { - const QString fileName = CSimConnectUtilities::getLocalSimConnectCfgFilename(); - const bool result = sGui->getIContextApplication()->removeFile(fileName); - if (result) - { - QMessageBox::information(qApp->activeWindow(), tr("File deleted"), - tr("File %1 deleted successfully.").arg(fileName)); - } - checkSimConnectCfgFile(); - } - - void CSimConnectSettingsComponent::checkSimConnectCfgFile() - { - const QString fileName = CSimConnectUtilities::getLocalSimConnectCfgFilename(); - if (sGui->getIContextApplication()->existsFile(fileName)) - { - ui->le_SettingsFsxExistsSimconncetCfg->setText(fileName); - } - else - { - ui->le_SettingsFsxExistsSimconncetCfg->setText("no file"); - } - } - - void CSimConnectSettingsComponent::testSimConnectConnection() - { - const QString address = ui->le_SettingsFsxAddress->text().trimmed(); - const QString port = ui->le_SettingsFsxPort->text().trimmed(); - - if (address.isEmpty() || port.isEmpty()) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), - tr("Address and/or port not specified!")); - return; - } - if (!CNetworkUtils::isValidIPv4Address(address)) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), - tr("Wrong IPv4 address!")); - return; - } - if (!CNetworkUtils::isValidPort(port)) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), - tr("Invalid port!")); - return; - } - int p = port.toInt(); - QString msg; - if (!CNetworkUtils::canConnect(address, p, msg)) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), msg); - return; - } - - QMessageBox::information(qApp->activeWindow(), tr("Connection successful"), - tr("Connected to %1:%2.").arg(address, port)); - } - - void CSimConnectSettingsComponent::saveSimConnectCfgFile() - { - QString address = ui->le_SettingsFsxAddress->text().trimmed(); - QString port = ui->le_SettingsFsxPort->text().trimmed(); - - if (address.isEmpty() || port.isEmpty()) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), - tr("Address and/or port not specified!")); - return; - } - if (!CNetworkUtils::isValidIPv4Address(address)) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), - tr("Wrong IPv4 address!")); - return; - } - if (!CNetworkUtils::isValidPort(port)) - { - QMessageBox::warning(qApp->activeWindow(), tr("Connection invalid"), - tr("Invalid port!")); - return; - } - - int p = port.toInt(); - QString fileName; - - if (sGui->getIContextSimulator()) - { - const BlackMisc::Simulation::CSimulatorInternals internals(sGui->getIContextSimulator()->getSimulatorInternals()); - fileName = internals.getStringValue("fsx/simConnectCfgFilename"); - } - - if (fileName.isEmpty()) - { - fileName = CSimConnectUtilities::getLocalSimConnectCfgFilename(); - } - - if (fileName.isEmpty()) - { - QMessageBox::warning(qApp->activeWindow(), tr("Failed writing simConnect.cfg"), - tr("No file name specified!")); - return; - } - - if (sGui->getIContextApplication()->writeToFile(fileName, CSimConnectUtilities::simConnectCfg(address, p))) - { - QMessageBox::information(qApp->activeWindow(), tr("File saved"), - tr("File %1 saved.").arg(fileName)); - checkSimConnectCfgFile(); - } - else - { - QMessageBox::warning(qApp->activeWindow(), tr("Failed writing simConnect.cfg"), - tr("Failed writing %1!").arg(fileName)); - } - } - } // ns -} // ns diff --git a/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.h b/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.h deleted file mode 100644 index d7ae25acb..000000000 --- a/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (C) 2015 - * swift project Community / Contributors - * - * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -//! \file - -#ifndef BLACKSIMPLUGIN_SIMCONNECT_SETTINGS_COMPONENT_H -#define BLACKSIMPLUGIN_SIMCONNECT_SETTINGS_COMPONENT_H - -#include -#include - -namespace Ui { class CSimConnectSettingsComponent; } - -namespace BlackSimPlugin -{ - namespace Fsx - { - /*! - * A component that gathers all SimConnect-related settings. - */ - class CSimConnectSettingsComponent : public QFrame - { - Q_OBJECT - - public: - //! Ctor - explicit CSimConnectSettingsComponent(QWidget *parent = nullptr); - - //! Dtor - ~CSimConnectSettingsComponent(); - - private slots: - //! Open simConnect.cfg using default application - void openSimConnectCfgFile(); - - //! Delete simConnect.cfg file - void deleteSimConnectCfgFile(); - - //! Check whether the simConnect.cfg file exists - void checkSimConnectCfgFile(); - - //! Test the SimConnect connectivity - void testSimConnectConnection(); - - //! Save a simconnect.cfg file for FSX - void saveSimConnectCfgFile(); - - private: - QScopedPointer ui; - }; - } // ns -} // ns - -#endif // guard diff --git a/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.ui b/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.ui deleted file mode 100644 index 8a7d8c1a4..000000000 --- a/src/plugins/simulator/fsxconfig/simconnectsettingscomponent.ui +++ /dev/null @@ -1,246 +0,0 @@ - - - CSimConnectSettingsComponent - - - - 0 - 0 - 400 - 158 - - - - Form - - - - - - FSX SimConnect config file - - - - 4 - - - 6 - - - 4 - - - 4 - - - - - FSX address - - - - - - - - 0 - 0 - - - - 127.0.0.1 - - - 128 - - - - - - - FSX port - - - - - - - - 0 - 0 - - - - 500 - - - - - - - is 'SimConnect.cfg' available? - - - .cfg? - - - - - - - - 4 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - true - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - check - - - - - - - - - - 3 - - - - - - 0 - 0 - - - - - 50 - 0 - - - - open - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - del. - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 16777215 - 16777215 - - - - save - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 16777215 - 16777215 - - - - Test connection - - - test - - - - - - - - - - - - - diff --git a/src/plugins/simulator/fsxconfig/simulatorfsxconfig.cpp b/src/plugins/simulator/fsxconfig/simulatorfsxconfig.cpp index 2d8387d35..8b53b9eb8 100644 --- a/src/plugins/simulator/fsxconfig/simulatorfsxconfig.cpp +++ b/src/plugins/simulator/fsxconfig/simulatorfsxconfig.cpp @@ -1,5 +1,14 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + #include "simulatorfsxconfig.h" -#include "simulatorfsxconfigwindow.h" +#include "../fsxcommon/simulatorfsxconfigwindow.h" namespace BlackSimPlugin { @@ -12,7 +21,7 @@ namespace BlackSimPlugin BlackGui::CPluginConfigWindow *CSimulatorFsxConfig::createConfigWindow(QWidget *parent) { - return new CSimulatorFsxConfigWindow(parent); + return new FsxCommon::CSimulatorFsxConfigWindow("P3D", parent); } } } diff --git a/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.cpp b/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.cpp deleted file mode 100644 index 75ec5bded..000000000 --- a/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "simulatorfsxconfigwindow.h" -#include "ui_simulatorfsxconfigwindow.h" - - -using namespace BlackGui; - -namespace BlackSimPlugin -{ - namespace Fsx - { - CSimulatorFsxConfigWindow::CSimulatorFsxConfigWindow(QWidget *parent) : - CPluginConfigWindow(parent), - ui(new Ui::CSimulatorFsxConfigWindow) - { - ui->setupUi(this); - connect(ui->bb_OkCancel, &QDialogButtonBox::rejected, this, &QWidget::close); - } - - CSimulatorFsxConfigWindow::~CSimulatorFsxConfigWindow() - { - // void - } - } -} diff --git a/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.h b/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.h deleted file mode 100644 index df7dbc9a5..000000000 --- a/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2015 - * swift project Community / Contributors - * - * This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level - * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, - * including this file, may be copied, modified, propagated, or distributed except according to the terms - * contained in the LICENSE file. - */ - -//! \file - -#ifndef BLACKSIMPLUGIN_SIMULATOR_FSX_CONFIG_WINDOW_H -#define BLACKSIMPLUGIN_SIMULATOR_FSX_CONFIG_WINDOW_H - -#include "simulatorfsxconfig.h" -#include "blackgui/pluginconfigwindow.h" -#include - -namespace Ui { class CSimulatorFsxConfigWindow; } - -namespace BlackSimPlugin -{ - namespace Fsx - { - /** - * A window the lets user set up the FSX plugin. - */ - class CSimulatorFsxConfigWindow : public BlackGui::CPluginConfigWindow - { - Q_OBJECT - - public: - //! Ctor. - CSimulatorFsxConfigWindow(QWidget *parent); - - //! Dtor. - virtual ~CSimulatorFsxConfigWindow(); - - private: - QScopedPointer ui; - }; - } -} - -#endif // guard diff --git a/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.ui b/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.ui deleted file mode 100644 index 133f0ec58..000000000 --- a/src/plugins/simulator/fsxconfig/simulatorfsxconfigwindow.ui +++ /dev/null @@ -1,46 +0,0 @@ - - - CSimulatorFsxConfigWindow - - - - 0 - 0 - 400 - 300 - - - - FSX plugin settings - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - QDialogButtonBox::Close - - - - - - - - BlackSimPlugin::Fsx::CSimConnectSettingsComponent - QFrame -
simconnectsettingscomponent.h
- 1 -
-
- - -