mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-20 12:35:43 +08:00
refs #271 CSimulatorXPlane sends text messages to XBus and they are displayed in X-Plane.
This commit is contained in:
@@ -266,19 +266,38 @@ namespace BlackSimPlugin
|
|||||||
|
|
||||||
void CSimulatorXPlane::displayStatusMessage(const BlackMisc::CStatusMessage &message) const
|
void CSimulatorXPlane::displayStatusMessage(const BlackMisc::CStatusMessage &message) const
|
||||||
{
|
{
|
||||||
|
// avoid infinite recursion in case this function is called due to a message caused by this very function
|
||||||
|
static bool isInFunction = false;
|
||||||
|
if (isInFunction) { return; }
|
||||||
|
isInFunction = true;
|
||||||
|
|
||||||
/* We do not assert here as status message may come because of network problems */
|
/* We do not assert here as status message may come because of network problems */
|
||||||
if (!isConnected()) { return; }
|
if (!isConnected()) { return; }
|
||||||
|
|
||||||
//! \todo XP driver, display text message: XPLMSpeakString()? http://www.xsquawkbox.net/xpsdk/mediawiki/XPLMSpeakString
|
QColor color;
|
||||||
Q_UNUSED(message);
|
switch (message.getSeverity())
|
||||||
|
{
|
||||||
|
case CStatusMessage::SeverityDebug: color = "teal"; break;
|
||||||
|
case CStatusMessage::SeverityInfo: color = "cyan"; break;
|
||||||
|
case CStatusMessage::SeverityWarning: color = "orange"; break;
|
||||||
|
case CStatusMessage::SeverityError: color = "red"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_service->addTextMessage("swift: " + message.getMessage(), color.redF(), color.greenF(), color.blueF());
|
||||||
|
isInFunction = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSimulatorXPlane::displayTextMessage(const BlackMisc::Network::CTextMessage &message) const
|
void CSimulatorXPlane::displayTextMessage(const BlackMisc::Network::CTextMessage &message) const
|
||||||
{
|
{
|
||||||
if (!isConnected()) { return; }
|
if (!isConnected()) { return; }
|
||||||
|
|
||||||
//! \todo XP driver, display text message: XPLMSpeakString()? http://www.xsquawkbox.net/xpsdk/mediawiki/XPLMSpeakString
|
QColor color;
|
||||||
Q_UNUSED(message);
|
if (message.isServerMessage()) { color = "orchid"; }
|
||||||
|
else if (message.isSupervisorMessage()) { color = "yellow"; }
|
||||||
|
else if (message.isPrivateMessage()) { color = "magenta"; }
|
||||||
|
else { color = "lime"; }
|
||||||
|
|
||||||
|
m_service->addTextMessage(message.getSenderCallsign().toQString() + ": " + message.getMessage(), color.redF(), color.greenF(), color.blueF());
|
||||||
}
|
}
|
||||||
|
|
||||||
CAircraftModelList CSimulatorXPlane::getInstalledModels() const
|
CAircraftModelList CSimulatorXPlane::getInstalledModels() const
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ namespace BlackSimPlugin
|
|||||||
if (! dummy) { m_dbusInterface->relayParentSignals(); }
|
if (! dummy) { m_dbusInterface->relayParentSignals(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CXBusServiceProxy::addTextMessage(const QString &text, double red, double green, double blue)
|
||||||
|
{
|
||||||
|
m_dbusInterface->callDBus(QLatin1String("addTextMessage"), text, red, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
void CXBusServiceProxy::updateAirportsInRange()
|
void CXBusServiceProxy::updateAirportsInRange()
|
||||||
{
|
{
|
||||||
m_dbusInterface->callDBus(QLatin1String("updateAirportsInRange"));
|
m_dbusInterface->callDBus(QLatin1String("updateAirportsInRange"));
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ namespace BlackSimPlugin
|
|||||||
void airportsInRangeUpdated(const QStringList &icaoCodes, const QStringList &names, const QList<double> &lats, const QList<double> &lons, const QList<double> &alts);
|
void airportsInRangeUpdated(const QStringList &icaoCodes, const QStringList &names, const QList<double> &lats, const QList<double> &lons, const QList<double> &alts);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
//! \copydoc XBus::CService::addTextMessage
|
||||||
|
void addTextMessage(const QString &text, double red, double green, double blue);
|
||||||
|
|
||||||
//! \copydoc XBus::CService::updateAirportsInRange
|
//! \copydoc XBus::CService::updateAirportsInRange
|
||||||
void updateAirportsInRange();
|
void updateAirportsInRange();
|
||||||
|
|
||||||
|
|||||||
141
src/xbus/messages.cpp
Normal file
141
src/xbus/messages.cpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/* Copyright (C) 2015
|
||||||
|
* swift project Community / Contributors
|
||||||
|
*
|
||||||
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||||
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||||
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||||
|
* contained in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NOMINMAX
|
||||||
|
#define NOMINMAX
|
||||||
|
#endif
|
||||||
|
#include "messages.h"
|
||||||
|
#include <XPLMGraphics.h>
|
||||||
|
#include <XPUIGraphics.h>
|
||||||
|
|
||||||
|
namespace XBus
|
||||||
|
{
|
||||||
|
|
||||||
|
const int c_screenWidth = 1024;
|
||||||
|
const int c_screenHeight = 768;
|
||||||
|
const int c_boxLeft = 128;
|
||||||
|
const int c_boxTop = c_screenHeight - 16;
|
||||||
|
const int c_boxRight = c_screenWidth - 128;
|
||||||
|
|
||||||
|
void CMessageBox::draw()
|
||||||
|
{
|
||||||
|
static int lineHeight = 0;
|
||||||
|
if (! lineHeight)
|
||||||
|
{
|
||||||
|
XPLMGetFontDimensions(xplmFont_Basic, nullptr, &lineHeight, nullptr);
|
||||||
|
}
|
||||||
|
static const int lineSpace = lineHeight / 3;
|
||||||
|
const int boxBottom = c_boxTop - lineSpace * 2 - (lineHeight + lineSpace) * m_messages.size();
|
||||||
|
XPLMDrawTranslucentDarkBox(c_boxLeft, c_boxTop, c_boxRight, boxBottom);
|
||||||
|
|
||||||
|
static int arrowWidth = 0, arrowHeight = 0;
|
||||||
|
if (! arrowHeight)
|
||||||
|
{
|
||||||
|
XPGetElementDefaultDimensions(xpElement_LittleUpArrow, &arrowWidth, &arrowHeight, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int x = c_boxLeft + lineSpace;
|
||||||
|
if (m_upArrow)
|
||||||
|
{
|
||||||
|
const int y = c_boxTop - lineSpace - arrowHeight;
|
||||||
|
XPDrawElement(x, y, x + arrowWidth, y + arrowHeight, xpElement_LittleUpArrow, 0);
|
||||||
|
}
|
||||||
|
if (m_downArrow)
|
||||||
|
{
|
||||||
|
const int y = c_boxTop - (lineHeight + lineSpace) * m_messages.size();
|
||||||
|
XPDrawElement(x, y, x + arrowWidth, y + arrowHeight, xpElement_LittleDownArrow, 0);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < m_messages.size(); ++i)
|
||||||
|
{
|
||||||
|
const int y = c_boxTop - (lineHeight + lineSpace) * (i + 1);
|
||||||
|
XPLMDrawString(m_messages[i].m_rgb.data(), x + arrowWidth + arrowWidth / 2, y, const_cast<char*>(m_messages[i].m_text.c_str()), nullptr, xplmFont_Basic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CMessageBox::maxLineLength() const
|
||||||
|
{
|
||||||
|
static int len = 0;
|
||||||
|
if (! len)
|
||||||
|
{
|
||||||
|
int charWidth;
|
||||||
|
XPLMGetFontDimensions(xplmFont_Basic, &charWidth, nullptr, nullptr);
|
||||||
|
len = (c_boxRight - c_boxLeft - 20) / charWidth;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMessageBoxControl::CMessageBoxControl() :
|
||||||
|
m_showCommand("org/swift-project/xbus/show_messages", "Show XBus text messages", [this] { show(); }),
|
||||||
|
m_hideCommand("org/swift-project/xbus/hide_messages", "Hide XBus text messages", [this] { hide(); }),
|
||||||
|
m_toggleCommand("org/swift-project/xbus/toggle_messages", "Toggle XBus text messages", [this] { toggle(); }),
|
||||||
|
m_scrollUpCommand("org/swift-project/xbus/scroll_up", "Scroll up XBus text messages", [this] { scrollUp(); }),
|
||||||
|
m_scrollDownCommand("org/swift-project/xbus/scroll_down", "Scroll down XBus text messages", [this] { scrollDown(); }),
|
||||||
|
m_scrollToTopCommand("org/swift-project/xbus/scroll_top", "Scroll to top of XBus text messages", [this] { scrollToTop(); }),
|
||||||
|
m_scrollToBottomCommand("org/swift-project/xbus/scroll_bottom", "Scroll to bottom of XBus text messages", [this] { scrollToBottom(); }),
|
||||||
|
m_debugCommand("org/swift-project/xbus/debug", "", [this] { static int c = 0; this->addMessage({ "hello " + std::to_string(c++), 0, .75, 0 }); })
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CMessageBoxControl::addMessage(const CMessage &message)
|
||||||
|
{
|
||||||
|
if (m_messages.size() >= c_maxTotalLines) { m_messages.erase(m_messages.begin()); }
|
||||||
|
m_messages.push_back(message);
|
||||||
|
if (m_position + 1 >= m_messages.size() || ! m_visible)
|
||||||
|
{
|
||||||
|
show();
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMessageBoxControl::scrollUp()
|
||||||
|
{
|
||||||
|
if (! m_visible) { return; }
|
||||||
|
|
||||||
|
if (m_position - 1 >= std::min(m_messages.size(), c_maxVisibleLines))
|
||||||
|
{
|
||||||
|
m_position--;
|
||||||
|
}
|
||||||
|
updateVisibleLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMessageBoxControl::scrollDown()
|
||||||
|
{
|
||||||
|
if (! m_visible) { return; }
|
||||||
|
|
||||||
|
if (m_position + 1 <= m_messages.size())
|
||||||
|
{
|
||||||
|
m_position++;
|
||||||
|
}
|
||||||
|
updateVisibleLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMessageBoxControl::scrollToTop()
|
||||||
|
{
|
||||||
|
if (! m_visible) { return; }
|
||||||
|
|
||||||
|
m_position = std::min(m_messages.size(), c_maxVisibleLines);
|
||||||
|
updateVisibleLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMessageBoxControl::scrollToBottom()
|
||||||
|
{
|
||||||
|
if (! m_visible) { return; }
|
||||||
|
|
||||||
|
m_position = m_messages.size();
|
||||||
|
updateVisibleLines();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMessageBoxControl::updateVisibleLines()
|
||||||
|
{
|
||||||
|
const size_t lines = std::min(m_messages.size(), c_maxVisibleLines);
|
||||||
|
const auto end = m_messages.cbegin() + m_position;
|
||||||
|
m_messageBox.setMessages(end - lines, end);
|
||||||
|
m_messageBox.enableArrows(m_position > lines, m_position < m_messages.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
124
src/xbus/messages.h
Normal file
124
src/xbus/messages.h
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/* Copyright (C) 2015
|
||||||
|
* swift project Community / Contributors
|
||||||
|
*
|
||||||
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
||||||
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
||||||
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
||||||
|
* contained in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLACKSIM_XBUS_MESSAGES_H
|
||||||
|
#define BLACKSIM_XBUS_MESSAGES_H
|
||||||
|
|
||||||
|
//! \file
|
||||||
|
|
||||||
|
#include "drawable.h"
|
||||||
|
#include "command.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <array>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace XBus
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Class representing a single line of text to be drawn in a message box.
|
||||||
|
*/
|
||||||
|
struct CMessage
|
||||||
|
{
|
||||||
|
//! Constructor.
|
||||||
|
CMessage(const std::string &text, float r, float g, float b) : m_text(text)
|
||||||
|
{
|
||||||
|
// MSVC initializer list bug
|
||||||
|
std::tie(m_rgb[0], m_rgb[1], m_rgb[2]) = std::tie(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Text.
|
||||||
|
std::string m_text;
|
||||||
|
|
||||||
|
//! Color.
|
||||||
|
std::array<float, 3> m_rgb;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Class for drawing a gray box with text messages.
|
||||||
|
*/
|
||||||
|
class CMessageBox : public CDrawable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Constructor.
|
||||||
|
CMessageBox() : CDrawable(xplm_Phase_Window, true) {}
|
||||||
|
|
||||||
|
//! Set messages to draw in message box, from a pair of iterators.
|
||||||
|
template <typename Iterator>
|
||||||
|
void setMessages(Iterator begin, Iterator end)
|
||||||
|
{
|
||||||
|
m_messages.clear();
|
||||||
|
std::copy(begin, end, std::back_inserter(m_messages));
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Set whether to draw a small arrow at the bottom of the box.
|
||||||
|
void enableArrows(bool up, bool down)
|
||||||
|
{
|
||||||
|
m_upArrow = up;
|
||||||
|
m_downArrow = down;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns the maximum number of characters per line.
|
||||||
|
int maxLineLength() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void draw() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<CMessage> m_messages;
|
||||||
|
bool m_upArrow = false;
|
||||||
|
bool m_downArrow = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Class which builds upon CMessageBox with a scrollback buffer and commands for user control.
|
||||||
|
*/
|
||||||
|
class CMessageBoxControl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Constructor.
|
||||||
|
CMessageBoxControl();
|
||||||
|
|
||||||
|
//! Add a new message to the bottom of the list.
|
||||||
|
void addMessage(const CMessage &message);
|
||||||
|
|
||||||
|
//! \copydoc XBus::CMessageBox::maxLineLength
|
||||||
|
int maxLineLength() const { return m_messageBox.maxLineLength(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void show() { m_messageBox.show(); m_visible = true; }
|
||||||
|
void hide() { m_messageBox.hide(); m_visible = false; }
|
||||||
|
void toggle() { if (m_visible) { hide(); } else { show(); } }
|
||||||
|
void scrollUp();
|
||||||
|
void scrollDown();
|
||||||
|
void scrollToTop();
|
||||||
|
void scrollToBottom();
|
||||||
|
void updateVisibleLines();
|
||||||
|
|
||||||
|
bool m_visible = false;
|
||||||
|
std::vector<CMessage> m_messages;
|
||||||
|
size_t m_position = 0;
|
||||||
|
const size_t c_maxVisibleLines = 8;
|
||||||
|
const size_t c_maxTotalLines = 1024;
|
||||||
|
CMessageBox m_messageBox;
|
||||||
|
|
||||||
|
CCommand m_showCommand;
|
||||||
|
CCommand m_hideCommand;
|
||||||
|
CCommand m_toggleCommand;
|
||||||
|
CCommand m_scrollUpCommand;
|
||||||
|
CCommand m_scrollDownCommand;
|
||||||
|
CCommand m_scrollToTopCommand;
|
||||||
|
CCommand m_scrollToBottomCommand;
|
||||||
|
CCommand m_debugCommand;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -28,6 +28,30 @@ namespace XBus
|
|||||||
emit aircraftModelChanged(path, filename, getAircraftLivery(), getAircraftIcaoCode());
|
emit aircraftModelChanged(path, filename, getAircraftLivery(), getAircraftIcaoCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CService::addTextMessage(const QString &text, double red, double green, double blue)
|
||||||
|
{
|
||||||
|
if (text.isEmpty()) { return; }
|
||||||
|
int lineLength = m_messages.maxLineLength() - 1;
|
||||||
|
QStringList wrappedLines;
|
||||||
|
for (int i = 0; i < text.size(); i += lineLength)
|
||||||
|
{
|
||||||
|
static const QChar ellipsis = 0x2026;
|
||||||
|
wrappedLines.push_back(text.mid(i, lineLength) + ellipsis);
|
||||||
|
}
|
||||||
|
wrappedLines.back().chop(1);
|
||||||
|
if (wrappedLines.back().isEmpty()) { wrappedLines.pop_back(); }
|
||||||
|
else if (wrappedLines.back().size() == 1 && wrappedLines.size() > 1)
|
||||||
|
{
|
||||||
|
(wrappedLines.end() - 2)->chop(1);
|
||||||
|
(wrappedLines.end() - 2)->append(wrappedLines.back());
|
||||||
|
wrappedLines.pop_back();
|
||||||
|
}
|
||||||
|
for (const auto &line : wrappedLines)
|
||||||
|
{
|
||||||
|
m_messages.addMessage({ line.toStdString(), static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString CService::getAircraftModelPath() const
|
QString CService::getAircraftModelPath() const
|
||||||
{
|
{
|
||||||
char filename[256];
|
char filename[256];
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#endif
|
#endif
|
||||||
#include "datarefs.h"
|
#include "datarefs.h"
|
||||||
|
#include "messages.h"
|
||||||
#include "blackmisc/geo/geodesicgrid.h"
|
#include "blackmisc/geo/geodesicgrid.h"
|
||||||
#include <XPLM/XPLMNavigation.h>
|
#include <XPLM/XPLMNavigation.h>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@@ -71,6 +72,9 @@ namespace XBus
|
|||||||
void airportsInRangeUpdated(const QStringList &icaoCodes, const QStringList &names, const QDoubleList &lats, const QDoubleList &lons, const QDoubleList &alts);
|
void airportsInRangeUpdated(const QStringList &icaoCodes, const QStringList &names, const QDoubleList &lats, const QDoubleList &lons, const QDoubleList &alts);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
//! Add a text message to the on-screen display, with RGB components in the range [0,1]
|
||||||
|
void addTextMessage(const QString &text, double red, double green, double blue);
|
||||||
|
|
||||||
//! Called by newly connected client to cause airportsInRangeUpdated to be emitted.
|
//! Called by newly connected client to cause airportsInRangeUpdated to be emitted.
|
||||||
void updateAirportsInRange();
|
void updateAirportsInRange();
|
||||||
|
|
||||||
@@ -217,6 +221,7 @@ namespace XBus
|
|||||||
double getSpeedBrakeRatio() const { return m_speedBrakeRatio.get(); }
|
double getSpeedBrakeRatio() const { return m_speedBrakeRatio.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CMessageBoxControl m_messages;
|
||||||
BlackMisc::Geo::CGeodesicGrid<128, XPLMNavRef> m_airports;
|
BlackMisc::Geo::CGeodesicGrid<128, XPLMNavRef> m_airports;
|
||||||
QTimer *m_airportUpdater = nullptr;
|
QTimer *m_airportUpdater = nullptr;
|
||||||
void readAirportsDatabase();
|
void readAirportsDatabase();
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ CONFIG += shared plugin
|
|||||||
CONFIG += blackmisc blackcore
|
CONFIG += blackmisc blackcore
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
equals(WORD_SIZE,64): LIBS += -lXPLM_64
|
equals(WORD_SIZE,64): LIBS += -lXPLM_64 -lXPWidgets_64
|
||||||
equals(WORD_SIZE,32): LIBS += -lXPLM
|
equals(WORD_SIZE,32): LIBS += -lXPLM -lXPWidgets
|
||||||
}
|
}
|
||||||
else:macx {
|
else:macx {
|
||||||
LIBS += -framework XPLM -framework Cocoa -framework CoreFoundation
|
LIBS += -framework XPLM -framework XPWidgets \
|
||||||
|
-framework Cocoa -framework CoreFoundation
|
||||||
DEFINES += XUTILS_EXCLUDE_MAC_CRAP=1
|
DEFINES += XUTILS_EXCLUDE_MAC_CRAP=1
|
||||||
}
|
}
|
||||||
else:unix {
|
else:unix {
|
||||||
|
|||||||
Reference in New Issue
Block a user