From 2a0d0e1d845b9084c232c9d0f3cff41b5f56b488 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Thu, 2 Feb 2017 00:05:47 +0100 Subject: [PATCH] refs #873, sendToggledLightsToSimulator as own function * better resending of lights when light state in simulator is not yet known * support for cabin/recognition light --- src/plugins/simulator/fsx/simulatorfsx.cpp | 117 +++++++++++++----- src/plugins/simulator/fsx/simulatorfsx.h | 4 + .../fsx/simulatorfsxsimconnectproc.cpp | 2 +- 3 files changed, 90 insertions(+), 33 deletions(-) diff --git a/src/plugins/simulator/fsx/simulatorfsx.cpp b/src/plugins/simulator/fsx/simulatorfsx.cpp index 6a1e96410..e9135172b 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.cpp +++ b/src/plugins/simulator/fsx/simulatorfsx.cpp @@ -959,6 +959,8 @@ namespace BlackSimPlugin const bool isOnGround = interpolatedSituation.isOnGround() == CAircraftSituation::OnGround; const double gsKts = interpolatedSituation.getGroundSpeed().value(CSpeedUnit::kts()); ddRemoteAircraftParts.setAllEngines(true); + lights.setCabinOn(true); + lights.setRecognitionOn(true); // when first detected moving, lights on if (isOnGround) @@ -1035,6 +1037,10 @@ namespace BlackSimPlugin ddRemoteAircraftParts.engine3Combustion = parts.isEngineOn(3) ? 1 : 0; ddRemoteAircraftParts.engine4Combustion = parts.isEngineOn(4) ? 1 : 0; + CAircraftLights lights = parts.getLights(); + lights.setRecognitionOn(parts.isAnyEngineOn()); + lights.setCabinOn(parts.isAnyEngineOn()); + return this->sendRemoteAircraftPartsToSimulator(simObj, ddRemoteAircraftParts, parts.getLights()); } @@ -1045,51 +1051,89 @@ namespace BlackSimPlugin // same as in simulator or same as already send to simulator? const CAircraftLights sentLights(simObj.getLightsAsSent()); - if (simObj.getPartsAsSent() == ddRemoteAircraftParts && - (simObj.getCurrentLightsInSimulator() == lights || sentLights == lights)) { return true; } + if (simObj.getPartsAsSent() == ddRemoteAircraftParts && sentLights == lights) { return true; } // in case we sent, we sent everything const HRESULT hr = SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraftParts, objectId, SIMCONNECT_DATA_SET_FLAG_DEFAULT, 0, sizeof(DataDefinitionRemoteAircraftParts), &ddRemoteAircraftParts); - if (hr != S_OK) { CLogMessage(this).warning("Failed so set parts on SimObject '%1' callsign: '%2'") << simObj.getObjectId() << simObj.getCallsign(); } + if (hr == S_OK) + { + // Update data + CSimConnectObject &objUdpate = m_simConnectObjects[simObj.getCallsign()]; + objUdpate.setPartsAsSent(ddRemoteAircraftParts); + } + else + { + CLogMessage(this).warning("Failed so set parts on SimObject '%1' callsign: '%2'") << simObj.getObjectId() << simObj.getCallsign(); + } // lights we can set directly SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventLandingLightsSet, lights.isLandingOn() ? 1.0 : 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventStrobesSet, lights.isStrobeOn() ? 1.0 : 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); // lights we need to toggle (risk with quickly changing values that we accidentally toggle back) - // I sent 0/1 here, but the value is supposed to be irrelevant since "toggling" - if (!sentLights.isNull()) - { - if (sentLights.isTaxiOn() == lights.isTaxiOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleTaxiLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (sentLights.isNavOn() == lights.isNavOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleNavLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (sentLights.isBeaconOn() == lights.isBeaconOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleBeaconLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - if (sentLights.isLogoOn() == lights.isLogoOn()) - { - SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleLogoLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); - } - } - - // Update data - CSimConnectObject &objUdpate = m_simConnectObjects[simObj.getCallsign()]; - objUdpate.setPartsAsSent(ddRemoteAircraftParts); - objUdpate.setLightsAsSent(lights); // pretend lights are set + sendToggledLightsToSimulator(simObj, lights); // done return hr == S_OK; } + void CSimulatorFsx::sendToggledLightsToSimulator(const CSimConnectObject &simObj, const CAircraftLights &lightsWanted, bool force) + { + if (!simObj.hasValidRequestAndObjectId()) { return; } // stale + const CAircraftLights lightsIsState = simObj.getCurrentLightsInSimulator(); + if (lightsWanted == lightsIsState) { return; } + if (!force && lightsWanted == simObj.getLightsAsSent()) { return; } + const CCallsign callsign(simObj.getCallsign()); + + // Update data + CSimConnectObject &simObjToUpdate = m_simConnectObjects[callsign]; + simObjToUpdate.setLightsAsSent(lightsWanted); + + // state available, then I can toggle + if (!lightsIsState.isNull()) + { + const DWORD objectId = simObj.getObjectId(); + if (lightsWanted.isTaxiOn() != lightsIsState.isTaxiOn()) + { + SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleTaxiLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } + if (lightsWanted.isNavOn() != lightsIsState.isNavOn()) + { + SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleNavLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } + if (lightsWanted.isBeaconOn() != lightsIsState.isBeaconOn()) + { + SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleBeaconLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } + if (lightsWanted.isLogoOn() != lightsIsState.isLogoOn()) + { + SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleLogoLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } + if (lightsWanted.isRecognitionOn() != lightsIsState.isRecognitionOn()) + { + SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleRecognitionLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } + if (lightsWanted.isCabinOn() != lightsIsState.isCabinOn()) + { + SimConnect_TransmitClientEvent(m_hSimConnect, objectId, EventToggleCabinLights, 0.0, SIMCONNECT_GROUP_PRIORITY_HIGHEST, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY); + } + return; + } + + // missing lights info from simulator + CLogMessage(this).info("Missing light state for '%1'") << callsign; + QTimer::singleShot(2500, this, [ = ] + { + const CSimConnectObject currentSimObj = m_simConnectObjects[callsign]; + if (!currentSimObj.hasValidRequestAndObjectId()) { return; } // stale + if (lightsWanted != currentSimObj.getLightsAsSent()) { return; } // changed in between + sendToggledLightsToSimulator(currentSimObj, lightsWanted, true); + }); + } + SIMCONNECT_DATA_INITPOSITION CSimulatorFsx::aircraftSituationToFsxPosition(const CAircraftSituation &situation) { SIMCONNECT_DATA_INITPOSITION position; @@ -1166,22 +1210,31 @@ namespace BlackSimPlugin if (!simObject.hasValidRequestAndObjectId()) { return false; } if (simObject.getSimDataPeriod() == period) { return true; } // already queried like this - const HRESULT result = SimConnect_RequestDataOnSimObject(m_hSimConnect, simObject.getRequestId() + RequestSimDataOffset, CSimConnectDefinitions::DataRemoteAircraftSimData, simObject.getObjectId(), period, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED); + // always request, not only when something has changed + const HRESULT result = SimConnect_RequestDataOnSimObject( + m_hSimConnect, simObject.getRequestId() + RequestSimDataOffset, + CSimConnectDefinitions::DataRemoteAircraftSimData, + simObject.getObjectId(), period); if (result == S_OK) { m_simConnectObjects[simObject.getCallsign()].setSimDataPeriod(period); return true; } - CLogMessage(this).error("Cannot request data on object '%1'") << simObject.getObjectId(); + CLogMessage(this).error("Cannot request sim data on object '%1'") << simObject.getObjectId(); return false; } bool CSimulatorFsx::requestLightsForSimObject(const CSimConnectObject &simObject) { if (!simObject.hasValidRequestAndObjectId()) { return false; } - const HRESULT result = SimConnect_RequestDataOnSimObject(m_hSimConnect, simObject.getRequestId() + RequestLightsOffset, CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(), SIMCONNECT_PERIOD_SECOND, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED); + + // always request, not only when something has changed + const HRESULT result = SimConnect_RequestDataOnSimObject( + m_hSimConnect, simObject.getRequestId() + RequestLightsOffset, + CSimConnectDefinitions::DataRemoteAircraftLights, simObject.getObjectId(), + SIMCONNECT_PERIOD_SECOND); if (result == S_OK) { return true; } - CLogMessage(this).error("Cannot request data on object '%1'") << simObject.getObjectId(); + CLogMessage(this).error("Cannot request lights data on object '%1'") << simObject.getObjectId(); return false; } diff --git a/src/plugins/simulator/fsx/simulatorfsx.h b/src/plugins/simulator/fsx/simulatorfsx.h index 2a3d71b19..c7c54a5e7 100644 --- a/src/plugins/simulator/fsx/simulatorfsx.h +++ b/src/plugins/simulator/fsx/simulatorfsx.h @@ -196,6 +196,10 @@ namespace BlackSimPlugin //! 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); diff --git a/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp b/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp index 902351394..bb3fda20a 100644 --- a/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp +++ b/src/plugins/simulator/fsx/simulatorfsxsimconnectproc.cpp @@ -233,7 +233,7 @@ namespace BlackSimPlugin } else if (isRequestForLights(requestId)) { - static_assert(sizeof(DataDefinitionRemoteAircraftLights) == 6 * sizeof(double), "DataDefinitionRemoteAircraftLights has an incorrect size."); + 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;