mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-20 12:35:43 +08:00
Issue #17 Restore aircraft labels with math and logic cribbed from LiveTraffic's XPMP2
This commit is contained in:
@@ -213,10 +213,10 @@ namespace BlackSimPlugin
|
|||||||
//! \copydoc XSwiftBus::CTraffic::setDefaultIcao
|
//! \copydoc XSwiftBus::CTraffic::setDefaultIcao
|
||||||
void setDefaultIcao(const QString &defaultIcao);
|
void setDefaultIcao(const QString &defaultIcao);
|
||||||
|
|
||||||
//! deprecated
|
//! \copydoc XSwiftBus::CTraffic::setDrawingLabels
|
||||||
void setDrawingLabels(bool drawing);
|
void setDrawingLabels(bool drawing);
|
||||||
|
|
||||||
//! deprecated
|
//! \copydoc XSwiftBus::CTraffic::isDrawingLabels
|
||||||
bool isDrawingLabels() const;
|
bool isDrawingLabels() const;
|
||||||
|
|
||||||
//! \copydoc XSwiftBus::CTraffic::setMaxPlanes
|
//! \copydoc XSwiftBus::CTraffic::setMaxPlanes
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <XPLM/XPLMDataAccess.h>
|
#include <XPLM/XPLMDataAccess.h>
|
||||||
#include <XPLM/XPLMUtilities.h>
|
#include <XPLM/XPLMUtilities.h>
|
||||||
#include <vector>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
@@ -65,10 +65,10 @@ namespace XSwiftBus
|
|||||||
bool isValid() const { return m_ref; }
|
bool isValid() const { return m_ref; }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void implSetAll(std::vector<T> const &);
|
void implSetAll(T* const);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<T> implGetAll() const;
|
void implGetAll(T*) const;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void implSetAt(int index, T);
|
void implSetAt(int index, T);
|
||||||
@@ -136,11 +136,14 @@ namespace XSwiftBus
|
|||||||
//! Dataref type
|
//! Dataref type
|
||||||
using DataRefType = typename DataRefTraits::type;
|
using DataRefType = typename DataRefTraits::type;
|
||||||
|
|
||||||
|
//! Array dataref size
|
||||||
|
static constexpr auto DataRefSize = DataRefTraits::size;
|
||||||
|
|
||||||
//! Set the value of the whole array (if it is writable)
|
//! Set the value of the whole array (if it is writable)
|
||||||
void setAll(std::vector<DataRefType> const &a) { static_assert(DataRefTraits::writable, "read-only dataref"); ArrayDataRefImpl::implSetAll(a); }
|
void setAll(std::array<DataRefType, DataRefSize> const &a) { static_assert(DataRefTraits::writable, "read-only dataref"); ArrayDataRefImpl::implSetAll<DataRefType>(a.data()); }
|
||||||
|
|
||||||
//! Get the value of the whole array
|
//! Get the value of the whole array
|
||||||
std::vector<DataRefType> getAll() const { return ArrayDataRefImpl::implGetAll<DataRefType>(); }
|
std::array<DataRefType, DataRefSize> getAll() const { std::array<DataRefType, DataRefSize> result; ArrayDataRefImpl::implGetAll<DataRefType>(result.data()); return result; }
|
||||||
|
|
||||||
//! Set the value of a single element (if it is writable)
|
//! Set the value of a single element (if it is writable)
|
||||||
void setAt(int index, DataRefType d) { static_assert(DataRefTraits::writable, "read-only dataref"); ArrayDataRefImpl::implSetAt(index, d); }
|
void setAt(int index, DataRefType d) { static_assert(DataRefTraits::writable, "read-only dataref"); ArrayDataRefImpl::implSetAt(index, d); }
|
||||||
@@ -218,13 +221,13 @@ namespace XSwiftBus
|
|||||||
inline double DataRefImpl::implGet<double>() const { return XPLMGetDatad(m_ref); }
|
inline double DataRefImpl::implGet<double>() const { return XPLMGetDatad(m_ref); }
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void ArrayDataRefImpl::implSetAll<int>(std::vector<int> const &v) { assert((int)v.size() <= m_size); XPLMSetDatavi(m_ref, const_cast<int *>(&v[0]), 0, (int)v.size()); }
|
inline void ArrayDataRefImpl::implSetAll(int const *v) { XPLMSetDatavi(m_ref, const_cast<int *>(v), 0, m_size); }
|
||||||
template <>
|
template <>
|
||||||
inline void ArrayDataRefImpl::implSetAll<float>(std::vector<float> const &v) { assert((int)v.size() <= m_size); XPLMSetDatavf(m_ref, const_cast<float *>(&v[0]), 0, (int)v.size()); }
|
inline void ArrayDataRefImpl::implSetAll(float const *v) { XPLMSetDatavf(m_ref, const_cast<float *>(v), 0, m_size); }
|
||||||
template <>
|
template <>
|
||||||
inline std::vector<int> ArrayDataRefImpl::implGetAll<int>() const { std::vector<int> v(m_size); XPLMGetDatavi(m_ref, &v[0], 0, m_size); return v; }
|
inline void ArrayDataRefImpl::implGetAll(int *v) const { XPLMGetDatavi(m_ref, &v[0], 0, m_size); }
|
||||||
template <>
|
template <>
|
||||||
inline std::vector<float> ArrayDataRefImpl::implGetAll<float>() const { std::vector<float> v(m_size); XPLMGetDatavf(m_ref, &v[0], 0, m_size); return v; }
|
inline void ArrayDataRefImpl::implGetAll(float *v) const { XPLMGetDatavf(m_ref, &v[0], 0, m_size); }
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void ArrayDataRefImpl::implSetAt<int>(int i, int d) { assert(i <= m_size); XPLMSetDatavi(m_ref, &d, i, 1); }
|
inline void ArrayDataRefImpl::implSetAt<int>(int i, int d) { assert(i <= m_size); XPLMSetDatavi(m_ref, &d, i, 1); }
|
||||||
|
|||||||
@@ -28,15 +28,20 @@ namespace XSwiftBus
|
|||||||
//! Destructor.
|
//! Destructor.
|
||||||
virtual ~CDrawable() { hide(); }
|
virtual ~CDrawable() { hide(); }
|
||||||
|
|
||||||
|
//! Is currently shown.
|
||||||
|
bool isVisible() const { return m_visible; }
|
||||||
|
|
||||||
//! Register the draw callback.
|
//! Register the draw callback.
|
||||||
void show()
|
void show()
|
||||||
{
|
{
|
||||||
|
m_visible = true;
|
||||||
XPLMRegisterDrawCallback(callback, m_phase, m_before, static_cast<void*>(this));
|
XPLMRegisterDrawCallback(callback, m_phase, m_before, static_cast<void*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Unregister the draw callback.
|
//! Unregister the draw callback.
|
||||||
void hide()
|
void hide()
|
||||||
{
|
{
|
||||||
|
m_visible = false;
|
||||||
XPLMUnregisterDrawCallback(callback, m_phase, m_before, static_cast<void*>(this));
|
XPLMUnregisterDrawCallback(callback, m_phase, m_before, static_cast<void*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +56,9 @@ namespace XSwiftBus
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XPLMDrawingPhase m_phase;
|
XPLMDrawingPhase m_phase;
|
||||||
const bool m_before;
|
bool m_before = false;
|
||||||
|
bool m_visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ namespace XSwiftBus
|
|||||||
{
|
{
|
||||||
// m_startServerMenuItem = m_menu.item("Start XSwiftBus", [this]{ startServer(CDBusConnection::SessionBus); });
|
// m_startServerMenuItem = m_menu.item("Start XSwiftBus", [this]{ startServer(CDBusConnection::SessionBus); });
|
||||||
|
|
||||||
|
m_showHideLabelsMenuItem = m_menu.item("Show/Hide Aircraft Labels", [this]
|
||||||
|
{
|
||||||
|
m_traffic->setDrawingLabels(!m_traffic->isDrawingLabels());
|
||||||
|
});
|
||||||
m_messageWindowSubMenu = m_menu.subMenu("Message Window");
|
m_messageWindowSubMenu = m_menu.subMenu("Message Window");
|
||||||
m_toggleMessageWindowMenuItem = m_messageWindowSubMenu.item("Show/Hide", [this]
|
m_toggleMessageWindowMenuItem = m_messageWindowSubMenu.item("Show/Hide", [this]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,6 +65,9 @@ namespace XSwiftBus
|
|||||||
assert(!s_instance);
|
assert(!s_instance);
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
XPLMRegisterKeySniffer(followAircraftKeySniffer, 1, this);
|
XPLMRegisterKeySniffer(followAircraftKeySniffer, 1, this);
|
||||||
|
|
||||||
|
// init labels
|
||||||
|
this->setDrawingLabels(this->getSettings().isDrawingLabels());
|
||||||
}
|
}
|
||||||
// *INDENT-ON*
|
// *INDENT-ON*
|
||||||
|
|
||||||
@@ -257,6 +260,30 @@ namespace XSwiftBus
|
|||||||
XPMPSetDefaultPlaneICAO(defaultIcao.c_str());
|
XPMPSetDefaultPlaneICAO(defaultIcao.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTraffic::setDrawingLabels(bool drawing)
|
||||||
|
{
|
||||||
|
CSettings s = this->getSettings();
|
||||||
|
if (s.isDrawingLabels() != drawing)
|
||||||
|
{
|
||||||
|
s.setDrawingLabels(drawing);
|
||||||
|
this->setSettings(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawing)
|
||||||
|
{
|
||||||
|
m_labels.show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_labels.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTraffic::isDrawingLabels() const
|
||||||
|
{
|
||||||
|
return m_labels.isVisible();
|
||||||
|
}
|
||||||
|
|
||||||
void CTraffic::setMaxPlanes(int planes)
|
void CTraffic::setMaxPlanes(int planes)
|
||||||
{
|
{
|
||||||
CSettings s = this->getSettings();
|
CSettings s = this->getSettings();
|
||||||
@@ -581,13 +608,19 @@ namespace XSwiftBus
|
|||||||
else if (message.getMethodName() == "setDrawingLabels")
|
else if (message.getMethodName() == "setDrawingLabels")
|
||||||
{
|
{
|
||||||
maybeSendEmptyDBusReply(wantsReply, sender, serial);
|
maybeSendEmptyDBusReply(wantsReply, sender, serial);
|
||||||
// removed in xpmp2
|
bool drawing = true;
|
||||||
|
message.beginArgumentRead();
|
||||||
|
message.getArgument(drawing);
|
||||||
|
queueDBusCall([ = ]()
|
||||||
|
{
|
||||||
|
setDrawingLabels(drawing);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (message.getMethodName() == "isDrawingLabels")
|
else if (message.getMethodName() == "isDrawingLabels")
|
||||||
{
|
{
|
||||||
queueDBusCall([ = ]()
|
queueDBusCall([ = ]()
|
||||||
{
|
{
|
||||||
sendDBusReply(sender, serial, false); // always false in xpmp2
|
sendDBusReply(sender, serial, isDrawingLabels());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (message.getMethodName() == "setMaxPlanes")
|
else if (message.getMethodName() == "setMaxPlanes")
|
||||||
@@ -843,6 +876,7 @@ namespace XSwiftBus
|
|||||||
void CTraffic::interpolatePosition(Plane *plane)
|
void CTraffic::interpolatePosition(Plane *plane)
|
||||||
{
|
{
|
||||||
std::memcpy(&plane->positions[3], &plane->positions[2], sizeof(plane->positions[2]));
|
std::memcpy(&plane->positions[3], &plane->positions[2], sizeof(plane->positions[2]));
|
||||||
|
return;
|
||||||
|
|
||||||
const auto now = std::chrono::steady_clock::now();
|
const auto now = std::chrono::steady_clock::now();
|
||||||
const auto t1 = plane->positionTimes[2] - plane->positionTimes[0];
|
const auto t1 = plane->positionTimes[2] - plane->positionTimes[0];
|
||||||
@@ -879,6 +913,53 @@ namespace XSwiftBus
|
|||||||
plane->prevSurfacesLerpTime = now;
|
plane->prevSurfacesLerpTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTraffic::Labels::draw()
|
||||||
|
{
|
||||||
|
static const double metersPerFt = 0.3048;
|
||||||
|
static float color[3]{ 1.0f, 0.75f, 0.0f };
|
||||||
|
std::array<float, 16> worldMat = m_worldMat.getAll();
|
||||||
|
std::array<float, 16> projMat = m_projMat.getAll();
|
||||||
|
double windowWidth = static_cast<double>(m_windowWidth.get());
|
||||||
|
double windowHeight = static_cast<double>(m_windowHeight.get());
|
||||||
|
XPLMCameraPosition_t camPos {};
|
||||||
|
XPLMReadCameraPosition(&camPos);
|
||||||
|
|
||||||
|
for (const auto pair : m_traffic->m_planesById)
|
||||||
|
{
|
||||||
|
char *text = const_cast<char *>(pair.second->label);
|
||||||
|
const XPMPPlanePosition_t &planePos = pair.second->positions[3];
|
||||||
|
|
||||||
|
double worldPos[4]{ 0, 0, 0, 1 };
|
||||||
|
double localPos[4]{};
|
||||||
|
double windowPos[4]{};
|
||||||
|
XPLMWorldToLocal(planePos.lat, planePos.lon, planePos.elevation * metersPerFt, &worldPos[0], &worldPos[1], &worldPos[2]);
|
||||||
|
matrixMultVec(localPos, worldMat.data(), worldPos);
|
||||||
|
matrixMultVec(windowPos, projMat.data(), localPos);
|
||||||
|
|
||||||
|
windowPos[3] = 1.0 / windowPos[3];
|
||||||
|
windowPos[0] *= windowPos[3];
|
||||||
|
windowPos[1] *= windowPos[3];
|
||||||
|
windowPos[2] *= windowPos[3];
|
||||||
|
|
||||||
|
if (windowPos[2] < 0.0 || windowPos[2] > 1.0)
|
||||||
|
{
|
||||||
|
continue; // plane is behind camera
|
||||||
|
}
|
||||||
|
XPLMDrawString(color,
|
||||||
|
static_cast<int>(std::lround(windowWidth * (windowPos[0] * 0.5 + 0.5))),
|
||||||
|
static_cast<int>(std::lround(windowHeight * (windowPos[1] * 0.5 + 0.5))),
|
||||||
|
text, nullptr, xplmFont_Basic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTraffic::Labels::matrixMultVec(double out[4], const float m[16], const double v[4])
|
||||||
|
{
|
||||||
|
out[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12];
|
||||||
|
out[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13];
|
||||||
|
out[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
|
||||||
|
out[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15];
|
||||||
|
}
|
||||||
|
|
||||||
int CTraffic::orbitPlaneFunc(XPLMCameraPosition_t *cameraPosition, int isLosingControl, void *refcon)
|
int CTraffic::orbitPlaneFunc(XPLMCameraPosition_t *cameraPosition, int isLosingControl, void *refcon)
|
||||||
{
|
{
|
||||||
constexpr bool DEBUG = false;
|
constexpr bool DEBUG = false;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "datarefs.h"
|
#include "datarefs.h"
|
||||||
#include "terrainprobe.h"
|
#include "terrainprobe.h"
|
||||||
|
#include "drawable.h"
|
||||||
#include "menus.h"
|
#include "menus.h"
|
||||||
#include "XPMPMultiplayer.h"
|
#include "XPMPMultiplayer.h"
|
||||||
#include <XPLM/XPLMCamera.h>
|
#include <XPLM/XPLMCamera.h>
|
||||||
@@ -74,6 +75,12 @@ namespace XSwiftBus
|
|||||||
//! Set the ICAO code to use for aircraft without a model match
|
//! Set the ICAO code to use for aircraft without a model match
|
||||||
void setDefaultIcao(const std::string &defaultIcao);
|
void setDefaultIcao(const std::string &defaultIcao);
|
||||||
|
|
||||||
|
//! Set whether the plugin draws type and callsign labels above aircraft
|
||||||
|
void setDrawingLabels(bool drawing);
|
||||||
|
|
||||||
|
//! Get whether the plugin draws type and callsign labels above aircraft
|
||||||
|
bool isDrawingLabels() const;
|
||||||
|
|
||||||
//! Set the maximum number of aircraft.
|
//! Set the maximum number of aircraft.
|
||||||
void setMaxPlanes(int planes);
|
void setMaxPlanes(int planes);
|
||||||
|
|
||||||
@@ -182,6 +189,24 @@ namespace XSwiftBus
|
|||||||
const std::string &livery_, const std::string &modelName_);
|
const std::string &livery_, const std::string &modelName_);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Label renderer
|
||||||
|
class Labels : public CDrawable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Labels(CTraffic *traffic) : CDrawable(xplm_Phase_Window, false), m_traffic(traffic) {}
|
||||||
|
protected:
|
||||||
|
virtual void draw() override;
|
||||||
|
private:
|
||||||
|
static void matrixMultVec(double out[4], const float m[16], const double v[4]);
|
||||||
|
CTraffic *m_traffic = nullptr;
|
||||||
|
ArrayDataRef<xplane::data::sim::graphics::view::world_matrix> m_worldMat;
|
||||||
|
ArrayDataRef<xplane::data::sim::graphics::view::projection_matrix_3d> m_projMat;
|
||||||
|
DataRef<xplane::data::sim::graphics::view::window_width> m_windowWidth;
|
||||||
|
DataRef<xplane::data::sim::graphics::view::window_height> m_windowHeight;
|
||||||
|
DataRef<xplane::data::sim::graphics::view::visibility_effective_m> m_visibilityM;
|
||||||
|
};
|
||||||
|
Labels m_labels { this };
|
||||||
|
|
||||||
//! Check functions
|
//! Check functions
|
||||||
//! @{
|
//! @{
|
||||||
static bool isPlusMinus180(float v);
|
static bool isPlusMinus180(float v);
|
||||||
@@ -220,7 +245,6 @@ namespace XSwiftBus
|
|||||||
CCommand m_followPlaneViewNextCommand;
|
CCommand m_followPlaneViewNextCommand;
|
||||||
CCommand m_followPlaneViewPreviousCommand;
|
CCommand m_followPlaneViewPreviousCommand;
|
||||||
|
|
||||||
DataRef<xplane::data::sim::graphics::view::world_render_type> m_worldRenderType;
|
|
||||||
DataRef<xplane::data::sim::flightmodel::position::local_x> m_ownAircraftPositionX;
|
DataRef<xplane::data::sim::flightmodel::position::local_x> m_ownAircraftPositionX;
|
||||||
DataRef<xplane::data::sim::flightmodel::position::local_y> m_ownAircraftPositionY;
|
DataRef<xplane::data::sim::flightmodel::position::local_y> m_ownAircraftPositionY;
|
||||||
DataRef<xplane::data::sim::flightmodel::position::local_z> m_ownAircraftPositionZ;
|
DataRef<xplane::data::sim::flightmodel::position::local_z> m_ownAircraftPositionZ;
|
||||||
|
|||||||
Reference in New Issue
Block a user