mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-06 01:45:38 +08:00
Moved FSX specific implementation into blacksim/fsx and
converted it into a plugin. refs #190
This commit is contained in:
@@ -28,12 +28,6 @@ SOURCES += *.cpp
|
||||
win32 {
|
||||
HEADERS += $$PWD/win/*.h
|
||||
SOURCES += $$PWD/win/*.cpp
|
||||
|
||||
contains(BLACK_CONFIG, FSX) {
|
||||
DEFINES += BLACK_WITH_FSX
|
||||
HEADERS += $$PWD/fsx/*.h
|
||||
SOURCES += $$PWD/fsx/*.cpp
|
||||
}
|
||||
}
|
||||
|
||||
win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib ../../lib/blacksound.lib
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
|
||||
#include "context_simulator_impl.h"
|
||||
#include "coreruntime.h"
|
||||
|
||||
#ifdef BLACK_WITH_FSX
|
||||
#include "fsx/simulator_fsx.h"
|
||||
#endif
|
||||
#include <QPluginLoader>
|
||||
|
||||
using namespace BlackMisc;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
@@ -26,10 +23,6 @@ namespace BlackCore
|
||||
{
|
||||
m_updateTimer = new QTimer(this);
|
||||
|
||||
#ifdef BLACK_WITH_FSX
|
||||
m_simulator = new BlackCore::FSX::CSimulatorFSX(this);
|
||||
connect(m_simulator, &ISimulator::connectionChanged, this, &CContextSimulator::setConnectionStatus);
|
||||
#endif
|
||||
connect(m_updateTimer, &QTimer::timeout, this, &CContextSimulator::updateOwnAircraft);
|
||||
}
|
||||
|
||||
@@ -53,13 +46,16 @@ namespace BlackCore
|
||||
|
||||
void CContextSimulator::init()
|
||||
{
|
||||
loadPlugins();
|
||||
|
||||
if (!m_contextNetwork)
|
||||
{
|
||||
m_contextNetwork = getRuntime()->getIContextNetwork();
|
||||
}
|
||||
|
||||
if (m_simulator)
|
||||
connect(m_contextNetwork, &IContextNetwork::aircraftSituationUpdate, m_simulator, &ISimulator::addAircraftSituation);
|
||||
connect(m_contextNetwork, SIGNAL(aircraftSituationUpdate(BlackMisc::Aviation::CCallsign,BlackMisc::Aviation::CAircraftSituation)),
|
||||
m_simulator, SLOT(addAircraftSituation(BlackMisc::Aviation::CCallsign,BlackMisc::Aviation::CAircraftSituation)));
|
||||
}
|
||||
|
||||
void CContextSimulator::updateOwnAircraft()
|
||||
@@ -84,4 +80,30 @@ namespace BlackCore
|
||||
emit connectionChanged(value);
|
||||
}
|
||||
|
||||
void CContextSimulator::loadPlugins()
|
||||
{
|
||||
m_pluginsDir = QDir(qApp->applicationDirPath());
|
||||
m_pluginsDir.cd("plugins");
|
||||
|
||||
foreach (QString fileName, m_pluginsDir.entryList(QDir::Files))
|
||||
{
|
||||
QPluginLoader loader(m_pluginsDir.absoluteFilePath(fileName));
|
||||
QObject *plugin = loader.instance();
|
||||
if (plugin)
|
||||
{
|
||||
ISimulatorFactory *factory = qobject_cast<ISimulatorFactory*>(plugin);
|
||||
if(plugin)
|
||||
{
|
||||
m_simulator = factory->create(this);
|
||||
connect(m_simulator, SIGNAL(connectionChanged(bool)), this, SLOT(setConnectionStatus(bool)));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << loader.errorString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BlackCore
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "blackcore/simulator.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QDir>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
@@ -83,11 +84,21 @@ namespace BlackCore
|
||||
void setConnectionStatus(bool value);
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
* \brief Load any kind of plugins
|
||||
* \todo Currently it goes through the plugins folder and creates an instance for any plugin it may find
|
||||
* In case an FSX and an X-Plane are in that folder, m_simulator will always point to X-Plane in the end.
|
||||
*/
|
||||
void loadPlugins();
|
||||
|
||||
BlackMisc::Aviation::CAircraft m_ownAircraft;
|
||||
BlackCore::ISimulator *m_simulator;
|
||||
|
||||
QTimer *m_updateTimer;
|
||||
BlackCore::IContextNetwork *m_contextNetwork;
|
||||
|
||||
QDir m_pluginsDir;
|
||||
};
|
||||
|
||||
} // namespace BlackCore
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "simconnect_datadefinition.h"
|
||||
#include "simconnect/SimConnect.h"
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
namespace FSX
|
||||
{
|
||||
|
||||
CSimConnectDataDefinition::CSimConnectDataDefinition()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CSimConnectDataDefinition::initDataDefinitions(const HANDLE hSimConnect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
hr = initOwnAircraft(hSimConnect);
|
||||
hr = initAircraftPosition(hSimConnect);
|
||||
hr = initAircraftConfiguration(hSimConnect);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CSimConnectDataDefinition::initOwnAircraft(const HANDLE hSimConnect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Latitude", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Longitude", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Altitude", "Feet");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Heading Degrees True", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Pitch Degrees", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "Plane Bank Degrees", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "GROUND VELOCITY", "knots");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "SIM ON GROUND", "bool");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "TRANSPONDER CODE:1", NULL);
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM ACTIVE FREQUENCY:1", "MHz");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM ACTIVE FREQUENCY:2", "MHz");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM STANDBY FREQUENCY:1", "MHz");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataOwnAircraft, "COM STANDBY FREQUENCY:2", "MHz");
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CSimConnectDataDefinition::initAircraftPosition(const HANDLE hSimConnect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, "Plane Latitude", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, "Plane Longitude", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, "Plane Altitude", "Feet");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, "Plane Heading Degrees True", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, "Plane Pitch Degrees", "Degrees");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, "Plane Bank Degrees", "Degrees");
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CSimConnectDataDefinition::initAircraftConfiguration(const HANDLE hSimConnect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, "GEAR CENTER POSITION", "Percent Over 100");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, "GEAR LEFT POSITION", "Percent Over 100");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, "GEAR RIGHT POSITION", "Percent Over 100");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, "GEAR TAIL POSITION", "Percent Over 100");
|
||||
hr = SimConnect_AddToDataDefinition(hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, "GEAR AUX POSITION", "Percent Over 100");
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BLACKCORE_FSX_SIMCONNECT_DATADEFINITION_H
|
||||
#define BLACKCORE_FSX_SIMCONNECT_DATADEFINITION_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
namespace FSX
|
||||
{
|
||||
//! \brief Data struct of our own aircraft
|
||||
struct DataDefinitionOwnAircraft
|
||||
{
|
||||
double latitude; //!< Latitude
|
||||
double longitude; //!< Longitude
|
||||
double altitude; //!< Altitude
|
||||
double trueHeading; //!< True heading
|
||||
double pitch; //!< Pitch
|
||||
double bank; //!< Bank
|
||||
double velocity; //!< Ground velocity
|
||||
double simOnGround; //!< Is sim on ground?
|
||||
double transponderCode; //!< Transponder Code
|
||||
double com1ActiveMHz; //!< COM1 active frequency
|
||||
double com2ActiveMHz; //!< COM2 active frequency
|
||||
double com1StandbyMHz; //!< COM1 standby frequency
|
||||
double com2StandbyMHz; //!< COM1 standby frequency
|
||||
};
|
||||
|
||||
//! \brief Data struct of aircraft position
|
||||
struct DataDefinitionAircraftPosition
|
||||
{
|
||||
double latitude; //!< Latitude
|
||||
double longitude; //!< Longitude
|
||||
double altitude; //!< Altitude
|
||||
double trueHeading; //!< True heading
|
||||
double pitch; //!< Pitch
|
||||
double bank; //!< Bank
|
||||
};
|
||||
|
||||
//! \brief Data struct of aircraft position
|
||||
struct DataDefinitionAircraftConfiguration
|
||||
{
|
||||
double gearCenter; //!< Gear center
|
||||
double gearLeft; //!< Gear left
|
||||
double gearRight; //!< Gear right
|
||||
double gearTail; //!< Gear tail
|
||||
double gearAux; //!< Gear aux
|
||||
};
|
||||
|
||||
//! \brief Handles SimConnect data definitions
|
||||
class CSimConnectDataDefinition
|
||||
{
|
||||
public:
|
||||
|
||||
//! \brief SimConnect definiton ID's
|
||||
enum DataDefiniton {
|
||||
DataOwnAircraft,
|
||||
DataAircraftPosition,
|
||||
DataAircraftConfiguration
|
||||
};
|
||||
|
||||
//! \brief SimConnect request ID's
|
||||
enum Requests {
|
||||
RequestOwnAircraft = 1000
|
||||
};
|
||||
|
||||
//! \brief Constructor
|
||||
CSimConnectDataDefinition();
|
||||
|
||||
/*!
|
||||
* \brief Initialize all data definitions
|
||||
* \param hSimConnect
|
||||
* \return
|
||||
*/
|
||||
static HRESULT initDataDefinitions(const HANDLE hSimConnect);
|
||||
|
||||
/*!
|
||||
* \brief Initialize data definition for our own aircraft
|
||||
* \param hSimConnect
|
||||
* \return
|
||||
*/
|
||||
static HRESULT initOwnAircraft(const HANDLE hSimConnect);
|
||||
|
||||
/*!
|
||||
* \brief Initialize data definition for remote aircrafts
|
||||
* \param hSimConnect
|
||||
* \return
|
||||
*/
|
||||
static HRESULT initAircraftPosition(const HANDLE hSimConnect);
|
||||
|
||||
/*!
|
||||
* \brief Initialize data definition for remote aircraft configuration
|
||||
* \param hSimConnect
|
||||
* \return
|
||||
*/
|
||||
static HRESULT initAircraftConfiguration(const HANDLE hSimConnect);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BLACKCORE__FSX_SIMCONNECT_DATADEFINITION_H
|
||||
@@ -1,106 +0,0 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "simconnect_exception.h"
|
||||
#include <QDebug>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
namespace FSX
|
||||
{
|
||||
CSimConnectException::CSimConnectException()
|
||||
{
|
||||
}
|
||||
|
||||
void CSimConnectException::handleException(SIMCONNECT_EXCEPTION exception)
|
||||
{
|
||||
switch(exception)
|
||||
{
|
||||
case SIMCONNECT_EXCEPTION_ERROR:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_SIZE_MISMATCH:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_UNOPENED:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_VERSION_MISMATCH:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_TOO_MANY_MAPS:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE:
|
||||
{
|
||||
qDebug() << "Invalid data size!";
|
||||
break;
|
||||
}
|
||||
case SIMCONNECT_EXCEPTION_DATA_ERROR:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_INVALID_ARRAY:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED:
|
||||
{
|
||||
qDebug() << "Failed to create object!";
|
||||
break;
|
||||
}
|
||||
case SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_INVALID_ENUM:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_DEFINITION_ERROR:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_DUPLICATE_ID:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_DATUM_ID:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_ALREADY_CREATED:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OBJECT_CONTAINER:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OBJECT_AI:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OBJECT_ATC:
|
||||
break;
|
||||
case SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BLACKCORE_FSX_SIMCONNECT_EXCEPTION_H
|
||||
#define BLACKCORE_FSX_SIMCONNECT_EXCEPTION_H
|
||||
|
||||
#include "simconnect/SimConnect.h"
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
namespace FSX
|
||||
{
|
||||
//! \brief Handles SimConnect exceptions
|
||||
class CSimConnectException
|
||||
{
|
||||
public:
|
||||
CSimConnectException();
|
||||
|
||||
/*!
|
||||
* \brief Handle exception
|
||||
* \param exception
|
||||
*/
|
||||
static void handleException(SIMCONNECT_EXCEPTION exception);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BLACKCORE_FSX_SIMCONNECT_EXCEPTION_H
|
||||
@@ -1,313 +0,0 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "simulator_fsx.h"
|
||||
#include "simconnect_datadefinition.h"
|
||||
#include "simconnect_exception.h"
|
||||
#include <QTimer>
|
||||
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
using namespace BlackMisc::Geo;
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
namespace FSX
|
||||
{
|
||||
CSimulatorFSX::CSimulatorFSX(QObject *parent) :
|
||||
ISimulator(parent),
|
||||
m_isConnected(false),
|
||||
m_simRunning(false),
|
||||
m_hSimConnect(nullptr),
|
||||
m_nextObjID(1)
|
||||
{
|
||||
QTimer::singleShot(5000, this, SLOT(checkConnection()));
|
||||
}
|
||||
|
||||
bool CSimulatorFSX::isConnected() const
|
||||
{
|
||||
return m_isConnected;
|
||||
}
|
||||
|
||||
void CSimulatorFSX::addRemoteAircraft(const CCallsign &callsign, const QString &type, const CAircraftSituation &initialSituation)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
Q_UNUSED(type);
|
||||
|
||||
SIMCONNECT_DATA_INITPOSITION initialPosition;
|
||||
initialPosition.Latitude = initialSituation.latitude().value();
|
||||
initialPosition.Longitude = initialSituation.longitude().value();
|
||||
initialPosition.Altitude = initialSituation.getAltitude().value();
|
||||
initialPosition.Pitch = initialSituation.getPitch().value();
|
||||
initialPosition.Bank = initialSituation.getBank().value();
|
||||
initialPosition.Heading = initialSituation.getHeading().value();
|
||||
initialPosition.Airspeed = 0;
|
||||
initialPosition.OnGround = 0;
|
||||
|
||||
SimConnectObject simObj;
|
||||
simObj.m_callsign = callsign;
|
||||
simObj.m_requestId = m_nextObjID;
|
||||
simObj.m_objectId = 0;
|
||||
simObj.m_interpolator.addAircraftSituation(initialSituation);
|
||||
m_simConnectObjects.insert(callsign, simObj);
|
||||
++m_nextObjID;
|
||||
|
||||
hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, "Boeing 737-800 Paint1", callsign.toQString().left(12).toLatin1().constData(), initialPosition, simObj.m_requestId);
|
||||
}
|
||||
|
||||
void CSimulatorFSX::addAircraftSituation(const CCallsign &callsign, const CAircraftSituation & situation)
|
||||
{
|
||||
if (!m_simConnectObjects.contains(callsign))
|
||||
{
|
||||
addRemoteAircraft(callsign, "Boeing 737-800 Paint1", situation);
|
||||
return;
|
||||
}
|
||||
|
||||
SimConnectObject simObj = m_simConnectObjects.value(callsign);
|
||||
simObj.m_interpolator.addAircraftSituation(situation);
|
||||
m_simConnectObjects.insert(callsign, simObj);
|
||||
}
|
||||
|
||||
void CSimulatorFSX::removeRemoteAircraft(const CCallsign &callsign)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CALLBACK CSimulatorFSX::SimConnectProc(SIMCONNECT_RECV* pData, DWORD /* cbData */, void *pContext)
|
||||
{
|
||||
CSimulatorFSX *simulatorFsx = static_cast<CSimulatorFSX*>(pContext);
|
||||
|
||||
switch(pData->dwID)
|
||||
{
|
||||
case SIMCONNECT_RECV_ID_EXCEPTION:
|
||||
{
|
||||
SIMCONNECT_RECV_EXCEPTION *event = (SIMCONNECT_RECV_EXCEPTION*)pData;
|
||||
CSimConnectException::handleException((SIMCONNECT_EXCEPTION)event->dwException);
|
||||
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 EVENT_SIM_STATUS:
|
||||
if (event->dwData)
|
||||
{
|
||||
simulatorFsx->onSimRunning();
|
||||
}
|
||||
else
|
||||
{
|
||||
simulatorFsx->onSimStopped();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE:
|
||||
{
|
||||
SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE *event = static_cast<SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE*>(pData);
|
||||
if (event->uEventID == EVENT_OBJECT_ADDED)
|
||||
{
|
||||
}
|
||||
else if (event->uEventID == EVENT_OBJECT_REMOVED)
|
||||
{
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SIMCONNECT_RECV_ID_EVENT_FRAME:
|
||||
{
|
||||
simulatorFsx->onSimFrame();
|
||||
break;
|
||||
}
|
||||
case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID:
|
||||
{
|
||||
SIMCONNECT_RECV_ASSIGNED_OBJECT_ID *event = static_cast<SIMCONNECT_RECV_ASSIGNED_OBJECT_ID*>(pData);
|
||||
simulatorFsx->setSimconnectObjectID(event->dwRequestID, event->dwObjectID);
|
||||
}
|
||||
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA:
|
||||
{
|
||||
SIMCONNECT_RECV_SIMOBJECT_DATA *pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*) pData;
|
||||
switch(pObjData->dwRequestID)
|
||||
{
|
||||
case CSimConnectDataDefinition::RequestOwnAircraft:
|
||||
DataDefinitionOwnAircraft *ownAircaft;
|
||||
ownAircaft = (DataDefinitionOwnAircraft*)&pObjData->dwData;
|
||||
simulatorFsx->setOwnAircraft(*ownAircaft);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CSimulatorFSX::onSimRunning()
|
||||
{
|
||||
m_simRunning = true;
|
||||
SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::RequestOwnAircraft,
|
||||
CSimConnectDataDefinition::DataOwnAircraft,
|
||||
SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME);
|
||||
}
|
||||
|
||||
void CSimulatorFSX::onSimStopped()
|
||||
{
|
||||
m_simRunning = false;
|
||||
}
|
||||
|
||||
void CSimulatorFSX::onSimFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void CSimulatorFSX::onSimExit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSimulatorFSX::setOwnAircraft(DataDefinitionOwnAircraft aircraft)
|
||||
{
|
||||
BlackMisc::Geo::CCoordinateGeodetic position;
|
||||
position.setLatitude(CLatitude(aircraft.latitude, CAngleUnit::deg()));
|
||||
position.setLongitude(CLongitude(aircraft.longitude, CAngleUnit::deg()));
|
||||
|
||||
BlackMisc::Aviation::CAircraftSituation aircraftSituation;
|
||||
aircraftSituation.setPosition(position);
|
||||
aircraftSituation.setPitch(CAngle(aircraft.pitch, CAngleUnit::deg()));
|
||||
aircraftSituation.setBank(CAngle(aircraft.bank, CAngleUnit::deg()));
|
||||
aircraftSituation.setHeading(CHeading(aircraft.trueHeading, CHeading::True, CAngleUnit::deg()));
|
||||
aircraftSituation.setGroundspeed(CSpeed(aircraft.velocity, CSpeedUnit::kts()));
|
||||
aircraftSituation.setAltitude(CAltitude(aircraft.altitude, CAltitude::MeanSeaLevel, CLengthUnit::ft()));
|
||||
|
||||
CComSystem com1;
|
||||
com1.setFrequencyActive(CFrequency(aircraft.com1ActiveMHz, CFrequencyUnit::MHz()));
|
||||
com1.setFrequencyStandby(CFrequency(aircraft.com1StandbyMHz, CFrequencyUnit::MHz()));
|
||||
|
||||
CComSystem com2;
|
||||
com2.setFrequencyActive(CFrequency(aircraft.com2ActiveMHz, CFrequencyUnit::MHz()));
|
||||
com2.setFrequencyStandby(CFrequency(aircraft.com2StandbyMHz, CFrequencyUnit::MHz()));
|
||||
|
||||
CTransponder transponder("Transponder", aircraft.transponderCode, CTransponder::ModeC);
|
||||
|
||||
m_ownAircraft.setSituation(aircraftSituation);
|
||||
m_ownAircraft.setCom1System(com1);
|
||||
m_ownAircraft.setCom2System(com2);
|
||||
m_ownAircraft.setTransponder(transponder);
|
||||
}
|
||||
|
||||
void CSimulatorFSX::setSimconnectObjectID(DWORD requestID, DWORD objectID)
|
||||
{
|
||||
SimConnect_AIReleaseControl(m_hSimConnect, objectID, requestID);
|
||||
SimConnect_TransmitClientEvent(m_hSimConnect, objectID, EVENT_FREEZELAT, 1,
|
||||
SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
SimConnect_TransmitClientEvent(m_hSimConnect, objectID, EVENT_FREEZEALT, 1,
|
||||
SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
SimConnect_TransmitClientEvent(m_hSimConnect, objectID, EVENT_FREEZEATT, 1,
|
||||
SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
|
||||
|
||||
DataDefinitionAircraftConfiguration configuration;
|
||||
configuration.gearCenter = 100.0;
|
||||
configuration.gearLeft = 100.0;
|
||||
configuration.gearRight = 100.0;
|
||||
configuration.gearTail = 100.0;
|
||||
configuration.gearAux = 100.0;
|
||||
SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, simObj.m_objectId, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(DataDefinitionAircraftConfiguration), &configuration);
|
||||
|
||||
SimConnectObject simObject;
|
||||
foreach (simObject, m_simConnectObjects)
|
||||
{
|
||||
if (simObject.m_requestId == requestID)
|
||||
{
|
||||
simObject.m_objectId = objectID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_simConnectObjects.insert(simObject.m_callsign, simObject);
|
||||
|
||||
}
|
||||
|
||||
void CSimulatorFSX::timerEvent(QTimerEvent* /* event */)
|
||||
{
|
||||
dispatch();
|
||||
update();
|
||||
}
|
||||
|
||||
void CSimulatorFSX::checkConnection()
|
||||
{
|
||||
if (FAILED(SimConnect_Open(&m_hSimConnect, "BlackBox", nullptr, 0, 0, 0)))
|
||||
{
|
||||
QTimer::singleShot(5000, this, SLOT(checkConnection()));
|
||||
return;
|
||||
}
|
||||
|
||||
initSystemEvents();
|
||||
initDataDefinitions();
|
||||
startTimer(50);
|
||||
m_isConnected = true;
|
||||
|
||||
emit connectionChanged(true);
|
||||
}
|
||||
|
||||
void CSimulatorFSX::dispatch()
|
||||
{
|
||||
SimConnect_CallDispatch(m_hSimConnect, SimConnectProc, this);
|
||||
}
|
||||
|
||||
HRESULT CSimulatorFSX::initSystemEvents()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
// System events
|
||||
hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, EVENT_SIM_STATUS, "Sim");
|
||||
hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, EVENT_OBJECT_ADDED, "ObjectAdded");
|
||||
hr += SimConnect_SubscribeToSystemEvent(m_hSimConnect, EVENT_OBJECT_REMOVED, "ObjectRemoved");
|
||||
hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EVENT_FREEZELAT, "FREEZE_LATITUDE_LONGITUDE_SET");
|
||||
hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EVENT_FREEZEALT, "FREEZE_ALTITUDE_SET");
|
||||
hr += SimConnect_MapClientEventToSimEvent(m_hSimConnect, EVENT_FREEZEATT, "FREEZE_ATTITUDE_SET");
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT CSimulatorFSX::initDataDefinitions()
|
||||
{
|
||||
return CSimConnectDataDefinition::initDataDefinitions(m_hSimConnect);
|
||||
}
|
||||
|
||||
void CSimulatorFSX::update()
|
||||
{
|
||||
foreach (SimConnectObject simObj, m_simConnectObjects)
|
||||
{
|
||||
if (simObj.m_interpolator.hasEnoughAircraftSituations())
|
||||
{
|
||||
DataDefinitionAircraftPosition position;
|
||||
CAircraftSituation situation = simObj.m_interpolator.getCurrentSituation();
|
||||
position.latitude = situation.latitude().value();
|
||||
position.longitude = situation.longitude().value();
|
||||
position.altitude = situation.getAltitude().value(CLengthUnit::ft());
|
||||
position.pitch = situation.getPitch().value();
|
||||
position.bank = situation.getBank().value();
|
||||
position.trueHeading = situation.getHeading().value(CAngleUnit::deg());
|
||||
|
||||
DataDefinitionAircraftConfiguration configuration;
|
||||
configuration.gearCenter = 100.0;
|
||||
configuration.gearLeft = 100.0;
|
||||
configuration.gearRight = 100.0;
|
||||
configuration.gearTail = 100.0;
|
||||
configuration.gearAux = 100.0;
|
||||
|
||||
if (simObj.m_objectId != 0)
|
||||
{
|
||||
SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::DataAircraftPosition, simObj.m_objectId, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(DataDefinitionAircraftPosition), &position);
|
||||
SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDataDefinition::DataAircraftConfiguration, simObj.m_objectId, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(DataDefinitionAircraftConfiguration), &configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/* Copyright (C) 2013 VATSIM Community / contributors
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BLACKCORE_SIMULATOR_FSX_H
|
||||
#define BLACKCORE_SIMULATOR_FSX_H
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
#include "simconnect_datadefinition.h"
|
||||
|
||||
#include "blackcore/simulator.h"
|
||||
#include "blackcore/interpolator_linear.h"
|
||||
#include "blackmisc/avaircraft.h"
|
||||
#include <simconnect/SimConnect.h>
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
namespace FSX
|
||||
{
|
||||
//! \brief SimConnect Event ID's
|
||||
enum EVENT_ID {
|
||||
EVENT_SIM_STATUS,
|
||||
EVENT_OBJECT_ADDED,
|
||||
EVENT_OBJECT_REMOVED,
|
||||
EVENT_SLEW_ON,
|
||||
EVENT_FRAME,
|
||||
EVENT_FREEZELAT,
|
||||
EVENT_FREEZEALT,
|
||||
EVENT_FREEZEATT
|
||||
};
|
||||
|
||||
//! \brief FSX Simulator Implementation
|
||||
class CSimulatorFSX : public ISimulator
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
//! \brief Constructor
|
||||
CSimulatorFSX(QObject *parent = nullptr);
|
||||
|
||||
//! \copydoc ISimulator::isConnected()
|
||||
virtual bool isConnected() const override;
|
||||
|
||||
//! \copydoc ISimulator::getOwnAircraft()
|
||||
virtual BlackMisc::Aviation::CAircraft getOwnAircraft() const override { return m_ownAircraft; }
|
||||
|
||||
//! \copydoc ISimulator::addRemoteAircraft()
|
||||
virtual void addRemoteAircraft(const BlackMisc::Aviation::CCallsign &callsign, const QString &type, const BlackMisc::Aviation::CAircraftSituation &initialSituation) override;
|
||||
|
||||
//! \copydoc ISimulator::addAircraftSituation()
|
||||
virtual void addAircraftSituation(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftSituation &initialSituation) override;
|
||||
|
||||
//! \copydoc ISimulator::removeRemoteAircraft()
|
||||
virtual void removeRemoteAircraft(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
|
||||
/*!
|
||||
* \brief SimConnect Callback
|
||||
* \param pData
|
||||
* \param cbData
|
||||
* \param pContext
|
||||
*/
|
||||
static void CALLBACK SimConnectProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext);
|
||||
|
||||
//! \brief Called when sim has started
|
||||
void onSimRunning();
|
||||
|
||||
//! \brief Called when sim has stopped
|
||||
void onSimStopped();
|
||||
|
||||
//! \brief Slot called every visual frame
|
||||
void onSimFrame();
|
||||
|
||||
/*!
|
||||
* \brief Called when data about our own aircraft is received
|
||||
* \param aircraft
|
||||
*/
|
||||
void setOwnAircraft(DataDefinitionOwnAircraft aircraft);
|
||||
|
||||
/*!
|
||||
* \brief Set ID of a SimConnect object
|
||||
* \param requestID
|
||||
* \param objectID
|
||||
*/
|
||||
void setSimconnectObjectID(DWORD requestID, DWORD objectID);
|
||||
|
||||
//! \private
|
||||
void onSimExit();
|
||||
|
||||
protected:
|
||||
//! \brief Timer event
|
||||
virtual void timerEvent(QTimerEvent *event);
|
||||
|
||||
private slots:
|
||||
//! \brief Try to connect
|
||||
void checkConnection();
|
||||
|
||||
//! \brief Dispatch SimConnect messages
|
||||
void dispatch();
|
||||
|
||||
private:
|
||||
|
||||
struct SimConnectObject
|
||||
{
|
||||
BlackMisc::Aviation::CCallsign m_callsign;
|
||||
BlackCore::CInterpolatorLinear m_interpolator;
|
||||
int m_requestId;
|
||||
int m_objectId;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Initialize SimConnect system events
|
||||
* \return
|
||||
*/
|
||||
HRESULT initSystemEvents();
|
||||
|
||||
/*!
|
||||
* \brief Initialize SimConnect data definitions
|
||||
* \return
|
||||
*/
|
||||
HRESULT initDataDefinitions();
|
||||
|
||||
void update();
|
||||
|
||||
bool m_isConnected; //!< Is sim connected
|
||||
bool m_simRunning; //!< Sim running.
|
||||
HANDLE m_hSimConnect; //!< Handle to SimConnect object
|
||||
uint m_nextObjID;
|
||||
|
||||
BlackMisc::Aviation::CAircraft m_ownAircraft; //!< Object representing our own aircraft from simulator
|
||||
|
||||
QHash<BlackMisc::Aviation::CCallsign, SimConnectObject> m_simConnectObjects;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace BlackCore
|
||||
|
||||
#endif // BLACKCORE_SIMULATOR_FSX_H
|
||||
@@ -40,6 +40,7 @@ namespace BlackCore
|
||||
//! \brief Are we connected to the simulator?
|
||||
virtual bool isConnected() const = 0;
|
||||
|
||||
public slots:
|
||||
/*!
|
||||
* \brief Return user aircraft object
|
||||
* \return
|
||||
@@ -78,6 +79,24 @@ namespace BlackCore
|
||||
void ownAircraftReceived(BlackMisc::Aviation::CAircraft aircraft);
|
||||
};
|
||||
|
||||
//! \brief Factory pattern class to create instances of ISimulator
|
||||
class ISimulatorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
//! \brief Virtual destructor
|
||||
virtual ~ISimulatorFactory() {}
|
||||
|
||||
/*!
|
||||
* \brief Create a new instance
|
||||
* \param parent
|
||||
* \return
|
||||
*/
|
||||
virtual ISimulator* create(QObject *parent = nullptr) = 0;
|
||||
};
|
||||
|
||||
} // namespace BlackCore
|
||||
|
||||
Q_DECLARE_INTERFACE(BlackCore::ISimulatorFactory, "net.vatsim.PilotClient.BlackCore.SimulatorInterface")
|
||||
|
||||
#endif // BLACKCORE_SIMULATOR_H
|
||||
|
||||
Reference in New Issue
Block a user