1. 修复了以Debug编译时显示实时FPS信息显示,在嵌入式Linux上不显示的问题:直接以img的方式显示,防止因为Qt交叉编译等原因产生的找不到系统字体之类的问题

This commit is contained in:
Misaki
2026-07-06 19:43:59 +08:00
parent 6b8983bc6d
commit 8fef837de3
4 changed files with 127 additions and 52 deletions
+1 -1
View File
@@ -95,7 +95,7 @@ private:
PttButton *pttButton; /// 嵌入式平台PTT按钮 PttButton *pttButton; /// 嵌入式平台PTT按钮
#endif #endif
#ifdef YOSUGA_DEBUG #ifdef YOSUGA_DEBUG
FpsOverlay fpsOverlay; /// 调试用FPS显示 FpsOverlay *fpsOverlay = nullptr; /// 调试用FPS显示
#endif #endif
bool isLeftPressed; /// 鼠标左键是否按下 bool isLeftPressed; /// 鼠标左键是否按下
+9 -3
View File
@@ -87,6 +87,10 @@ GLCore::GLCore(const int width, const int height, QWidget *parent)
// 启用鼠标跟踪,不启用的话鼠标按下才会回调mouseMoveEvent函数 // 启用鼠标跟踪,不启用的话鼠标按下才会回调mouseMoveEvent函数
this->setMouseTracking(true); this->setMouseTracking(true);
#ifdef YOSUGA_DEBUG
fpsOverlay = new FpsOverlay(this);
#endif
// 连接一些必要的信号与槽 // 连接一些必要的信号与槽
#ifndef EMBEDDED_LINUX // 如果不是嵌入式Linux系统(注意如果你的嵌入式Linux平台启用了桌面系统,那么可能需要去掉这个条件宏) #ifndef EMBEDDED_LINUX // 如果不是嵌入式Linux系统(注意如果你的嵌入式Linux平台启用了桌面系统,那么可能需要去掉这个条件宏)
connect(contextMenu, &Menu::closeMainWindow, this, &GLCore::closeGL); // 关闭窗口信号 connect(contextMenu, &Menu::closeMainWindow, this, &GLCore::closeGL); // 关闭窗口信号
@@ -330,7 +334,7 @@ void GLCore::initializeGL()
} }
#ifndef EMBEDDED_LINUX #ifndef EMBEDDED_LINUX
// 初始化GLEW 必须在任何Live2D渲染操作之前调用 // 由于加入了对嵌入式平台的支持,因此桌面平台需要手动初始化GLEW 必须在任何Live2D渲染操作之前调用
// Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等), // Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等),
// 未调用glewInit()会导致空指针解引用SIGSEGV // 未调用glewInit()会导致空指针解引用SIGSEGV
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
@@ -356,8 +360,7 @@ void GLCore::paintGL()
TextRenderer::getInstance()->update(); TextRenderer::getInstance()->update();
TextRenderer::getInstance()->render(); TextRenderer::getInstance()->render();
#ifdef YOSUGA_DEBUG #ifdef YOSUGA_DEBUG
fpsOverlay.tick(); fpsOverlay->tick();
fpsOverlay.draw(width(), height());
#endif #endif
} }
@@ -371,6 +374,9 @@ void GLCore::resizeGL(const int w, const int h)
#ifdef EMBEDDED_LINUX #ifdef EMBEDDED_LINUX
pttButton->updateLayout(w, h); pttButton->updateLayout(w, h);
#endif #endif
#ifdef YOSUGA_DEBUG
if (fpsOverlay) fpsOverlay->renderToPixmap(); // 窗口大小变化时重算位置
#endif
} }
// 设置窗口大小,并触发 resizeGL 事件 // 设置窗口大小,并触发 resizeGL 事件
+10 -10
View File
@@ -1,33 +1,33 @@
#pragma once #pragma once
#ifdef YOSUGA_DEBUG #ifdef YOSUGA_DEBUG
#include <QElapsedTimer> #include <QLabel>
#include <QString>
class QTimer; class QTimer;
class QElapsedTimer;
class FpsOverlay class FpsOverlay : public QLabel
{ {
Q_OBJECT
public: public:
FpsOverlay(); explicit FpsOverlay(QWidget* parent = nullptr);
~FpsOverlay(); ~FpsOverlay();
void tick(); void tick();
void draw(int parentWidth, int parentHeight); void renderToPixmap(); // 离线渲染文字到 pixmap
float rightMargin = 0.03f; float rightMargin = 0.03f;
float topMargin = 0.03f; float topMargin = 0.03f;
int fontSize = 20; int fontSize = 18;
private: private:
QElapsedTimer _elapsed;
QTimer* _timer = nullptr; QTimer* _timer = nullptr;
QElapsedTimer* _elapsed = nullptr;
int _frameCount = 0; int _frameCount = 0;
int _displayedFps = 0; int _displayedFps = 0;
QString _text = "FPS: --";
void recalcFps(); void recalcFps();
}; };
#endif #endif
+107 -38
View File
@@ -1,22 +1,78 @@
#ifdef YOSUGA_DEBUG #ifdef YOSUGA_DEBUG
#include "FpsOverlay.hpp" #include "FpsOverlay.hpp"
#include <QPainter>
#include <QOpenGLPaintDevice>
#include <QTimer> #include <QTimer>
#include <QElapsedTimer>
#include <QFont>
#include <QFontMetrics>
#include <QFontDatabase>
#include <QImage>
#include <QPainter>
#include <QPixmap>
#include <QFile>
#include <cstdio> #include <cstdio>
FpsOverlay::FpsOverlay() FpsOverlay::FpsOverlay(QWidget* parent)
: QLabel(parent)
{ {
_timer = new QTimer; setAttribute(Qt::WA_TransparentForMouseEvents);
setAlignment(Qt::AlignCenter);
raise();
show();
// 尝试加载系统字体
QStringList fontPaths = {
"/usr/share/fonts/noto/NotoSansCJK-Regular.ttc",
"/usr/share/fonts/noto/NotoSans-Regular.ttf",
"/usr/share/fonts/noto/NotoSansCJKsc-Regular.otf",
"/usr/share/fonts/TTF/DejaVuSans.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
};
bool loaded = false;
for (const QString& path : fontPaths) {
if (QFile::exists(path)) {
int id = QFontDatabase::addApplicationFont(path);
if (id != -1) {
QString family = QFontDatabase::applicationFontFamilies(id).first();
QFont f(family, fontSize);
f.setBold(true);
setFont(f);
fprintf(stderr, "[FpsOverlay] Loaded font: %s from %s\n",
family.toUtf8().constData(), path.toUtf8().constData());
loaded = true;
break;
} else {
fprintf(stderr, "[FpsOverlay] addApplicationFont failed: %s\n",
path.toUtf8().constData());
}
}
}
if (!loaded) {
// fallback:不指定字体族,用 Qt 默认
QFont f = font();
f.setPointSize(fontSize);
f.setBold(true);
setFont(f);
fprintf(stderr, "[FpsOverlay] WARNING: No font loaded, using default: %s\n",
font().family().toUtf8().constData());
}
// 先显示初始帧
_displayedFps = 0;
renderToPixmap();
_elapsed = new QElapsedTimer;
_elapsed->start();
_timer = new QTimer(this);
_timer->setTimerType(Qt::PreciseTimer); _timer->setTimerType(Qt::PreciseTimer);
QObject::connect(_timer, &QTimer::timeout, [this]() { recalcFps(); }); connect(_timer, &QTimer::timeout, this, &FpsOverlay::recalcFps);
_timer->start(1000); _timer->start(1000);
_elapsed.start();
} }
FpsOverlay::~FpsOverlay() FpsOverlay::~FpsOverlay()
{ {
delete _timer; delete _elapsed;
} }
void FpsOverlay::tick() void FpsOverlay::tick()
@@ -24,48 +80,61 @@ void FpsOverlay::tick()
++_frameCount; ++_frameCount;
} }
void FpsOverlay::draw(int parentWidth, int parentHeight) void FpsOverlay::renderToPixmap()
{ {
QOpenGLPaintDevice device(QSize(parentWidth, parentHeight)); QString text = QString("FPS: %1").arg(_displayedFps);
QPainter painter(&device);
painter.setRenderHint(QPainter::Antialiasing);
QFont f; // 计算尺寸
f.setPixelSize(fontSize); QFontMetrics fm(font());
f.setBold(true); const int padX = 12;
f.setStyleHint(QFont::Monospace); const int padY = 8;
const int textW = fm.horizontalAdvance(text);
const int textH = fm.height();
const int w = textW + padX * 2;
const int h = textH + padY * 2;
QFontMetrics fm(f); // 父窗口大小决定位置
const int pad = 8; int parentW = parentWidget() ? parentWidget()->width() : 1080;
const int textW = fm.horizontalAdvance(_text) + pad * 2; int parentH = parentWidget() ? parentWidget()->height() : 1920;
const int textH = fm.height() + pad; const int x = parentW - w - static_cast<int>(parentW * rightMargin);
const int x = parentWidth - textW - static_cast<int>(parentWidth * rightMargin); const int y = static_cast<int>(parentH * topMargin);
const int y = static_cast<int>(parentHeight * topMargin);
painter.setBrush(QColor(0, 0, 0, 180)); // 设置几何位置
painter.setPen(Qt::NoPen); setGeometry(x, y, w, h);
painter.drawRoundedRect(x, y, textW, textH, 4, 4);
painter.setFont(f); // 用 QImage 离线渲染,不依赖 QLabel 的字体系统
const QColor fg = _displayedFps <= 0 ? QColor(170, 170, 170) : QImage img(w, h, QImage::Format_ARGB32);
_displayedFps <= 30 ? QColor(255, 68, 68) : img.fill(Qt::transparent); // 透明
_displayedFps <= 45 ? QColor(255, 170, 0) :
QColor( 68, 255, 68); QPainter p(&img);
painter.setPen(fg); p.setRenderHint(QPainter::Antialiasing);
painter.drawText(QRect(x + pad, y, textW - pad * 2, textH),
Qt::AlignVCenter | Qt::AlignLeft, _text); // 文字颜色:根据 FPS 变色
const QColor fg = _displayedFps <= 0 ? QColor(170, 170, 170) :
_displayedFps <= 30 ? QColor(255, 68, 68) :
_displayedFps <= 45 ? QColor(255, 170, 0) :
QColor( 68, 255, 68);
p.setPen(fg);
p.setFont(font());
p.drawText(img.rect(), Qt::AlignCenter, text);
p.end();
setPixmap(QPixmap::fromImage(img));
} }
void FpsOverlay::recalcFps() void FpsOverlay::recalcFps()
{ {
const qint64 ms = _elapsed.elapsed(); const qint64 ms = _elapsed->elapsed();
if (ms == 0) return; if (ms == 0) return;
_displayedFps = static_cast<int>(_frameCount * 1000.0 / ms); _displayedFps = static_cast<int>(_frameCount * 1000.0 / ms);
_frameCount = 0; _frameCount = 0;
_elapsed.restart(); _elapsed->restart();
_text = QString("FPS: %1").arg(_displayedFps); // fprintf(stderr, "[FPS] %d\n", _displayedFps);
fprintf(stderr, "[FPS] %s\n", _text.toUtf8().constData());
// 重新渲染为 pixmap
renderToPixmap();
} }
#endif
#endif