1. 完善了对于不同平台的shader文件的处理
2. 新增了对红米5Plus的支持 3. 将嵌入式Linux平台的PTT按钮重构成了动态位置大小变化 4. 新增了以Debug编译时显示实时FPS信息显示,在桌面平台表现正常,在嵌入式Linux还存在问题
This commit is contained in:
+37
-8
@@ -10,13 +10,17 @@ set(CMAKE_AUTOUIC ON)
|
||||
if(DEFINED TARGET_ARCH AND TARGET_ARCH STREQUAL "arm64")
|
||||
set(PLAT "linux_arm")
|
||||
set(ARCH "arm64")
|
||||
set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3")
|
||||
if(NOT DEFINED CMAKE_PREFIX_PATH) # 优先使用外部传入的变量值
|
||||
set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3")
|
||||
endif()
|
||||
add_definitions(-DCSM_TARGET_HARMONYOS_ES3) # OpenGL ES 3.0 渲染宏
|
||||
add_definitions(-DEMBEDDED_LINUX) # 嵌入式Linux专用宏
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
|
||||
set(PLAT "linux_arm")
|
||||
set(ARCH "arm64")
|
||||
set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3")
|
||||
if(NOT DEFINED CMAKE_PREFIX_PATH)
|
||||
set(CMAKE_PREFIX_PATH "/home/misaki/MisakiCodes/rk3566-sdk/3rd/Qt6.6.3")
|
||||
endif()
|
||||
add_definitions(-DCSM_TARGET_HARMONYOS_ES3)
|
||||
add_definitions(-DEMBEDDED_LINUX)
|
||||
elseif(WIN32)
|
||||
@@ -73,6 +77,8 @@ file(GLOB_RECURSE YosugaSrc
|
||||
"src/DAO/Src/*.cpp"
|
||||
"src/UI/Render/TextRender/Src/*.cpp"
|
||||
"src/UI/Render/TextRender/Inc/*.h"
|
||||
"src/UI/Widgets/Src/*.cpp"
|
||||
"src/UI/Widgets/Inc/*.hpp"
|
||||
"src/Core/Src/*.cpp"
|
||||
"src/Core/Inc/*.h"
|
||||
"src/Utils/Inc/*.hpp"
|
||||
@@ -92,6 +98,10 @@ if(NOT PLAT STREQUAL "linux_arm")
|
||||
list(APPEND YosugaSrc ${DesktopUI_Src})
|
||||
endif()
|
||||
|
||||
message(STATUS ">>> CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
|
||||
message(STATUS ">>> CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}")
|
||||
message(STATUS ">>> Qt6_DIR = ${Qt6_DIR}")
|
||||
|
||||
# 查找Qt6模块以及其他必须模块
|
||||
find_package(Qt6 COMPONENTS
|
||||
Core
|
||||
@@ -111,7 +121,8 @@ if(NOT PLAT STREQUAL "linux_arm")
|
||||
find_package(OpenGL REQUIRED)
|
||||
else ()
|
||||
# 若为arm平台,对于C++采用静态链接标准库,避免环境复杂出现问题
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc")
|
||||
# --allow-shlib-undefined: 允许共享库存在未定义符号,运行时由目标设备的 glibc 解析(这是为了放置你使用的交叉编译工具链对glibc版本要求严格)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libstdc++ -static-libgcc -Wl,--allow-shlib-undefined")
|
||||
endif ()
|
||||
|
||||
# 添加第三方子项目
|
||||
@@ -222,9 +233,9 @@ if(PLAT STREQUAL "linux_arm") ## 针对嵌入式Linux的配置,部分条
|
||||
Framework
|
||||
Live2DCubismCore
|
||||
# Mali GPU 驱动完整链接(EGLFS 必需)
|
||||
-lmali-hook # 注意此处,你的soc不一定是该GPU,可能需要修改
|
||||
-Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive
|
||||
-lmali
|
||||
# -lmali-hook # 注意此处,你的soc不一定是该GPU,可能需要修改
|
||||
# -Wl,--whole-archive -lmali-hook-injector -Wl,--no-whole-archive
|
||||
# -lmali
|
||||
-ldrm
|
||||
-lEGL
|
||||
-lGLESv2
|
||||
@@ -268,16 +279,34 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
src/UI/Menu/Inc
|
||||
src/UI/Setting/Inc
|
||||
src/UI/Render/TextRender/Inc
|
||||
src/UI/Widgets/Inc
|
||||
src/Core/Inc
|
||||
src/DAO/Inc
|
||||
src/Utils/Inc
|
||||
)
|
||||
|
||||
# Debug 编译时启用 FPS 显示等调试功能
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DYOSUGA_DEBUG)
|
||||
endif()
|
||||
|
||||
# 资源复制(所有平台)
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/Resources"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShaders"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
# 根据平台选择不同的 Shader 目录,但目标目录名统一为 FrameworkShaders
|
||||
if(PLAT STREQUAL "linux_arm")
|
||||
# 先清理旧的
|
||||
file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/FrameworkShaders")
|
||||
# 复制到构建目录 会生成 FrameworkShadersES
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShadersES"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
# 重命名为 FrameworkShaders,最终路径 build/FrameworkShaders/
|
||||
file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/FrameworkShadersES"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/FrameworkShaders")
|
||||
else()
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/other/FrameworkShaders"
|
||||
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
# Windows 特有的 DLL 复制
|
||||
if(PLAT STREQUAL "windows")
|
||||
|
||||
+20
-1
@@ -95,6 +95,23 @@
|
||||
"EGL_INCLUDE_DIR": "/home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/include",
|
||||
"EGL_LIBRARY": "/home/misaki/MisakiCodes/rk3566-sdk/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libEGL.so"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "vince-cross",
|
||||
"inherits": "embedded-base",
|
||||
"displayName": "Redmi 5 Plus (vince) Cross Compile",
|
||||
"description": "红米5 Plus 嵌入式交叉编译 (ARM64 + Qt6.6.3 EGLFS/DRM)",
|
||||
"binaryDir": "${sourceDir}/build_vince",
|
||||
"generator": "Unix Makefiles",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_TOOLCHAIN_FILE": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince_toolchain.cmake",
|
||||
"CMAKE_PREFIX_PATH": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/qt6.6.3-vince",
|
||||
"GLESv2_INCLUDE_DIR": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/include",
|
||||
"GLESv2_LIBRARY": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/lib/libGLESv2.so",
|
||||
"EGL_INCLUDE_DIR": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/include",
|
||||
"EGL_LIBRARY": "/home/misaki/MisakiCodes/Redmi5Plus-SDK/vince-rootfs/usr/lib/libEGL.so"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
@@ -107,6 +124,8 @@
|
||||
{ "name": "macos-debug", "configurePreset": "macos-native", "configuration": "Debug" },
|
||||
{ "name": "macos-release", "configurePreset": "macos-native", "configuration": "Release" },
|
||||
{ "name": "rk3566-debug", "configurePreset": "rk3566-cross", "configuration": "Debug" },
|
||||
{ "name": "rk3566-release", "configurePreset": "rk3566-cross", "configuration": "Release" }
|
||||
{ "name": "rk3566-release", "configurePreset": "rk3566-cross", "configuration": "Release" },
|
||||
{ "name": "vince-debug", "configurePreset": "vince-cross", "configuration": "Debug" },
|
||||
{ "name": "vince-release", "configurePreset": "vince-cross", "configuration": "Release" }
|
||||
]
|
||||
}
|
||||
@@ -52,8 +52,9 @@ cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
注意:本项目只是Yosuga的客户端部分,完整的还包括服务端
|
||||
注意:本项目只是Yosuga的客户端部分,完整的还包括服务端和嵌入式端
|
||||
- 服务端项目地址见:https://github.com/Misakityan/Yosuga_server
|
||||
- 嵌入式项目地址见:https://github.com/Misakityan/Yosuga_embedded
|
||||
|
||||
当前支持平台(已测试过的):
|
||||
- Windows: Windows 10
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -6,7 +6,10 @@
|
||||
#include "menu.h"
|
||||
#endif
|
||||
#ifdef EMBEDDED_LINUX
|
||||
#include <QPushButton>
|
||||
#include "PttButton.hpp"
|
||||
#endif
|
||||
#ifdef YOSUGA_DEBUG
|
||||
#include "FpsOverlay.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -89,7 +92,10 @@ private:
|
||||
Menu *contextMenu; /// 使用 Menu 类
|
||||
#endif
|
||||
#ifdef EMBEDDED_LINUX
|
||||
QPushButton *pttButton; /// 嵌入式平台PTT按钮
|
||||
PttButton *pttButton; /// 嵌入式平台PTT按钮
|
||||
#endif
|
||||
#ifdef YOSUGA_DEBUG
|
||||
FpsOverlay fpsOverlay; /// 调试用FPS显示
|
||||
#endif
|
||||
|
||||
bool isLeftPressed; /// 鼠标左键是否按下
|
||||
|
||||
+18
-20
@@ -7,6 +7,7 @@
|
||||
#include <QTimer>
|
||||
#include <QMouseEvent>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
|
||||
#include <QFont>
|
||||
#include <QApplication>
|
||||
@@ -94,28 +95,13 @@ GLCore::GLCore(const int width, const int height, QWidget *parent)
|
||||
#ifdef EMBEDDED_LINUX
|
||||
AppCore::getInstance();
|
||||
|
||||
pttButton = new QPushButton(this);
|
||||
pttButton->setFixedSize(64, 64);
|
||||
pttButton->move(width - 80, height - 80);
|
||||
pttButton->setIcon(QIcon("Resources/Pic/Others/voice.png"));
|
||||
pttButton->setIconSize(QSize(56, 56));
|
||||
pttButton->setStyleSheet(
|
||||
"QPushButton {"
|
||||
" background-color: rgba(255, 255, 255, 60);"
|
||||
" border-radius: 32px;"
|
||||
" border: none;"
|
||||
"}"
|
||||
"QPushButton:pressed {"
|
||||
" background-color: rgba(250, 80, 80, 150);"
|
||||
"}"
|
||||
);
|
||||
pttButton->raise();
|
||||
pttButton->show();
|
||||
pttButton = new PttButton(this);
|
||||
pttButton->updateLayout(width, height);
|
||||
|
||||
connect(pttButton, &QPushButton::pressed, this, []() {
|
||||
connect(pttButton, &PttButton::pressedForPtt, this, []() {
|
||||
AppCore::getInstance()->startPttRecording();
|
||||
});
|
||||
connect(pttButton, &QPushButton::released, this, []() {
|
||||
connect(pttButton, &PttButton::releasedForPtt, this, []() {
|
||||
AppCore::getInstance()->stopPttRecording();
|
||||
});
|
||||
#endif
|
||||
@@ -342,6 +328,8 @@ void GLCore::initializeGL()
|
||||
if (!LAppDelegate::GetInstance()->GetRenderContext()) {
|
||||
LAppDelegate::GetInstance()->SetRenderContext(new GLRenderContext());
|
||||
}
|
||||
|
||||
#ifndef EMBEDDED_LINUX
|
||||
// 初始化GLEW 必须在任何Live2D渲染操作之前调用
|
||||
// Live2D预编译的libFramework.a使用GLEW函数指针(如glGenFramebuffers等),
|
||||
// 未调用glewInit()会导致空指针解引用SIGSEGV
|
||||
@@ -350,6 +338,7 @@ void GLCore::initializeGL()
|
||||
qFatal("Failed to initialize GLEW");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 注册窗口大小变更回调 模型加载后通过此回调通知GLCore调整窗口
|
||||
LAppDelegate::GetInstance()->SetWindowResizeCallback([this](int w, int h) {
|
||||
@@ -361,10 +350,15 @@ void GLCore::initializeGL()
|
||||
|
||||
void GLCore::paintGL()
|
||||
{
|
||||
LAppDelegate::GetInstance()->update(); // Live2D画面渲染
|
||||
// Live2D Model画面渲染
|
||||
LAppDelegate::GetInstance()->update();
|
||||
// 渲染文本
|
||||
TextRenderer::getInstance()->update();
|
||||
TextRenderer::getInstance()->render();
|
||||
#ifdef YOSUGA_DEBUG
|
||||
fpsOverlay.tick();
|
||||
fpsOverlay.draw(width(), height());
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLCore::resizeGL(const int w, const int h)
|
||||
@@ -373,6 +367,10 @@ void GLCore::resizeGL(const int w, const int h)
|
||||
TextRenderer::getInstance()->setWindowSize(w, h);
|
||||
|
||||
LAppDelegate::GetInstance()->resize(w, h);
|
||||
|
||||
#ifdef EMBEDDED_LINUX
|
||||
pttButton->updateLayout(w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 设置窗口大小,并触发 resizeGL 事件
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef YOSUGA_DEBUG
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QString>
|
||||
|
||||
class QTimer;
|
||||
|
||||
class FpsOverlay
|
||||
{
|
||||
public:
|
||||
FpsOverlay();
|
||||
~FpsOverlay();
|
||||
|
||||
void tick();
|
||||
void draw(int parentWidth, int parentHeight);
|
||||
|
||||
float rightMargin = 0.03f;
|
||||
float topMargin = 0.03f;
|
||||
int fontSize = 20;
|
||||
|
||||
private:
|
||||
QElapsedTimer _elapsed;
|
||||
QTimer* _timer = nullptr;
|
||||
int _frameCount = 0;
|
||||
int _displayedFps = 0;
|
||||
QString _text = "FPS: --";
|
||||
|
||||
void recalcFps();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef EMBEDDED_LINUX
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
class PttButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PttButton(QWidget* parent = nullptr);
|
||||
|
||||
void updateLayout(int parentWidth, int parentHeight);
|
||||
|
||||
float scale = 0.15f;
|
||||
float rightMargin = 0.05f;
|
||||
float bottomMargin = 0.05f;
|
||||
int minSize = 48;
|
||||
int maxSize = 128;
|
||||
|
||||
signals:
|
||||
void pressedForPtt();
|
||||
void releasedForPtt();
|
||||
|
||||
private:
|
||||
void applyStyleSheet(int btnSize);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifdef YOSUGA_DEBUG
|
||||
#include "FpsOverlay.hpp"
|
||||
#include <QPainter>
|
||||
#include <QOpenGLPaintDevice>
|
||||
#include <QTimer>
|
||||
#include <cstdio>
|
||||
|
||||
FpsOverlay::FpsOverlay()
|
||||
{
|
||||
_timer = new QTimer;
|
||||
_timer->setTimerType(Qt::PreciseTimer);
|
||||
QObject::connect(_timer, &QTimer::timeout, [this]() { recalcFps(); });
|
||||
_timer->start(1000);
|
||||
_elapsed.start();
|
||||
}
|
||||
|
||||
FpsOverlay::~FpsOverlay()
|
||||
{
|
||||
delete _timer;
|
||||
}
|
||||
|
||||
void FpsOverlay::tick()
|
||||
{
|
||||
++_frameCount;
|
||||
}
|
||||
|
||||
void FpsOverlay::draw(int parentWidth, int parentHeight)
|
||||
{
|
||||
QOpenGLPaintDevice device(QSize(parentWidth, parentHeight));
|
||||
QPainter painter(&device);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QFont f;
|
||||
f.setPixelSize(fontSize);
|
||||
f.setBold(true);
|
||||
f.setStyleHint(QFont::Monospace);
|
||||
|
||||
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<int>(parentWidth * rightMargin);
|
||||
const int y = static_cast<int>(parentHeight * topMargin);
|
||||
|
||||
painter.setBrush(QColor(0, 0, 0, 180));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRoundedRect(x, y, textW, textH, 4, 4);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void FpsOverlay::recalcFps()
|
||||
{
|
||||
const qint64 ms = _elapsed.elapsed();
|
||||
if (ms == 0) return;
|
||||
|
||||
_displayedFps = static_cast<int>(_frameCount * 1000.0 / ms);
|
||||
_frameCount = 0;
|
||||
_elapsed.restart();
|
||||
|
||||
_text = QString("FPS: %1").arg(_displayedFps);
|
||||
fprintf(stderr, "[FPS] %s\n", _text.toUtf8().constData());
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifdef EMBEDDED_LINUX
|
||||
#include "PttButton.hpp"
|
||||
#include <QIcon>
|
||||
#include <algorithm>
|
||||
|
||||
PttButton::PttButton(QWidget* parent)
|
||||
: QPushButton(parent)
|
||||
{
|
||||
setIcon(QIcon("Resources/Pic/Others/voice.png"));
|
||||
setFlat(true);
|
||||
raise();
|
||||
show();
|
||||
|
||||
connect(this, &QPushButton::pressed, this, &PttButton::pressedForPtt);
|
||||
connect(this, &QPushButton::released, this, &PttButton::releasedForPtt);
|
||||
}
|
||||
|
||||
void PttButton::updateLayout(int parentWidth, int parentHeight)
|
||||
{
|
||||
if (parentWidth <= 0 || parentHeight <= 0) return;
|
||||
|
||||
const int minDim = std::min(parentWidth, parentHeight);
|
||||
const int btnSize = std::clamp(static_cast<int>(minDim * scale), minSize, maxSize);
|
||||
const int x = parentWidth - btnSize - static_cast<int>(parentWidth * rightMargin);
|
||||
const int y = parentHeight - btnSize - static_cast<int>(parentHeight * bottomMargin);
|
||||
const int iconPad = btnSize / 8;
|
||||
|
||||
setFixedSize(btnSize, btnSize);
|
||||
move(x, y);
|
||||
setIconSize(QSize(btnSize - iconPad * 2, btnSize - iconPad * 2));
|
||||
applyStyleSheet(btnSize);
|
||||
}
|
||||
|
||||
void PttButton::applyStyleSheet(int btnSize)
|
||||
{
|
||||
setStyleSheet(
|
||||
QString(
|
||||
"QPushButton {"
|
||||
" background-color: rgba(255, 255, 255, 60);"
|
||||
" border-radius: %1px;"
|
||||
" border: none;"
|
||||
"}"
|
||||
"QPushButton:pressed {"
|
||||
" background-color: rgba(250, 80, 80, 150);"
|
||||
"}"
|
||||
).arg(btnSize / 2)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user