refs #891, FSX using common base class

This commit is contained in:
Klaus Basan
2017-02-28 04:33:34 +01:00
committed by Mathew Sutcliffe
parent 70045c046d
commit 5d8ed66931
16 changed files with 24 additions and 3213 deletions

View File

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

View File

@@ -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 <tuple>
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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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<CSimConnectDefinitions *>(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

View File

@@ -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 <QtGlobal>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include "blackmisc/aviation/aircraftlights.h"
#include <simconnect/SimConnect.h>
#include <windows.h>
#include <algorithm>
#include <QString>
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<byte>(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

View File

@@ -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<BlackMisc::Simulation::CInterpolatorLinear>::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

View File

@@ -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 <QSharedPointer>
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<BlackMisc::Simulation::CInterpolatorLinear> m_interpolator; //!< shared pointer because CSimConnectObject can be copied
};
//! Simulator objects (aka AI aircraft)
class CSimConnectObjects : public QHash<BlackMisc::Aviation::CCallsign, CSimConnectObject>
{
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

File diff suppressed because it is too large Load Diff

View File

@@ -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 <simconnect/SimConnect.h>
#include <QObject>
#include <QtPlugin>
#include <QHash>
#include <QFutureWatcher>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#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<int>(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

View File

@@ -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<CSimulatorFsx *>(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<CSimulatorFsx *>(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<SIMCONNECT_RECV_EVENT *>(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<SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE *>(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<SIMCONNECT_RECV_ASSIGNED_OBJECT_ID *>(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<SIMCONNECT_RECV_EVENT_FILENAME *>(pData);
switch (event->uEventID)
{
case SystemEventFlightLoaded:
break;
default:
break;
}
break;
}
default:
break;
} // main switch
} // method
} // namespace
} // namespace