mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-23 07:15:35 +08:00
Ref T245, a P3D version of follow aircraft, still experimental
* testing approaches camera, observer, and guessing view name * SimObject code for camera/observer * functions aircraft situation -> FSX formats
This commit is contained in:
@@ -182,12 +182,28 @@ namespace BlackSimPlugin
|
||||
//! Camera rotation;
|
||||
const SIMCONNECT_DATA_PBH &cameraRotation() const { return m_cameraRotation; }
|
||||
|
||||
//! Camera position/rotation
|
||||
void setCameraPositionAndRotation(const SIMCONNECT_DATA_XYZ &position, const SIMCONNECT_DATA_PBH &rotation)
|
||||
{
|
||||
m_cameraPosition = position;
|
||||
m_cameraRotation = rotation;
|
||||
}
|
||||
|
||||
//! Camera GUID
|
||||
GUID getCameraGUID() const { return m_cameraGuid; }
|
||||
|
||||
//! Set camera GUID
|
||||
void setCameraGUID(GUID guid) { m_cameraGuid = guid; m_camera = true; }
|
||||
|
||||
//! No camera anymore
|
||||
void removeCamera() { m_camera = false; }
|
||||
|
||||
//! Set observer
|
||||
void setObserverName(const QString &observer) { m_observerName = observer; }
|
||||
|
||||
//! Observer name
|
||||
const QString &getObserverName() const { return m_observerName; }
|
||||
|
||||
//! Reset the state (like it was a new onject) without affecting interpolator and aircraft
|
||||
void resetState();
|
||||
|
||||
@@ -288,6 +304,7 @@ namespace BlackSimPlugin
|
||||
SIMCONNECT_DATA_XYZ m_cameraPosition;
|
||||
SIMCONNECT_DATA_PBH m_cameraRotation;
|
||||
QByteArray m_callsignByteArray;
|
||||
QString m_observerName;
|
||||
BlackMisc::Aviation::CAircraftLights m_currentLightsInSim { nullptr }; //!< current lights to know state for toggling
|
||||
BlackMisc::Aviation::CAircraftLights m_lightsAsSent { nullptr }; //!< lights as sent to simulator
|
||||
SIMCONNECT_PERIOD m_requestSimDataPeriod = SIMCONNECT_PERIOD_NEVER; //!< how often do we query ground elevation
|
||||
|
||||
@@ -539,6 +539,18 @@ namespace BlackSimPlugin
|
||||
return m_simConnectObjects.removeByOtherSimObject(trace.simObject);
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::removeCamera(CSimConnectObject &simObject)
|
||||
{
|
||||
// not in FSX
|
||||
Q_UNUSED(simObject);
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::removeObserver(CSimConnectObject &simObject)
|
||||
{
|
||||
// not in FSX
|
||||
Q_UNUSED(simObject);
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::triggerAutoTraceSendId(qint64 traceTimeMs)
|
||||
{
|
||||
if (m_traceSendId) { return false; } // no need
|
||||
@@ -1554,6 +1566,8 @@ namespace BlackSimPlugin
|
||||
|
||||
// call in SIM
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = simObject.getRequestId(CSimConnectDefinitions::SimObjectRemove);
|
||||
this->removeCamera(simObject);
|
||||
this->removeObserver(simObject);
|
||||
const HRESULT result = SimConnect_AIRemoveObject(m_hSimConnect, static_cast<SIMCONNECT_OBJECT_ID>(simObject.getObjectId()), requestId);
|
||||
if (isOk(result))
|
||||
{
|
||||
@@ -1968,6 +1982,16 @@ namespace BlackSimPlugin
|
||||
return position;
|
||||
}
|
||||
|
||||
SIMCONNECT_DATA_PBH CSimulatorFsxCommon::aircraftSituationToFsxPBH(const CAircraftSituation &situation)
|
||||
{
|
||||
// MSFS has inverted pitch and bank angles
|
||||
SIMCONNECT_DATA_PBH pbh;
|
||||
pbh.Pitch = -situation.getPitch().value(CAngleUnit::deg());
|
||||
pbh.Bank = -situation.getBank().value(CAngleUnit::deg());
|
||||
pbh.Heading = situation.getHeading().value(CAngleUnit::deg());
|
||||
return pbh;
|
||||
}
|
||||
|
||||
SIMCONNECT_DATA_INITPOSITION CSimulatorFsxCommon::coordinateToFsxPosition(const ICoordinateGeodetic &coordinate)
|
||||
{
|
||||
SIMCONNECT_DATA_INITPOSITION position;
|
||||
@@ -1982,6 +2006,15 @@ namespace BlackSimPlugin
|
||||
return position;
|
||||
}
|
||||
|
||||
SIMCONNECT_DATA_LATLONALT CSimulatorFsxCommon::coordinateToFsxLatLonAlt(const ICoordinateGeodetic &coordinate)
|
||||
{
|
||||
SIMCONNECT_DATA_LATLONALT lla;
|
||||
lla.Latitude = coordinate.latitude().value(CAngleUnit::deg());
|
||||
lla.Longitude = coordinate.longitude().value(CAngleUnit::deg());
|
||||
lla.Altitude = coordinate.geodeticHeight().value(CLengthUnit::ft()); // already corrected in interpolator if there is an underflow
|
||||
return lla;
|
||||
}
|
||||
|
||||
void CSimulatorFsxCommon::synchronizeTime(const CTime &zuluTimeSim, const CTime &localTimeSim)
|
||||
{
|
||||
if (!m_simTimeSynced) { return; }
|
||||
|
||||
@@ -261,6 +261,12 @@ namespace BlackSimPlugin
|
||||
//! Remove the CSimConnectObject linked in the trace
|
||||
bool removeSimObjectForTrace(const TraceFsxSendId &trace);
|
||||
|
||||
//! Remove camera if any
|
||||
virtual void removeCamera(CSimConnectObject &simObject);
|
||||
|
||||
//! Remove observer if any
|
||||
virtual void removeObserver(CSimConnectObject &simObject);
|
||||
|
||||
//! Trace if required, log errors
|
||||
HRESULT logAndTraceSendId(HRESULT hr, const QString &warningMsg, const QString &functionName, const QString &functionDetails = {});
|
||||
|
||||
@@ -281,6 +287,20 @@ namespace BlackSimPlugin
|
||||
static bool is64bit() { return (BlackConfig::CBuildConfig::buildWordSize() == 64); }
|
||||
//! @}
|
||||
|
||||
//! Format conversion
|
||||
//! \note must be valid situation
|
||||
static SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation, bool sendGnd = true);
|
||||
|
||||
//! Format conversion
|
||||
//! \note must be valid situation
|
||||
static SIMCONNECT_DATA_PBH aircraftSituationToFsxPBH(const BlackMisc::Aviation::CAircraftSituation &situation);
|
||||
|
||||
//! Format conversion
|
||||
static SIMCONNECT_DATA_INITPOSITION coordinateToFsxPosition(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
|
||||
|
||||
//! Format conversion
|
||||
static SIMCONNECT_DATA_LATLONALT coordinateToFsxLatLonAlt(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
|
||||
|
||||
static constexpr qint64 AutoTraceOffsetMs = 10 * 1000; //!< how long do we trace?
|
||||
HANDLE m_hSimConnect = nullptr; //!< handle to SimConnect object
|
||||
DispatchProc m_dispatchProc = &CSimulatorFsxCommon::SimConnectProc; //!< called function for dispatch, can be overriden by specialized P3D function
|
||||
@@ -454,13 +474,6 @@ namespace BlackSimPlugin
|
||||
//! The SimConnect object for idxs
|
||||
CSimConnectObject getSimObjectForObjectId(DWORD objectId) const;
|
||||
|
||||
//! Format conversion
|
||||
//! \note must be valid situation
|
||||
SIMCONNECT_DATA_INITPOSITION aircraftSituationToFsxPosition(const BlackMisc::Aviation::CAircraftSituation &situation, bool sendGnd = true);
|
||||
|
||||
//! Format conversion
|
||||
SIMCONNECT_DATA_INITPOSITION coordinateToFsxPosition(const BlackMisc::Geo::ICoordinateGeodetic &coordinate);
|
||||
|
||||
//! Sync time with user's computer
|
||||
void synchronizeTime(const BlackMisc::PhysicalQuantities::CTime &zuluTimeSim, const BlackMisc::PhysicalQuantities::CTime &localTimeSim);
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace BlackSimPlugin
|
||||
const double latDeg = reference.latitude().value(CAngleUnit::deg());
|
||||
const double lngDeg = reference.longitude().value(CAngleUnit::deg());
|
||||
const double maxAltFt = hasHeight ? reference.geodeticHeight().value(CLengthUnit::ft()) : 50000;
|
||||
const DWORD dwGridWidth = 1.0;
|
||||
const DWORD dwGridWidth = 1.0;
|
||||
const DWORD dwGridHeight = 1.0;
|
||||
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimObjTerrainProbe(); // P3D we use new request id each time (no simobject)
|
||||
@@ -136,55 +136,93 @@ namespace BlackSimPlugin
|
||||
bool CSimulatorP3D::followAircraft(const CCallsign &callsign)
|
||||
{
|
||||
if (this->isShuttingDownOrDisconnected()) { return false; }
|
||||
if (!CBuildConfig::isLocalDeveloperDebugBuild()) { return false; }
|
||||
|
||||
// Experimental code, suffering from bugs and also requiring
|
||||
// P3D v4.2 (bugs in V4.1
|
||||
CSimConnectObject &simObject = m_simConnectObjects[callsign];
|
||||
|
||||
const CAircraftModel model = simObject.getAircraft().getModel();
|
||||
const QString viewName = "Commercial Jet-" + callsign.asString();
|
||||
const char *view = viewName.toLatin1().constData();
|
||||
CLogMessage(this).warning("Modelview %1") << viewName;
|
||||
Q_UNUSED(model);
|
||||
|
||||
HRESULT hr = SimConnect_ChangeView(m_hSimConnect, view);
|
||||
return isOk(hr);
|
||||
|
||||
/**
|
||||
if (!simObject.hasValidRequestAndObjectId()) { return false; }
|
||||
if (simObject.getCallsignByteArray().isEmpty()) { return false; }
|
||||
const char *cs = simObject.getCallsignByteArray().constData();
|
||||
HRESULT hr = s_false();
|
||||
|
||||
HRESULT hr = S_FALSE;
|
||||
//
|
||||
// Experimental code
|
||||
//
|
||||
|
||||
/** version a
|
||||
const char *cameraName = simObject.getCallsignByteArray().constData();
|
||||
if (!simObject.hasCamera())
|
||||
{
|
||||
SIMCONNECT_DATA_XYZ position; position.x = 25; position.y = 25; position.z = 0;
|
||||
SIMCONNECT_DATA_PBH rotation; rotation.Pitch = 0; rotation.Bank = 0; rotation.Heading = -90;
|
||||
simObject.setCameraPositionAndRotation(position, rotation);
|
||||
|
||||
GUID guid;
|
||||
CoCreateGuid(&guid);
|
||||
const SIMCONNECT_CAMERA_TYPE cameraType = SIMCONNECT_CAMERA_TYPE_OBJECT_CENTER;
|
||||
hr = SimConnect_CreateCameraDefinition(m_hSimConnect, guid, cameraType, cs, simObject.cameraPosition(), simObject.cameraRotation());
|
||||
if (hr == S_OK)
|
||||
// SIMCONNECT_CAMERA_TYPE_OBJECT_AI_VIRTUAL needs a P3D configuration
|
||||
// SIMCONNECT_CAMERA_TYPE_LATLONALT_ORTHOGONAL is a top down view
|
||||
// SIMCONNECT_CAMERA_TYPE_FIXED position at one place
|
||||
const SIMCONNECT_CAMERA_TYPE cameraType = SIMCONNECT_CAMERA_TYPE_OBJECT_AI_CENTER;
|
||||
hr = SimConnect_CreateCameraDefinition(m_hSimConnect, guid, cameraType, cameraName, simObject.cameraPosition(), simObject.cameraRotation());
|
||||
if (isOk(hr))
|
||||
{
|
||||
const SIMCONNECT_OBJECT_ID objectId = static_cast<SIMCONNECT_OBJECT_ID>(simObject.getObjectId());
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimData();
|
||||
hr = SimConnect_CreateCameraInstance(m_hSimConnect, guid, cs, objectId, requestId);
|
||||
if (hr == S_OK)
|
||||
const SIMCONNECT_DATA_REQUEST_ID requestId = this->obtainRequestIdForSimObjAircraft();
|
||||
hr = SimConnect_CreateCameraInstance(m_hSimConnect, guid, cameraName, objectId, requestId);
|
||||
if (isOk(hr))
|
||||
{
|
||||
simObject.setCameraGUID(guid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
version a **/
|
||||
|
||||
/** version b
|
||||
const CAircraftModel m = simObject.getAircraftModel();
|
||||
const QString viewName = "Regional Jet-" + callsign.asString();
|
||||
const QByteArray viewNameBA = viewName.toLatin1();
|
||||
hr = SimConnect_ChangeView(m_hSimConnect, viewNameBA.constData());
|
||||
**/
|
||||
|
||||
// Observer is P3D only, not FSX
|
||||
const CAircraftSituation situation = m_lastSentSituations[callsign];
|
||||
if (situation.isNull()) { return false; }
|
||||
SIMCONNECT_DATA_OBSERVER obs;
|
||||
SIMCONNECT_DATA_PBH pbh; pbh.Pitch = pbh.Bank = pbh.Heading = 0;
|
||||
obs.Rotation = pbh;
|
||||
obs.Position = coordinateToFsxLatLonAlt(situation);
|
||||
obs.Regime = SIMCONNECT_OBSERVER_REGIME_GHOST;
|
||||
obs.RotateOnTarget = TRUE;
|
||||
obs.FocusFixed = TRUE;
|
||||
obs.FieldOfViewH = 30; // deg.
|
||||
obs.FieldOfViewV = 30; // deg.
|
||||
obs.LinearStep = 20; // meters
|
||||
obs.AngularStep = 10; // deg.
|
||||
|
||||
const char *observerName = simObject.getCallsignByteArray().constData();
|
||||
hr = SimConnect_CreateObserver(m_hSimConnect, observerName, obs);
|
||||
if (isOk(hr))
|
||||
{
|
||||
SIMCONNECT_DATA_XYZ offset;
|
||||
offset.x = offset.y = 30;
|
||||
offset.z = 0;
|
||||
hr = SimConnect_ObserverAttachToEntityOn(m_hSimConnect, observerName, simObject.getObjectId(), offset);
|
||||
if (isOk(hr))
|
||||
{
|
||||
SimConnect_SetObserverLookAt(m_hSimConnect, observerName, obs.Position);
|
||||
|
||||
// const QByteArray viewName = QStringLiteral("Observer %1").arg(callsign.asString()).toLatin1();
|
||||
hr = SimConnect_OpenView(m_hSimConnect, observerName);
|
||||
|
||||
simObject.setObserverName(callsign.asString());
|
||||
}
|
||||
}
|
||||
|
||||
if (!simObject.hasCamera()) { return false; }
|
||||
hr = SimConnect_OpenView(m_hSimConnect, cs);
|
||||
return hr == S_OK;
|
||||
**/
|
||||
return isOk(hr);
|
||||
}
|
||||
|
||||
HRESULT CSimulatorP3D::initEventsP3D()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (hr != S_OK)
|
||||
HRESULT hr = s_ok();
|
||||
if (isFailure(hr))
|
||||
{
|
||||
CLogMessage(this).error("P3D plugin error: %1") << "initEventsP3D failed";
|
||||
return hr;
|
||||
@@ -192,6 +230,23 @@ namespace BlackSimPlugin
|
||||
return hr;
|
||||
}
|
||||
|
||||
void CSimulatorP3D::removeCamera(FsxCommon::CSimConnectObject &simObject)
|
||||
{
|
||||
if (!simObject.hasCamera()) { return; }
|
||||
simObject.removeCamera();
|
||||
// const char *cameraName = simObject.getCallsignByteArray().constData();
|
||||
// SimConnect_DeleteCameraInstance(m_hSimConnect, simObject.getCameraGUID(), 0);
|
||||
// SimConnect_CloseView(m_hSimConnect, cameraName);
|
||||
}
|
||||
|
||||
void CSimulatorP3D::removeObserver(CSimConnectObject &simObject)
|
||||
{
|
||||
if (simObject.getObserverName().isEmpty()) { return; }
|
||||
|
||||
QByteArray viewName = simObject.getObserverName().toLatin1();
|
||||
SimConnect_CloseView(m_hSimConnect, viewName.constData());
|
||||
}
|
||||
|
||||
bool CSimulatorP3D::releaseAIControl(const CSimConnectObject &simObject, SIMCONNECT_DATA_REQUEST_ID requestId)
|
||||
{
|
||||
// completely remove AI control
|
||||
|
||||
@@ -55,6 +55,12 @@ namespace BlackSimPlugin
|
||||
virtual HRESULT initEventsP3D() override;
|
||||
|
||||
#ifdef Q_OS_WIN64
|
||||
//! \copydoc FsxCommon::CSimulatorFsxCommon::removeCamera
|
||||
virtual void removeCamera(FsxCommon::CSimConnectObject &simObject) override;
|
||||
|
||||
//! \copydoc FsxCommon::CSimulatorFsxCommon::removeObserver
|
||||
virtual void removeObserver(FsxCommon::CSimConnectObject &simObject) override;
|
||||
|
||||
//! \copydoc FsxCommon::CSimulatorFsxCommon::releaseAIControl
|
||||
//! \remark P3D API release of control
|
||||
virtual bool releaseAIControl(const FsxCommon::CSimConnectObject &simObject, SIMCONNECT_DATA_REQUEST_ID requestId) override;
|
||||
|
||||
Reference in New Issue
Block a user