From 8fef837de34f002dd8c4ad4eb6b72bc8509b5c1d Mon Sep 17 00:00:00 2001 From: Misaki Date: Mon, 6 Jul 2026 19:43:59 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=BB=A5Debug?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E6=97=B6=E6=98=BE=E7=A4=BA=E5=AE=9E=E6=97=B6?= =?UTF-8?q?FPS=E4=BF=A1=E6=81=AF=E6=98=BE=E7=A4=BA=EF=BC=8C=E5=9C=A8?= =?UTF-8?q?=E5=B5=8C=E5=85=A5=E5=BC=8FLinux=E4=B8=8A=E4=B8=8D=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9A=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E4=BB=A5img=E7=9A=84=E6=96=B9=E5=BC=8F=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=EF=BC=8C=E9=98=B2=E6=AD=A2=E5=9B=A0=E4=B8=BAQt=E4=BA=A4?= =?UTF-8?q?=E5=8F=89=E7=BC=96=E8=AF=91=E7=AD=89=E5=8E=9F=E5=9B=A0=E4=BA=A7?= =?UTF-8?q?=E7=94=9F=E7=9A=84=E6=89=BE=E4=B8=8D=E5=88=B0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E5=AD=97=E4=BD=93=E4=B9=8B=E7=B1=BB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/Inc/GLCore.h | 2 +- src/Core/Src/GLCore.cpp | 12 ++- src/UI/Widgets/Inc/FpsOverlay.hpp | 20 ++--- src/UI/Widgets/Src/FpsOverlay.cpp | 145 ++++++++++++++++++++++-------- 4 files changed, 127 insertions(+), 52 deletions(-) diff --git a/src/Core/Inc/GLCore.h b/src/Core/Inc/GLCore.h index 63319cc..7a996d0 100644 --- a/src/Core/Inc/GLCore.h +++ b/src/Core/Inc/GLCore.h @@ -95,7 +95,7 @@ private: PttButton *pttButton; /// 嵌入式平台PTT按钮 #endif #ifdef YOSUGA_DEBUG - FpsOverlay fpsOverlay; /// 调试用FPS显示 + FpsOverlay *fpsOverlay = nullptr; /// 调试用FPS显示 #endif bool isLeftPressed; /// 鼠标左键是否按下 diff --git a/src/Core/Src/GLCore.cpp b/src/Core/Src/GLCore.cpp index 29a8fde..fac26cf 100644 --- a/src/Core/Src/GLCore.cpp +++ b/src/Core/Src/GLCore.cpp @@ -87,6 +87,10 @@ GLCore::GLCore(const int width, const int height, QWidget *parent) // 启用鼠标跟踪,不启用的话鼠标按下才会回调mouseMoveEvent函数 this->setMouseTracking(true); +#ifdef YOSUGA_DEBUG + fpsOverlay = new FpsOverlay(this); +#endif + // 连接一些必要的信号与槽 #ifndef EMBEDDED_LINUX // 如果不是嵌入式Linux系统(注意如果你的嵌入式Linux平台启用了桌面系统,那么可能需要去掉这个条件宏) connect(contextMenu, &Menu::closeMainWindow, this, &GLCore::closeGL); // 关闭窗口信号 @@ -330,7 +334,7 @@ void GLCore::initializeGL() } #ifndef EMBEDDED_LINUX - // 初始化GLEW 必须在任何Live2D渲染操作之前调用 + // 由于加入了对嵌入式平台的支持,因此桌面平台需要手动初始化GLEW 必须在任何Live2D渲染操作之前调用 // Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等), // 未调用glewInit()会导致空指针解引用SIGSEGV glewExperimental = GL_TRUE; @@ -356,8 +360,7 @@ void GLCore::paintGL() TextRenderer::getInstance()->update(); TextRenderer::getInstance()->render(); #ifdef YOSUGA_DEBUG - fpsOverlay.tick(); - fpsOverlay.draw(width(), height()); + fpsOverlay->tick(); #endif } @@ -371,6 +374,9 @@ void GLCore::resizeGL(const int w, const int h) #ifdef EMBEDDED_LINUX pttButton->updateLayout(w, h); #endif +#ifdef YOSUGA_DEBUG + if (fpsOverlay) fpsOverlay->renderToPixmap(); // 窗口大小变化时重算位置 +#endif } // 设置窗口大小,并触发 resizeGL 事件 diff --git a/src/UI/Widgets/Inc/FpsOverlay.hpp b/src/UI/Widgets/Inc/FpsOverlay.hpp index 6907fcb..d5ede48 100644 --- a/src/UI/Widgets/Inc/FpsOverlay.hpp +++ b/src/UI/Widgets/Inc/FpsOverlay.hpp @@ -1,33 +1,33 @@ #pragma once - #ifdef YOSUGA_DEBUG -#include -#include +#include class QTimer; +class QElapsedTimer; -class FpsOverlay +class FpsOverlay : public QLabel { + Q_OBJECT public: - FpsOverlay(); + explicit FpsOverlay(QWidget* parent = nullptr); ~FpsOverlay(); void tick(); - void draw(int parentWidth, int parentHeight); + void renderToPixmap(); // 离线渲染文字到 pixmap + float rightMargin = 0.03f; float topMargin = 0.03f; - int fontSize = 20; + int fontSize = 18; private: - QElapsedTimer _elapsed; QTimer* _timer = nullptr; + QElapsedTimer* _elapsed = nullptr; int _frameCount = 0; int _displayedFps = 0; - QString _text = "FPS: --"; void recalcFps(); }; -#endif +#endif \ No newline at end of file diff --git a/src/UI/Widgets/Src/FpsOverlay.cpp b/src/UI/Widgets/Src/FpsOverlay.cpp index 71aa0bc..c26070c 100644 --- a/src/UI/Widgets/Src/FpsOverlay.cpp +++ b/src/UI/Widgets/Src/FpsOverlay.cpp @@ -1,22 +1,78 @@ #ifdef YOSUGA_DEBUG #include "FpsOverlay.hpp" -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include -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); - QObject::connect(_timer, &QTimer::timeout, [this]() { recalcFps(); }); + connect(_timer, &QTimer::timeout, this, &FpsOverlay::recalcFps); _timer->start(1000); - _elapsed.start(); } FpsOverlay::~FpsOverlay() { - delete _timer; + delete _elapsed; } void FpsOverlay::tick() @@ -24,48 +80,61 @@ void FpsOverlay::tick() ++_frameCount; } -void FpsOverlay::draw(int parentWidth, int parentHeight) +void FpsOverlay::renderToPixmap() { - QOpenGLPaintDevice device(QSize(parentWidth, parentHeight)); - QPainter painter(&device); - painter.setRenderHint(QPainter::Antialiasing); + QString text = QString("FPS: %1").arg(_displayedFps); - QFont f; - f.setPixelSize(fontSize); - f.setBold(true); - f.setStyleHint(QFont::Monospace); + // 计算尺寸 + QFontMetrics fm(font()); + const int padX = 12; + 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; - const int textW = fm.horizontalAdvance(_text) + pad * 2; - const int textH = fm.height() + pad; - const int x = parentWidth - textW - static_cast(parentWidth * rightMargin); - const int y = static_cast(parentHeight * topMargin); + // 父窗口大小决定位置 + int parentW = parentWidget() ? parentWidget()->width() : 1080; + int parentH = parentWidget() ? parentWidget()->height() : 1920; + const int x = parentW - w - static_cast(parentW * rightMargin); + const int y = static_cast(parentH * topMargin); - painter.setBrush(QColor(0, 0, 0, 180)); - painter.setPen(Qt::NoPen); - painter.drawRoundedRect(x, y, textW, textH, 4, 4); + // 设置几何位置 + setGeometry(x, y, w, h); - painter.setFont(f); - 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); - painter.setPen(fg); - painter.drawText(QRect(x + pad, y, textW - pad * 2, textH), - Qt::AlignVCenter | Qt::AlignLeft, _text); + // 用 QImage 离线渲染,不依赖 QLabel 的字体系统 + QImage img(w, h, QImage::Format_ARGB32); + img.fill(Qt::transparent); // 透明 + + QPainter p(&img); + p.setRenderHint(QPainter::Antialiasing); + + // 文字颜色:根据 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() { - const qint64 ms = _elapsed.elapsed(); + const qint64 ms = _elapsed->elapsed(); if (ms == 0) return; _displayedFps = static_cast(_frameCount * 1000.0 / ms); - _frameCount = 0; - _elapsed.restart(); + _frameCount = 0; + _elapsed->restart(); - _text = QString("FPS: %1").arg(_displayedFps); - fprintf(stderr, "[FPS] %s\n", _text.toUtf8().constData()); + // fprintf(stderr, "[FPS] %d\n", _displayedFps); + + // 重新渲染为 pixmap + renderToPixmap(); } -#endif + +#endif \ No newline at end of file