mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-03 07:35:48 +08:00
Ref T335, improve FSX/P3D probe/aircraft handling
- probes handled in same sim object list as aircraft - init probes at beginning, probes can be disabled - better handle SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED: - CSimulatorFsxCommon::verifyAddedTerrainProbe - use "SimConnect_AICreateSimulatedObject" for probes
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "blackmisc/aviation/airportlist.h"
|
||||
#include "blackmisc/geo/elevationplane.h"
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
#include "blackmisc/country.h"
|
||||
#include "blackmisc/logmessage.h"
|
||||
#include "blackmisc/statusmessagelist.h"
|
||||
#include "blackmisc/threadutils.h"
|
||||
@@ -279,16 +280,16 @@ namespace BlackSimPlugin
|
||||
|
||||
bool CSimulatorFsxCommon::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign)
|
||||
{
|
||||
// this is the 32bit FSX version, the P3D x64 is overridden!
|
||||
|
||||
if (this->isShuttingDownOrDisconnected()) { return false; }
|
||||
if (!this->isUsingFsxTerrainProbe()) { return false; }
|
||||
if (reference.isNull()) { return false; }
|
||||
const CSimConnectObject simObject = m_simConnectObjects.getNotPendingProbe();
|
||||
if (!simObject.isConfirmedAdded()) { return false; }
|
||||
|
||||
static const CAltitude alt(50000, CLengthUnit::ft());
|
||||
CCoordinateGeodetic pos(reference);
|
||||
pos.setGeodeticHeight(alt);
|
||||
|
||||
if (m_simConnectProbes.isEmpty()) { return this->physicallyAddAITerrainProbe(pos); }
|
||||
if (m_simConnectProbes.countConfirmedAdded() < 1) { return false; } // pending probes
|
||||
const CSimConnectObject simObject = m_simConnectProbes.values().front();
|
||||
pos.setGeodeticHeight(terrainProbeAltitude());
|
||||
|
||||
SIMCONNECT_DATA_INITPOSITION position = this->coordinateToFsxPosition(pos);
|
||||
const HRESULT hr = this->logAndTraceSendId(
|
||||
@@ -299,7 +300,7 @@ namespace BlackSimPlugin
|
||||
|
||||
if (isFailure(hr)) { return false; }
|
||||
|
||||
this->requestTerrainProbeData(callsign);
|
||||
this->requestTerrainProbeData(simObject);
|
||||
emit this->requestedElevation(callsign);
|
||||
return true;
|
||||
}
|
||||
@@ -372,11 +373,6 @@ namespace BlackSimPlugin
|
||||
return this->getSimConnectObjects().getSimObjectForObjectId(objectId);
|
||||
}
|
||||
|
||||
CSimConnectObject CSimulatorFsxCommon::getProbeForObjectId(DWORD objectId) const
|
||||
{
|
||||
return this->getSimConnectProbes().getSimObjectForObjectId(objectId);
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::setSimConnected()
|
||||
{
|
||||
m_simConnected = true;
|
||||
@@ -413,26 +409,26 @@ namespace BlackSimPlugin
|
||||
HRESULT hr1 = this->logAndTraceSendId(
|
||||
SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraft,
|
||||
CSimConnectDefinitions::DataOwnAircraft, SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_VISUAL_FRAME),
|
||||
0, "Cannot request own aircraft data", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
"Cannot request own aircraft data", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
|
||||
HRESULT hr2 = this->logAndTraceSendId(
|
||||
SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestOwnAircraftTitle,
|
||||
CSimConnectDefinitions::DataOwnAircraftTitle,
|
||||
SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED),
|
||||
0, "Cannot request title", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
"Cannot request title", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
|
||||
HRESULT hr3 = this->logAndTraceSendId(
|
||||
SimConnect_RequestDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::RequestSimEnvironment,
|
||||
CSimConnectDefinitions::DataSimEnvironment,
|
||||
SIMCONNECT_OBJECT_ID_USER, SIMCONNECT_PERIOD_SECOND, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED),
|
||||
0, "Cannot request sim.env.", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
"Cannot request sim.env.", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
|
||||
|
||||
// Request the data from SB only when its changed and only ONCE so we don't have to run a 1sec event to get/set this info ;)
|
||||
HRESULT hr4 = this->logAndTraceSendId(
|
||||
SimConnect_RequestClientData(m_hSimConnect, ClientAreaSquawkBox, CSimConnectDefinitions::RequestSbData,
|
||||
CSimConnectDefinitions::DataClientAreaSb, SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED),
|
||||
0, "Cannot request client data", Q_FUNC_INFO, "SimConnect_RequestClientData");
|
||||
"Cannot request client data", Q_FUNC_INFO, "SimConnect_RequestClientData");
|
||||
|
||||
if (isFailure(hr1, hr2, hr3, hr4)) { return; }
|
||||
this->emitSimulatorCombinedStatus(); // force sending status
|
||||
@@ -499,6 +495,16 @@ namespace BlackSimPlugin
|
||||
return true;
|
||||
}
|
||||
|
||||
CSimConnectObject CSimulatorFsxCommon::getSimObjectForTrace(const TraceFsxSendId &trace) const
|
||||
{
|
||||
return m_simConnectObjects.getSimObjectForOtherSimObject(trace.simObject);
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::removeSimObjectForTrace(const TraceFsxSendId &trace)
|
||||
{
|
||||
return m_simConnectObjects.removeByOtherSimObject(trace.simObject);
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::triggerAutoTraceSendId(qint64 traceTimeMs)
|
||||
{
|
||||
if (m_traceSendId) { return false; } // no need
|
||||
@@ -609,17 +615,28 @@ namespace BlackSimPlugin
|
||||
--m_skipCockpitUpdateCycles;
|
||||
}
|
||||
|
||||
if (m_isWeatherActivated)
|
||||
// slower updates
|
||||
if (m_ownAircraftUpdate % 10 == 0)
|
||||
{
|
||||
const auto currentPosition = CCoordinateGeodetic { aircraftSituation.latitude(), aircraftSituation.longitude() };
|
||||
if (CWeatherScenario::isRealWeatherScenario(m_weatherScenarioSettings.get()) &&
|
||||
calculateGreatCircleDistance(m_lastWeatherPosition, currentPosition).value(CLengthUnit::mi()) > 20)
|
||||
if (m_isWeatherActivated)
|
||||
{
|
||||
m_lastWeatherPosition = currentPosition;
|
||||
const auto weatherGrid = CWeatherGrid { { "GLOB", currentPosition } };
|
||||
requestWeatherGrid(weatherGrid, { this, &CSimulatorFsxCommon::injectWeatherGrid });
|
||||
const auto currentPosition = CCoordinateGeodetic { aircraftSituation.latitude(), aircraftSituation.longitude() };
|
||||
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, &CSimulatorFsxCommon::injectWeatherGrid });
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_useFsxTerrainProbe && m_addedProbes < 1)
|
||||
{
|
||||
this->physicallyInitAITerrainProbes(position, 2);
|
||||
}
|
||||
}
|
||||
|
||||
m_ownAircraftUpdate++; // with 50updates/sec long enough even for 32bit
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::triggerUpdateRemoteAircraftFromSimulator(const CSimConnectObject &simObject, const DataDefinitionPosData &remoteAircraftData)
|
||||
@@ -735,17 +752,14 @@ namespace BlackSimPlugin
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::simulatorReportedProbeAdded(DWORD objectId)
|
||||
{
|
||||
if (this->isShuttingDownOrDisconnected()) { return true; } // pretend everything is fine
|
||||
const CSimConnectObject simObject = m_simConnectProbes.markObjectAsAdded(objectId);
|
||||
const bool valid(simObject.hasValidRequestAndObjectId() && simObject.isConfirmedAdded());
|
||||
return valid;
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::verifyAddedRemoteAircraft(const CSimulatedAircraft &remoteAircraftIn)
|
||||
{
|
||||
if (this->isShuttingDownOrDisconnected()) { return; }
|
||||
if (remoteAircraftIn.isTerrainProbe())
|
||||
{
|
||||
this->verifyAddedTerrainProbe(remoteAircraftIn);
|
||||
return;
|
||||
}
|
||||
|
||||
CStatusMessage msg;
|
||||
CSimulatedAircraft remoteAircraft = remoteAircraftIn;
|
||||
@@ -836,6 +850,17 @@ namespace BlackSimPlugin
|
||||
}
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::verifyAddedTerrainProbe(const CSimulatedAircraft &remoteAircraftIn)
|
||||
{
|
||||
CSimConnectObject &simObject = m_simConnectObjects[remoteAircraftIn.getCallsign()];
|
||||
simObject.setConfirmedAdded(true);
|
||||
// trigger new adding from pending if any
|
||||
if (!m_addPendingAircraft.isEmpty())
|
||||
{
|
||||
this->addPendingAircraftAfterAdded();
|
||||
}
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::addPendingAircraftByTimer()
|
||||
{
|
||||
this->addPendingAircraft(AddByTimer);
|
||||
@@ -849,13 +874,13 @@ namespace BlackSimPlugin
|
||||
void CSimulatorFsxCommon::addPendingAircraft(AircraftAddMode mode)
|
||||
{
|
||||
if (m_addPendingAircraft.isEmpty()) { return; }
|
||||
const CCallsignSet aircraftCallsignsInRange(getAircraftInRangeCallsigns());
|
||||
const CCallsignSet aircraftCallsignsInRange(this->getAircraftInRangeCallsigns());
|
||||
CSimulatedAircraftList toBeAddedAircraft;
|
||||
CCallsignSet toBeRemovedCallsigns;
|
||||
for (const CSimulatedAircraft &aircraft : as_const(m_addPendingAircraft))
|
||||
{
|
||||
Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
|
||||
if (aircraftCallsignsInRange.contains(aircraft.getCallsign()))
|
||||
if (aircraft.isTerrainProbe() || aircraftCallsignsInRange.contains(aircraft.getCallsign()))
|
||||
{
|
||||
toBeAddedAircraft.push_back(aircraft);
|
||||
}
|
||||
@@ -956,11 +981,6 @@ namespace BlackSimPlugin
|
||||
return m_simConnectObjects.setSimConnectObjectIdForRequestId(requestId, objectId);
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::setSimConnectProbeId(DWORD requestId, DWORD objectId)
|
||||
{
|
||||
return m_simConnectProbes.setSimConnectObjectIdForRequestId(requestId, objectId);
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::setCurrentLights(const CCallsign &callsign, const CAircraftLights &lights)
|
||||
{
|
||||
if (!m_simConnectObjects.contains(callsign)) { return false; }
|
||||
@@ -1092,6 +1112,7 @@ namespace BlackSimPlugin
|
||||
bool CSimulatorFsxCommon::physicallyAddRemoteAircraftImpl(const CSimulatedAircraft &newRemoteAircraft, CSimulatorFsxCommon::AircraftAddMode addMode)
|
||||
{
|
||||
const CCallsign callsign(newRemoteAircraft.getCallsign());
|
||||
const bool probe = newRemoteAircraft.isTerrainProbe();
|
||||
|
||||
// entry checks
|
||||
Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread");
|
||||
@@ -1170,8 +1191,8 @@ namespace BlackSimPlugin
|
||||
|
||||
this->removeFromAddPendingAndAddAgainAircraft(callsign);
|
||||
|
||||
// create AI
|
||||
if (!this->isAircraftInRange(callsign))
|
||||
// create AI after crosscheking it
|
||||
if (!probe && !this->isAircraftInRange(callsign))
|
||||
{
|
||||
CLogMessage(this).info("Skipping adding of '%1' since it is no longer in range") << callsign.asString();
|
||||
return false;
|
||||
@@ -1182,13 +1203,19 @@ namespace BlackSimPlugin
|
||||
const bool sendGround = setup.isSendingGndFlagToSimulator();
|
||||
|
||||
// FSX/P3D adding
|
||||
Q_ASSERT_X(!probe || m_useFsxTerrainProbe, Q_FUNC_INFO, "Adding probe, but FSX probe mode is off");
|
||||
|
||||
bool adding = false; // will be added flag
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimObjAircraft(); // add
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = probe ?
|
||||
this->obtainRequestIdForSimObjTerrainProbe() :
|
||||
this->obtainRequestIdForSimObjAircraft();
|
||||
const SIMCONNECT_DATA_INITPOSITION initialPosition = CSimulatorFsxCommon::aircraftSituationToFsxPosition(newRemoteAircraft.getSituation(), sendGround);
|
||||
const QString modelString(newRemoteAircraft.getModelString());
|
||||
if (this->showDebugLogMessage()) { this->debugLogMessage(Q_FUNC_INFO, QString("CS: '%1' model: '%2' request: %3, init pos: %4").arg(callsign.toQString(), modelString).arg(requestId).arg(fsxPositionToString(initialPosition))); }
|
||||
|
||||
const HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(callsign.toQString().left(12)), initialPosition, requestId);
|
||||
const HRESULT hr = !probe ?
|
||||
SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(callsign.toQString().left(12)), initialPosition, requestId) :
|
||||
SimConnect_AICreateSimulatedObject(m_hSimConnect, qPrintable(modelString), initialPosition, requestId);
|
||||
if (isFailure(hr))
|
||||
{
|
||||
const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create AI traffic: '%1' '%2'") << callsign.toQString() << modelString;
|
||||
@@ -1198,48 +1225,51 @@ namespace BlackSimPlugin
|
||||
else
|
||||
{
|
||||
// we will request a new aircraft by request ID, later we will receive its object id
|
||||
// so far this object id is -1
|
||||
// so far this object id is 0 (DWORD)
|
||||
static const QString mode("mode: %1");
|
||||
const CSimConnectObject simObject = this->insertNewSimConnectObject(newRemoteAircraft, requestId);
|
||||
if (this->isTracingSendId()) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);}
|
||||
this->traceSendId(simObject, Q_FUNC_INFO, mode.arg(CSimulatorFsxCommon::modeToString(addMode)), true);
|
||||
adding = true;
|
||||
}
|
||||
return adding;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::physicallyAddAITerrainProbe(const ICoordinateGeodetic &coordinate)
|
||||
bool CSimulatorFsxCommon::physicallyAddAITerrainProbe(const ICoordinateGeodetic &coordinate, int number)
|
||||
{
|
||||
if (coordinate.isNull()) { return false; }
|
||||
if (!this->isUsingFsxTerrainProbe()) { return false; }
|
||||
Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "thread");
|
||||
|
||||
// static const QString modelString = this->getDefaultModel().getModelString();
|
||||
static const QString modelString("OrcaWhale");
|
||||
static const QString pseudoCallsign("swift pr: %1"); // max 12 chars
|
||||
const int index = m_simConnectProbes.size() + 1;
|
||||
const CCallsign cs(pseudoCallsign.arg(index));
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimObjTerrainProbe(); // add
|
||||
const SIMCONNECT_DATA_INITPOSITION initialPosition = CSimulatorFsxCommon::coordinateToFsxPosition(coordinate);
|
||||
const HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, qPrintable(modelString), qPrintable(cs.asString().right(12)), initialPosition, requestId);
|
||||
// const HRESULT hr = SimConnect_AICreateSimulatedObject(m_hSimConnect, qPrintable(modelString), initialPosition, requestId);
|
||||
if (this->isTracingSendId()) { this->traceSendId(0, Q_FUNC_INFO, QString("Adding probe, req.id: %1").arg(requestId));}
|
||||
// static const QString modelString("OrcaWhale");
|
||||
// static const QString modelString("Water Drop");
|
||||
// static const QString modelString("A321ACA");
|
||||
static const QString modelString("AI_Tracker_Object_0");
|
||||
static const QString pseudoCallsign("PROBE%1"); // max 12 chars
|
||||
static const CCountry ctry("SW", "SWIFT");
|
||||
static const CAirlineIcaoCode swiftAirline("SWI", "swift probe", ctry, "SWIFT", false, false);
|
||||
static const CLivery swiftLivery(CLivery::getStandardCode(swiftAirline), swiftAirline, "swift probe");
|
||||
|
||||
bool ok = false;
|
||||
if (isOk(hr))
|
||||
const CCallsign cs(pseudoCallsign.arg(number));
|
||||
const CAircraftModel model(modelString, CAircraftModel::TypeTerrainProbe, QStringLiteral("swift terrain probe"), CAircraftIcaoCode::unassignedIcao(), swiftLivery);
|
||||
CAircraftSituation situation(cs, coordinate);
|
||||
situation.setAltitude(terrainProbeAltitude());
|
||||
situation.setZeroPBH();
|
||||
const CSimulatedAircraft pseudoAircraft(cs, model, CUser("123456", "swift", cs), situation);
|
||||
return this->physicallyAddRemoteAircraftImpl(pseudoAircraft, ExternalCall);
|
||||
}
|
||||
|
||||
int CSimulatorFsxCommon::physicallyInitAITerrainProbes(const ICoordinateGeodetic &coordinate, int number)
|
||||
{
|
||||
if (number < 1) { return 0; }
|
||||
int c = 0;
|
||||
for (int n = 1; n <= number; ++n)
|
||||
{
|
||||
ok = true;
|
||||
const CAircraftModel model(modelString, CAircraftModel::TypeTerrainProbe, QStringLiteral("swift terrain probe"), CAircraftIcaoCode::unassignedIcao());
|
||||
const CAircraftSituation situation(cs, coordinate);
|
||||
const CSimulatedAircraft pseudoAircraft(cs, model, CUser("123456", "swift", cs), situation);
|
||||
CSimConnectObject simObject(CSimConnectObject::TerrainProbe);
|
||||
simObject.setRequestId(requestId);
|
||||
simObject.setAircraft(pseudoAircraft);
|
||||
m_simConnectProbes.insert(cs, simObject);
|
||||
if (this->physicallyAddAITerrainProbe(coordinate, n)) { c++; }
|
||||
}
|
||||
else
|
||||
{
|
||||
const CStatusMessage msg = CStatusMessage(this).error("SimConnect, can not create terrain AI: '%1'") << requestId;
|
||||
CLogMessage::preformatted(msg);
|
||||
}
|
||||
return ok;
|
||||
|
||||
CLogMessage(this).info("Adding %1 FSX terrain probes") << number;
|
||||
m_addedProbes = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::physicallyRemoveRemoteAircraft(const CCallsign &callsign)
|
||||
@@ -1255,20 +1285,23 @@ namespace BlackSimPlugin
|
||||
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.isTerrainProbe())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for pending objects
|
||||
m_addPendingAircraft.removeByCallsign(callsign); // just in case still in list of pending aircraft
|
||||
const bool pendingAdded = simObject.isPendingAdded(); // already added in simulator, but not yet confirmed
|
||||
const bool stillWaitingForLights = !simObject.hasCurrentLightsInSimulator();
|
||||
if (pendingAdded || stillWaitingForLights)
|
||||
if (!simObject.isRemovedWhileAdding() && (pendingAdded || stillWaitingForLights))
|
||||
{
|
||||
// problem: we try to delete an aircraft just requested to be added
|
||||
// best solution so far, call remove again with a delay
|
||||
CLogMessage(this).warning("Object: '%1' requested to be removed, but pedning added (%2) / or pending lights(%3). CS '%4' will be removed again.")
|
||||
CLogMessage(this).warning("Object: '%1' requested to be removed, but pending added (%2) / or pending lights(%3). CS '%4' will be removed again.")
|
||||
<< simObject.toQString() << boolToYesNo(pendingAdded)
|
||||
<< boolToYesNo(stillWaitingForLights) << callsign.asString();
|
||||
simObject.fakeCurrentLightsInSimulator(); // next time looks like we have lights
|
||||
simObject.setRemovedWhileAdding(true);
|
||||
simObject.setRemovedWhileAdding(true); // next time kill
|
||||
QPointer<CSimulatorFsxCommon> myself(this);
|
||||
QTimer::singleShot(2000, this, [ = ]
|
||||
{
|
||||
@@ -1290,7 +1323,7 @@ namespace BlackSimPlugin
|
||||
const HRESULT result = SimConnect_AIRemoveObject(m_hSimConnect, static_cast<SIMCONNECT_OBJECT_ID>(simObject.getObjectId()), requestId);
|
||||
if (isOk(result))
|
||||
{
|
||||
if (this->isTracingSendId()) { this->traceSendId(simObject.getObjectId(), Q_FUNC_INFO);}
|
||||
if (this->isTracingSendId()) { this->traceSendId(simObject, Q_FUNC_INFO);}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1673,13 +1706,15 @@ namespace BlackSimPlugin
|
||||
|
||||
SIMCONNECT_DATA_INITPOSITION position = CSimulatorFsxCommon::coordinateToFsxPosition(situation);
|
||||
position.Heading = situation.getHeading().value(CAngleUnit::deg());
|
||||
position.Airspeed = static_cast<DWORD>(situation.getGroundSpeed().valueInteger(CSpeedUnit::kts()));
|
||||
const double gsKts = situation.getGroundSpeed().value(CSpeedUnit::kts());
|
||||
position.Airspeed = static_cast<DWORD>(qRound(gsKts));
|
||||
|
||||
// sanity check
|
||||
if (CBuildConfig::isLocalDeveloperDebugBuild() && situation.getGroundSpeed().isNegativeWithEpsilonConsidered())
|
||||
if (gsKts < 0.0)
|
||||
{
|
||||
BLACK_VERIFY_X(false, Q_FUNC_INFO, "Negative speed");
|
||||
position.Airspeed = 0;
|
||||
// we get negative GS for pushback and helicopters
|
||||
// do do we handle them her with DWORD
|
||||
position.Airspeed = 0U;
|
||||
}
|
||||
|
||||
// MSFS has inverted pitch and bank angles
|
||||
@@ -1783,13 +1818,9 @@ namespace BlackSimPlugin
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::requestTerrainProbeData(const CCallsign &callsign)
|
||||
bool CSimulatorFsxCommon::requestTerrainProbeData(const CSimConnectObject &simObject)
|
||||
{
|
||||
if (m_simConnectProbes.countConfirmedAdded() < 1) { return false; }
|
||||
if (!m_simConnectObjects.contains(callsign)) { return false; } // removed in meantime
|
||||
|
||||
static const QString w("Cannot request terrain probe data for id '%1'");
|
||||
const CSimConnectObject simObject = m_simConnectProbes.values().front();
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectPositionData);
|
||||
const DWORD objectId = simObject.getObjectId();
|
||||
const HRESULT result =
|
||||
@@ -1813,7 +1844,7 @@ namespace BlackSimPlugin
|
||||
SimConnect_RequestDataOnSimObject(
|
||||
m_hSimConnect, requestId, CSimConnectDefinitions::DataRemoteAircraftLights,
|
||||
simObject.getObjectId(), SIMCONNECT_PERIOD_SECOND),
|
||||
true, simObject, "Cannot request lights data", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
simObject, "Cannot request lights data", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
return isOk(result);
|
||||
}
|
||||
|
||||
@@ -1827,8 +1858,8 @@ namespace BlackSimPlugin
|
||||
const HRESULT result = this->logAndTraceSendId(
|
||||
SimConnect_RequestDataOnSimObject(
|
||||
m_hSimConnect, requestId,
|
||||
CSimConnectDefinitions::DataRemoteAircraftModelData, simObject.getObjectId(),
|
||||
SIMCONNECT_PERIOD_ONCE),
|
||||
CSimConnectDefinitions::DataRemoteAircraftModelData,
|
||||
simObject.getObjectId(), SIMCONNECT_PERIOD_ONCE),
|
||||
simObject, "Cannot request model info", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
return isOk(result);
|
||||
}
|
||||
@@ -1851,8 +1882,8 @@ namespace BlackSimPlugin
|
||||
const HRESULT hr2 = this->logAndTraceSendId(
|
||||
SimConnect_RequestDataOnSimObject(
|
||||
m_hSimConnect, requestId,
|
||||
CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(),
|
||||
SIMCONNECT_PERIOD_NEVER),
|
||||
CSimConnectDefinitions::DataRemoteAircraftLights,
|
||||
simObject.getObjectId(), SIMCONNECT_PERIOD_NEVER),
|
||||
simObject, "Stopping lights request", Q_FUNC_INFO, "SimConnect_RequestDataOnSimObject");
|
||||
return isOk(hr1, hr2);
|
||||
}
|
||||
@@ -1882,9 +1913,11 @@ namespace BlackSimPlugin
|
||||
m_simSimulating = false;
|
||||
m_syncDeferredCounter = 0;
|
||||
m_skipCockpitUpdateCycles = 0;
|
||||
m_ownAircraftUpdate = 0;
|
||||
m_requestIdSimObjAircraft = static_cast<SIMCONNECT_DATA_REQUEST_ID>(RequestSimObjAircraftStart);
|
||||
m_dispatchErrors = 0;
|
||||
m_receiveExceptionCount = 0;
|
||||
m_addedProbes = 0;
|
||||
m_sendIdTraces.clear();
|
||||
}
|
||||
|
||||
@@ -1908,39 +1941,27 @@ namespace BlackSimPlugin
|
||||
|
||||
CCallsignSet CSimulatorFsxCommon::getCallsignsMissingInProvider() const
|
||||
{
|
||||
const CCallsignSet simObjectCallsigns(m_simConnectObjects.keys());
|
||||
const CCallsignSet simObjectCallsigns(m_simConnectObjects.getAllCallsigns(true));
|
||||
const CCallsignSet providerCallsigns(this->getAircraftInRangeCallsigns());
|
||||
return simObjectCallsigns.difference(providerCallsigns);
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::traceSendId(DWORD simObjectId, const QString &functionName, const QString &details)
|
||||
void CSimulatorFsxCommon::traceSendId(const CSimConnectObject &simObject, const QString &functionName, const QString &details, bool forceTrace)
|
||||
{
|
||||
if (!this->isTracingSendId()) { return; }
|
||||
if (!forceTrace && !this->isTracingSendId()) { return; }
|
||||
if (MaxSendIdTraces < 1) { return; }
|
||||
DWORD dwLastId = 0;
|
||||
const HRESULT hr = SimConnect_GetLastSentPacketID(m_hSimConnect, &dwLastId);
|
||||
if (isFailure(hr)) { return; }
|
||||
if (m_sendIdTraces.size() > MaxSendIdTraces) { m_sendIdTraces.removeLast(); }
|
||||
const TraceFsxSendId trace(dwLastId, simObjectId, details.isEmpty() ? functionName : details % QStringLiteral(", ") % functionName);
|
||||
const TraceFsxSendId trace(dwLastId, simObject, details.isEmpty() ? functionName : details % QStringLiteral(", ") % functionName);
|
||||
m_sendIdTraces.push_front(trace);
|
||||
}
|
||||
|
||||
HRESULT CSimulatorFsxCommon::logAndTraceSendId(HRESULT hr, DWORD simObjectId, const QString &warningMsg, const QString &functionName, const QString &functionDetails)
|
||||
HRESULT CSimulatorFsxCommon::logAndTraceSendId(HRESULT hr, const QString &warningMsg, const QString &functionName, const QString &functionDetails)
|
||||
{
|
||||
return this->logAndTraceSendId(hr, this->isTracingSendId(), simObjectId, warningMsg, functionName, functionDetails);
|
||||
}
|
||||
|
||||
HRESULT CSimulatorFsxCommon::logAndTraceSendId(HRESULT hr, bool traceSendId, DWORD simObjectId, const QString &warningMsg, const QString &functionName, const QString &functionDetails)
|
||||
{
|
||||
if (traceSendId) { this->traceSendId(simObjectId, functionName, functionDetails); }
|
||||
if (isOk(hr)) { return hr; }
|
||||
if (!warningMsg.isEmpty())
|
||||
{
|
||||
CSimConnectObject simObject = (simObjectId == 0) ? CSimConnectObject() : m_simConnectObjects.getSimObjectForObjectId(simObjectId);
|
||||
CLogMessage(this).warning(warningMsg % QStringLiteral(" ") % simObject.toQString());
|
||||
}
|
||||
this->triggerAutoTraceSendId();
|
||||
return hr;
|
||||
const CSimConnectObject empty;
|
||||
return this->logAndTraceSendId(hr, empty, warningMsg, functionName, functionDetails);
|
||||
}
|
||||
|
||||
HRESULT CSimulatorFsxCommon::logAndTraceSendId(HRESULT hr, const CSimConnectObject &simObject, const QString &warningMsg, const QString &functionName, const QString &functionDetails)
|
||||
@@ -1950,7 +1971,7 @@ namespace BlackSimPlugin
|
||||
|
||||
HRESULT CSimulatorFsxCommon::logAndTraceSendId(HRESULT hr, bool traceSendId, const CSimConnectObject &simObject, const QString &warningMsg, const QString &functionName, const QString &functionDetails)
|
||||
{
|
||||
if (traceSendId) { this->traceSendId(simObject.getObjectId(), functionName, functionDetails); }
|
||||
if (traceSendId) { this->traceSendId(simObject, functionName, functionDetails); }
|
||||
if (isOk(hr)) { return hr; }
|
||||
if (!warningMsg.isEmpty())
|
||||
{
|
||||
@@ -1960,26 +1981,42 @@ namespace BlackSimPlugin
|
||||
return hr;
|
||||
}
|
||||
|
||||
QString CSimulatorFsxCommon::getSendIdTraceDetails(DWORD sendId) const
|
||||
TraceFsxSendId CSimulatorFsxCommon::getSendIdTrace(DWORD sendId) const
|
||||
{
|
||||
for (const TraceFsxSendId &trace : m_sendIdTraces)
|
||||
{
|
||||
if (trace.sendId == sendId)
|
||||
{
|
||||
static const QString d("Send id: %1 obj.id.: %2 SimObj: %3 | '%4'");
|
||||
const CSimConnectObject simObj = m_simConnectObjects.getSimObjectForObjectId(trace.simObjectId);
|
||||
return d.arg(sendId).arg(trace.simObjectId).arg(simObj.toQString(), trace.comment);
|
||||
}
|
||||
if (trace.sendId == sendId) { return trace; }
|
||||
}
|
||||
return TraceFsxSendId::invalid();
|
||||
}
|
||||
|
||||
QString CSimulatorFsxCommon::getSendIdTraceDetails(DWORD sendId) const
|
||||
{
|
||||
const TraceFsxSendId trace = this->getSendIdTrace(sendId);
|
||||
if (trace.sendId == sendId)
|
||||
{
|
||||
return this->getSendIdTraceDetails(trace);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QString CSimulatorFsxCommon::getSendIdTraceDetails(const TraceFsxSendId &trace) const
|
||||
{
|
||||
static const QString d("Send id: %1 obj.id.: %2 SimObj: %3 | '%4'");
|
||||
if (trace.isInvalid()) { return QString(); }
|
||||
|
||||
// update with latest sim object
|
||||
const CSimConnectObject simObject = this->getSimObjectForTrace(trace);
|
||||
return d.arg(trace.sendId).arg(simObject.getObjectId()).arg(simObject.toQString(), trace.comment);
|
||||
}
|
||||
|
||||
int CSimulatorFsxCommon::removeAllProbes()
|
||||
{
|
||||
if (!m_hSimConnect) { return 0; } // already disconnected
|
||||
if (m_simConnectProbes.isEmpty()) { return 0; }
|
||||
const QList<CSimConnectObject> probes = m_simConnectObjects.getProbes();
|
||||
|
||||
int c = 0;
|
||||
for (const CSimConnectObject &probeSimObject : m_simConnectProbes.values())
|
||||
for (const CSimConnectObject &probeSimObject : probes)
|
||||
{
|
||||
if (!probeSimObject.isConfirmedAdded()) { continue; }
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = probeSimObject.getRequestId(CSimConnectDefinitions::SimObjectRemove);
|
||||
@@ -1993,7 +2030,7 @@ namespace BlackSimPlugin
|
||||
CLogMessage(this).warning("Removing probe '%1' from simulator failed") << probeSimObject.getObjectId();
|
||||
}
|
||||
}
|
||||
m_simConnectProbes.clear();
|
||||
m_simConnectObjects.removeAllProbes();
|
||||
m_pendingProbeRequests.clear();
|
||||
return c;
|
||||
}
|
||||
@@ -2025,6 +2062,12 @@ namespace BlackSimPlugin
|
||||
return simObject;
|
||||
}
|
||||
|
||||
const CAltitude &CSimulatorFsxCommon::terrainProbeAltitude()
|
||||
{
|
||||
static const CAltitude alt(10000, CLengthUnit::ft());
|
||||
return alt;
|
||||
}
|
||||
|
||||
QString CSimulatorFsxCommon::fsxCharToQString(const char *fsxChar, int size)
|
||||
{
|
||||
return QString::fromLatin1(fsxChar, size);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "blackmisc/simulation/aircraftmodel.h"
|
||||
#include "blackmisc/simulation/simulatedaircraft.h"
|
||||
#include "blackmisc/aviation/airportlist.h"
|
||||
#include "blackmisc/aviation/altitude.h"
|
||||
#include "blackmisc/statusmessage.h"
|
||||
#include "blackmisc/network/client.h"
|
||||
#include "blackmisc/pixmap.h"
|
||||
@@ -87,14 +88,29 @@ namespace BlackSimPlugin
|
||||
struct TraceFsxSendId
|
||||
{
|
||||
//! Ctor
|
||||
TraceFsxSendId(DWORD sendId, DWORD simObjectId, const QString &comment) :
|
||||
sendId(sendId), simObjectId(simObjectId), comment(comment)
|
||||
TraceFsxSendId(DWORD sendId, const CSimConnectObject &simObject, const QString &comment) :
|
||||
sendId(sendId), simObject(simObject), comment(comment)
|
||||
{ }
|
||||
|
||||
// DWORD is unsigned
|
||||
DWORD sendId = 0; //!< the send id
|
||||
DWORD simObjectId = 0; //!< corresponding CSimConnectObject
|
||||
QString comment; //!< where sent
|
||||
DWORD sendId = 0; //!< the send id
|
||||
CSimConnectObject simObject; //!< CSimConnectObject at the time of the trace
|
||||
QString comment; //!< where sent
|
||||
|
||||
//! For probe
|
||||
bool isForProbe() const { return simObject.getType() == CSimConnectObject::TerrainProbe; }
|
||||
|
||||
//! For aircraft
|
||||
bool isForAircraft() const { return simObject.getType() == CSimConnectObject::Aircraft; }
|
||||
|
||||
//! Invalid trace?
|
||||
bool isInvalid() const { return sendId == 0 && simObject.isInvalid() == 0 && comment.isEmpty(); }
|
||||
|
||||
//! Valid trace?
|
||||
bool isValid() const { return !this->isInvalid(); }
|
||||
|
||||
//! Invalid object
|
||||
static const TraceFsxSendId &invalid() { static const TraceFsxSendId i(0, CSimConnectObject(), ""); return i; }
|
||||
};
|
||||
|
||||
//! FSX Simulator Implementation
|
||||
@@ -136,6 +152,8 @@ namespace BlackSimPlugin
|
||||
//! @}
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::ISimulationEnvironmentProvider::requestElevation
|
||||
//! \remark x86 FSX version, x64 version is overridden
|
||||
//! \sa CSimulatorFsxCommon::is
|
||||
virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
|
||||
//! Tracing?
|
||||
@@ -144,12 +162,25 @@ namespace BlackSimPlugin
|
||||
//! Set tracing on/off
|
||||
void setTractingSendId(bool trace);
|
||||
|
||||
//! FSX Terrain probe
|
||||
//! \remark must be off at P3D v4.2 drivers or later
|
||||
bool isUsingFsxTerrainProbe() const { return m_useFsxTerrainProbe; }
|
||||
|
||||
//! FSX terrain probe
|
||||
void setUsingFsxTerrainProbe(bool use) { m_useFsxTerrainProbe = use; }
|
||||
|
||||
//! Request for sim data (request in range of sim data)?
|
||||
static bool isRequestForSimObjAircraft(DWORD requestId) { return requestId >= RequestSimObjAircraftStart && requestId <= RequestSimObjAircraftRangeEnd; }
|
||||
|
||||
//! Request for probe (elevation)?
|
||||
static bool isRequestForSimObjTerrainProbe(DWORD requestId) { return requestId >= RequestSimObjTerrainProbeStart && requestId <= RequestSimObjTerrainProbeRangeEnd; }
|
||||
|
||||
//! Request for any CSimConnectObject?
|
||||
static bool isRequestForSimConnectObject(DWORD requestId)
|
||||
{
|
||||
return isRequestForSimObjAircraft(requestId) || isRequestForSimObjTerrainProbe(requestId);
|
||||
}
|
||||
|
||||
//! Sub request type
|
||||
static CSimConnectDefinitions::SimObjectRequest requestToSimObjectRequest(DWORD requestId);
|
||||
|
||||
@@ -210,6 +241,12 @@ namespace BlackSimPlugin
|
||||
//! Valid CSimConnectObject which is NOT pendig removed
|
||||
bool isValidSimObjectNotPendingRemoved(const CSimConnectObject &simObject) const;
|
||||
|
||||
//! CSimConnectObject for trace
|
||||
CSimConnectObject getSimObjectForTrace(const TraceFsxSendId &trace) const;
|
||||
|
||||
//! Remove the CSimConnectObject linked in the trace
|
||||
bool removeSimObjectForTrace(const TraceFsxSendId &trace);
|
||||
|
||||
//! Register help
|
||||
static void registerHelp();
|
||||
|
||||
@@ -217,7 +254,10 @@ namespace BlackSimPlugin
|
||||
HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object
|
||||
DispatchProc m_dispatchProc = &CSimulatorFsxCommon::SimConnectProc; //!< called function for dispatch, can be overriden by specialized P3D function
|
||||
CSimConnectObjects m_simConnectObjects; //!< AI objects and their object and request ids
|
||||
CSimConnectObjects m_simConnectProbes; //!< AI terrain probes and their object / request ids
|
||||
|
||||
// probes
|
||||
bool m_useFsxTerrainProbe = true; //!< Use FSX Terrain probe?
|
||||
int m_addedProbes = 0; //!< added probes
|
||||
QMap<DWORD, BlackMisc::Aviation::CCallsign> m_pendingProbeRequests; //!< pending elevation requests
|
||||
|
||||
private:
|
||||
@@ -231,7 +271,7 @@ namespace BlackSimPlugin
|
||||
};
|
||||
|
||||
//! Mode as string
|
||||
const QString &modeToString(AircraftAddMode mode);
|
||||
static const QString &modeToString(AircraftAddMode mode);
|
||||
|
||||
//! Dispatch SimConnect messages
|
||||
//! \remark very frequently called
|
||||
@@ -243,7 +283,11 @@ namespace BlackSimPlugin
|
||||
|
||||
//! Add AI object for terrain probe
|
||||
//! \remark experimental
|
||||
bool physicallyAddAITerrainProbe(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
|
||||
bool physicallyAddAITerrainProbe(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, int number);
|
||||
|
||||
//! Add number probes (inits the probe objects)
|
||||
//! \remark experimental
|
||||
int physicallyInitAITerrainProbes(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, int number);
|
||||
|
||||
//! Remove aircraft no longer in provider
|
||||
//! \remark kind of cleanup function, in an ideal this should never need to cleanup something
|
||||
@@ -254,6 +298,9 @@ namespace BlackSimPlugin
|
||||
//! \remark requests further data on remote aircraft (lights, ..) when correctly added
|
||||
void verifyAddedRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraftIn);
|
||||
|
||||
//! Verify the probe
|
||||
void verifyAddedTerrainProbe(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraftIn);
|
||||
|
||||
//! Add next aircraft based on timer
|
||||
void addPendingAircraftByTimer();
|
||||
|
||||
@@ -342,18 +389,12 @@ namespace BlackSimPlugin
|
||||
//! An AI aircraft was added in the simulator
|
||||
bool simulatorReportedObjectAdded(DWORD objectId);
|
||||
|
||||
//! An AI probe was added in the simulator
|
||||
bool simulatorReportedProbeAdded(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);
|
||||
|
||||
//! Set ID of a SimConnect object, so far we only have an request id in the object
|
||||
bool setSimConnectProbeId(DWORD requestId, DWORD objectId);
|
||||
|
||||
//! Remember current lights
|
||||
bool setCurrentLights(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftLights &lights);
|
||||
|
||||
@@ -369,12 +410,6 @@ namespace BlackSimPlugin
|
||||
//! The SimConnect object for idxs
|
||||
CSimConnectObject getSimObjectForObjectId(DWORD objectId) const;
|
||||
|
||||
//! The simconnect related probes
|
||||
const CSimConnectObjects &getSimConnectProbes() const { return m_simConnectProbes; }
|
||||
|
||||
//! Get probe for id
|
||||
CSimConnectObject getProbeForObjectId(DWORD objectId) const;
|
||||
|
||||
//! Format conversion
|
||||
//! \note must be valid situation
|
||||
SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation, bool sendGnd = true);
|
||||
@@ -389,7 +424,7 @@ namespace BlackSimPlugin
|
||||
bool requestPositionDataForSimObject(const CSimConnectObject &simObject, SIMCONNECT_PERIOD period = SIMCONNECT_PERIOD_SECOND);
|
||||
|
||||
//! Request data for the terrain probe
|
||||
bool requestTerrainProbeData(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
bool requestTerrainProbeData(const CSimConnectObject &simObject);
|
||||
|
||||
//! Request lights for a CSimConnectObject
|
||||
bool requestLightsForSimObject(const CSimConnectObject &simObject);
|
||||
@@ -410,13 +445,10 @@ namespace BlackSimPlugin
|
||||
void setTraceSendId(bool traceSendId) { m_traceSendId = traceSendId; }
|
||||
|
||||
//! Trace the send id
|
||||
void traceSendId(DWORD simObjectId, const QString &functionName, const QString &details = {});
|
||||
void traceSendId(const CSimConnectObject &simObject, const QString &functionName, const QString &details = {}, bool forceTrace = false);
|
||||
|
||||
//! Trace if required, log errors
|
||||
HRESULT logAndTraceSendId(HRESULT hr, DWORD simObjectId, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
|
||||
|
||||
//! Trace if required, log errors
|
||||
HRESULT logAndTraceSendId(HRESULT hr, bool traceSendId, DWORD simObjectId, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
|
||||
HRESULT logAndTraceSendId(HRESULT hr, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
|
||||
|
||||
//! Trace if required, log errors
|
||||
HRESULT logAndTraceSendId(HRESULT hr, const CSimConnectObject &simObject, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
|
||||
@@ -424,6 +456,12 @@ namespace BlackSimPlugin
|
||||
//! Trace if required, log errors
|
||||
HRESULT logAndTraceSendId(HRESULT hr, bool traceSendId, const CSimConnectObject &simObject, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
|
||||
|
||||
//! Send id trace or given send id
|
||||
TraceFsxSendId getSendIdTrace(DWORD sendId) const;
|
||||
|
||||
//! Get the trace details, otherwise empty string
|
||||
QString getSendIdTraceDetails(const TraceFsxSendId &trace) const;
|
||||
|
||||
//! Get the trace details, otherwise empty string
|
||||
QString getSendIdTraceDetails(DWORD sendId) const;
|
||||
|
||||
@@ -433,6 +471,9 @@ namespace BlackSimPlugin
|
||||
//! Insert a new SimConnect object
|
||||
CSimConnectObject insertNewSimConnectObject(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, DWORD requestId);
|
||||
|
||||
//! Used for terrain probes
|
||||
static const BlackMisc::Aviation::CAltitude &terrainProbeAltitude();
|
||||
|
||||
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
|
||||
@@ -465,6 +506,7 @@ namespace BlackSimPlugin
|
||||
qint64 m_simulatingChangedTs = -1; //!< timestamp, when simulating changed (used to avoid jitter)
|
||||
int m_syncDeferredCounter = 0; //!< Set when synchronized, used to wait some time
|
||||
int m_skipCockpitUpdateCycles = 0; //!< skip some update cycles to allow changes in simulator cockpit to be set
|
||||
int m_ownAircraftUpdate = 0; //!< own aircraft update
|
||||
|
||||
// tracing dispatch performance
|
||||
int m_dispatchErrors = 0; //!< number of dispatched failed, \sa dispatch
|
||||
|
||||
@@ -64,23 +64,63 @@ namespace BlackSimPlugin
|
||||
SIMCONNECT_RECV_EXCEPTION *exception = static_cast<SIMCONNECT_RECV_EXCEPTION *>(pData);
|
||||
const DWORD exceptionId = exception->dwException;
|
||||
const DWORD sendId = exception->dwSendID;
|
||||
const DWORD index = exception->dwIndex; // index of parameter that was source of error, 4294967295/0xFFFFFFFF means unknown, 0 means also UNKNOWN INDEX
|
||||
const DWORD data = cbData;
|
||||
const DWORD index = exception->dwIndex; // index of parameter that was source of error, 4294967295/0xFFFFFFFF means unknown, 0 means also UNKNOWN INDEX
|
||||
const DWORD data = cbData;
|
||||
const TraceFsxSendId trace = simulatorFsxP3D->getSendIdTrace(sendId);
|
||||
bool logGenericExceptionInfo = true;
|
||||
|
||||
switch (exceptionId)
|
||||
{
|
||||
case SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE: break;
|
||||
case SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID: break; // Specifies that the client event, request ID, data definition ID, or object ID was not recognized
|
||||
case SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED: break;
|
||||
default: break;
|
||||
case SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED:
|
||||
{
|
||||
if (trace.isValid())
|
||||
{
|
||||
// it can happen the object is not yet
|
||||
CSimConnectObject simObject = simulatorFsxP3D->getSimObjectForTrace(trace);
|
||||
if (simObject.isInvalid()) { simObject = trace.simObject; } // take the one in the trace
|
||||
if (simObject.isValid())
|
||||
{
|
||||
const bool removed = simulatorFsxP3D->m_simConnectObjects.remove(simObject.getCallsign());
|
||||
if (removed)
|
||||
{
|
||||
if (simObject.isAircraft())
|
||||
{
|
||||
CLogMessage(simulatorFsxP3D).warning("Model failed to be added and will be disabled: '%1' details: %2")
|
||||
<< simObject.getAircraftModelString()
|
||||
<< simObject.getAircraft().toQString(true);
|
||||
logGenericExceptionInfo = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLogMessage(simulatorFsxP3D).warning("Adding probe failed: %1 %2")
|
||||
<< simObject.getCallsign().asString()
|
||||
<< simObject.getAircraftModelString();
|
||||
simulatorFsxP3D->setUsingFsxTerrainProbe(false);
|
||||
logGenericExceptionInfo = false;
|
||||
}
|
||||
} // removed
|
||||
}
|
||||
}
|
||||
} // SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // switch exception id
|
||||
|
||||
// generic exception warning
|
||||
if (logGenericExceptionInfo)
|
||||
{
|
||||
QString ex;
|
||||
ex.sprintf("Exception=%lu | SendID=%lu | Index=%lu | cbData=%lu", exceptionId, sendId, index, data);
|
||||
const QString exceptionString(CSimConnectUtilities::simConnectExceptionToString(static_cast<DWORD>(exception->dwException)));
|
||||
const QString sendIdDetails = simulatorFsxP3D->getSendIdTraceDetails(sendId);
|
||||
CLogMessage(simulatorFsxP3D).warning("Caught simConnect exception: '%1' '%2' | send details: '%3'")
|
||||
<< exceptionString << ex
|
||||
<< (sendIdDetails.isEmpty() ? "N/A" : sendIdDetails);
|
||||
simulatorFsxP3D->triggerAutoTraceSendId();
|
||||
}
|
||||
QString ex;
|
||||
ex.sprintf("Exception=%lu | SendID=%lu | Index=%lu | cbData=%lu", exceptionId, sendId, index, data);
|
||||
const QString exceptionString(CSimConnectUtilities::simConnectExceptionToString(static_cast<DWORD>(exception->dwException)));
|
||||
const QString sendIdDetails = simulatorFsxP3D->getSendIdTraceDetails(sendId);
|
||||
CLogMessage(simulatorFsxP3D).warning("Caught simConnect exception: '%1' '%2' | send details: '%3'")
|
||||
<< exceptionString << ex
|
||||
<< (sendIdDetails.isEmpty() ? "N/A" : sendIdDetails);
|
||||
simulatorFsxP3D->triggerAutoTraceSendId();
|
||||
break; // SIMCONNECT_RECV_ID_EXCEPTION
|
||||
}
|
||||
case SIMCONNECT_RECV_ID_QUIT:
|
||||
@@ -145,19 +185,6 @@ namespace BlackSimPlugin
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (simulatorFsxP3D->getSimConnectProbes().isKnownSimObjectId(objectId))
|
||||
{
|
||||
switch (event->uEventID)
|
||||
{
|
||||
case SystemEventObjectRemoved:
|
||||
CLogMessage(simulatorFsxP3D).info("Removed probe id: %2") << objectId;
|
||||
simulatorFsxP3D->m_simConnectProbes.removeByObjectId(objectId);
|
||||
break;
|
||||
case SystemEventObjectAdded: // added in SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break; // SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE
|
||||
}
|
||||
case SIMCONNECT_RECV_ID_EVENT_FRAME:
|
||||
@@ -179,27 +206,11 @@ namespace BlackSimPlugin
|
||||
const 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 = false;
|
||||
simulatorFsxP3D->m_dispatchRequestIdLast = requestId;
|
||||
|
||||
if (CSimulatorFsxCommon::isRequestForSimObjTerrainProbe(requestId))
|
||||
if (CSimulatorFsxCommon::isRequestForSimConnectObject(requestId))
|
||||
{
|
||||
success = simulatorFsxP3D->setSimConnectProbeId(requestId, objectId);
|
||||
if (!success) { break; } // not an request ID of ours
|
||||
success = simulatorFsxP3D->simulatorReportedProbeAdded(objectId);
|
||||
const CSimConnectObject simObject = simulatorFsxP3D->getProbeForObjectId(objectId);
|
||||
if (success)
|
||||
{
|
||||
CLogMessage(simulatorFsxP3D).info("Added probe '%1' id: %2") << simObject.getCallsign() << objectId;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLogMessage(simulatorFsxP3D).error("Cannot add probe '%1' id: %2") << simObject.getCallsign() << objectId;
|
||||
}
|
||||
}
|
||||
else if (CSimulatorFsxCommon::isRequestForSimObjAircraft(requestId))
|
||||
{
|
||||
success = simulatorFsxP3D->setSimConnectObjectId(requestId, objectId);
|
||||
bool success = simulatorFsxP3D->setSimConnectObjectId(requestId, objectId);
|
||||
if (!success) { break; } // not an request ID of ours
|
||||
success = simulatorFsxP3D->simulatorReportedObjectAdded(objectId); // trigger follow up actions
|
||||
if (!success)
|
||||
@@ -314,8 +325,9 @@ namespace BlackSimPlugin
|
||||
}
|
||||
else if (CSimulatorFsxCommon::isRequestForSimObjTerrainProbe(requestId))
|
||||
{
|
||||
const CSimConnectObject probeObj = simulatorFsxP3D->getProbeForObjectId(objectId);
|
||||
const CSimConnectObject probeObj = simulatorFsxP3D->getSimObjectForObjectId(objectId);
|
||||
if (!probeObj.hasValidRequestAndObjectId()) { break; }
|
||||
Q_ASSERT_X(probeObj.isTerrainProbe(), Q_FUNC_INFO, "No probe");
|
||||
const CSimConnectDefinitions::SimObjectRequest subRequest = CSimulatorFsxCommon::requestToSimObjectRequest(requestId);
|
||||
|
||||
if (subRequest == CSimConnectDefinitions::SimObjectPositionData)
|
||||
@@ -340,7 +352,6 @@ namespace BlackSimPlugin
|
||||
}
|
||||
}
|
||||
} // probe
|
||||
break;
|
||||
}
|
||||
break; // default (SIMCONNECT_RECV_ID_SIMOBJECT_DATA)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user