diff --git a/3rdparty/Live2D/Src/Framework/src/Model/CubismModel.hpp b/3rdparty/Live2D/Src/Framework/src/Model/CubismModel.hpp index bf98952..ce40288 100644 --- a/3rdparty/Live2D/Src/Framework/src/Model/CubismModel.hpp +++ b/3rdparty/Live2D/Src/Framework/src/Model/CubismModel.hpp @@ -159,43 +159,43 @@ public: void Update() const; /** - * Returns the width of the canvas. - * + * Returns the width of the canvas.
+ * 返回画布的像素宽度。 * @return Width of the canvas in pixels */ csmFloat32 GetCanvasWidthPixel() const; /** - * Returns the height of the canvas. - * + * Returns the height of the canvas.
+ * 返回画布的像素高度。 * @return Height of the canvas in pixels */ csmFloat32 GetCanvasHeightPixel() const; /** - * Returns the pixels per unit (PPU). - * + * Returns the pixels per unit (PPU).
+ * 返回 PPU(Pixels Per Unit),即 Live2D 坐标系中的 $1.0$ 单位对应多少像素。 (Misaki注解) * @return Pixels per unit */ csmFloat32 GetPixelsPerUnit() const; /** * Returns the width of the canvas. - * + * 返回画布在 PPU 单位下的宽度(例如 1.0) * @return Width of the canvas in PPU (pixels per unit) */ csmFloat32 GetCanvasWidth() const; /** * Returns the height of the canvas. - * + * 返回画布在 PPU 单位下的高度(例如 2.155300)。 * @return Height of the canvas in PPU (pixels per unit) */ csmFloat32 GetCanvasHeight() const; /** * Returns the index of the part. - * + * 根据部件 ID (例如 PartId::HairFront) 获取其在数组中的索引。 * @param partId Part ID * * @return Index of the part @@ -204,7 +204,7 @@ public: /** * Returns the ID of the part. - * + * 根据索引获取部件 ID。 * @param partIndex Index of the part * @return Part ID */ @@ -212,21 +212,21 @@ public: /** * Returns the number of parts. - * + * 返回模型中部件的总数。 * @return Number of parts */ csmInt32 GetPartCount() const; /** * Returns the index of the parent parts for the parts. - * + * 获取每个部件的父部件索引数组,用于确定绘制顺序或层级关系。 * @return Index of parent parts for the parts. */ const csmInt32* GetPartParentPartIndices() const; /** * Sets the opacity of the part. - * + * 设置或获取部件的不透明度(0.0 到 1.0)。常用于实现部件的动态隐藏或显示效果。 * @param partId Part ID * @param opacity Opacity */ @@ -234,7 +234,7 @@ public: /** * Sets the opacity of the part. - * + * 设置或获取部件的不透明度(0.0 到 1.0)。常用于实现部件的动态隐藏或显示效果。 * @param partIndex Part index * @param opacity Part opacity */ diff --git a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp index 0ae7d42..44eb977 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Inc/LAppModel.hpp @@ -48,6 +48,25 @@ public: */ int getTapBodyMotionCount(); + /** + * @brief 获取 Live2D 模型的 Canvas 宽度像素 (在 Live2D 坐标系下) + * @return Canvas 宽度 + */ + Live2D::Cubism::Framework::csmFloat32 GetModelCanvasWidthPixel() const + { + // _model 是 CubismModel 的基类指针 + return _model ? _model->GetCanvasWidthPixel() : 0.0f; + } + + /** + * @brief 获取 Live2D 模型的 Canvas 高度像素 (在 Live2D 坐标系下) + * @return Canvas 高度 + */ + Live2D::Cubism::Framework::csmFloat32 GetModelCanvasHeightPixel() const + { + return _model ? _model->GetCanvasHeightPixel() : 0.0f; + } + /** * @brief 启动唇形同步并播放指定的 WAV 文件 * @param filePath WAV 文件的路径(csmString 类型) @@ -64,8 +83,8 @@ public: /** - * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する - * + * @brief model3.jsonが置かれたディレクトリとファイルパスからモデルを生成する \n + * 从 model3.json 所在的目录和文件路径生成模型 */ void LoadAssets(const Csm::csmChar* dir, const Csm::csmChar* fileName); diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp index bf97e96..13d2c16 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppDelegate.cpp @@ -63,7 +63,7 @@ bool LAppDelegate::Initialize(GLCore* window) // Windowの生成_ //_window = glfwCreateWindow(RenderTargetWidth, RenderTargetHeight, "SAMPLE", NULL, NULL); _window = window; // Misaki 修改 - if (_window == NULL) + if (_window == nullptr) { if (DebugLogEnable) { @@ -217,7 +217,7 @@ void LAppDelegate::update() LAppDelegate::LAppDelegate(): _cubismOption(), - _window(NULL), + _window(nullptr), _captured(false), _mouseX(0.0f), _mouseY(0.0f), @@ -259,7 +259,7 @@ void LAppDelegate::InitializeCubism() void LAppDelegate::OnMouseCallBack(GLFWwindow* window, int button, int action, int modify) { - if (_view == NULL) + if (_view == nullptr) { return; } @@ -292,7 +292,7 @@ void LAppDelegate::OnMouseCallBack(GLFWwindow* window, double x, double y) { return; } - if (_view == NULL) + if (_view == nullptr) { return; } @@ -313,7 +313,7 @@ GLuint LAppDelegate::CreateShader() " gl_Position = vec4(position, 1.0);" " vuv = uv;" "}"; - glShaderSource(vertexShaderId, 1, &vertexShader, NULL); + glShaderSource(vertexShaderId, 1, &vertexShader, nullptr); glCompileShader(vertexShaderId); if(!CheckShader(vertexShaderId)) { @@ -330,7 +330,7 @@ GLuint LAppDelegate::CreateShader() "void main(void){" " gl_FragColor = texture2D(texture, vuv) * baseColor;" "}"; - glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL); + glShaderSource(fragmentShaderId, 1, &fragmentShader, nullptr); glCompileShader(fragmentShaderId); if (!CheckShader(fragmentShaderId)) { diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp index 7dba80b..8c61d6f 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppLive2DManager.cpp @@ -29,7 +29,7 @@ using namespace LAppDefine; using namespace std; namespace { - LAppLive2DManager* s_instance = NULL; + LAppLive2DManager* s_instance = nullptr; void FinishedMotion(ACubismMotion* self) { @@ -45,7 +45,7 @@ namespace { LAppLive2DManager* LAppLive2DManager::GetInstance() { - if (s_instance == NULL) + if (s_instance == nullptr) { s_instance = new LAppLive2DManager(); } @@ -55,22 +55,22 @@ LAppLive2DManager* LAppLive2DManager::GetInstance() void LAppLive2DManager::ReleaseInstance() { - if (s_instance != NULL) + if (s_instance != nullptr) { delete s_instance; } - s_instance = NULL; + s_instance = nullptr; } LAppLive2DManager::LAppLive2DManager() - : _viewMatrix(NULL) + : _viewMatrix(nullptr) , _sceneIndex(0) { _viewMatrix = new CubismMatrix44(); //SetUpModel(); // Resources/Haru/ Haru.model3.json - LoadModelFromPath("Resources/Live2DModels/KITU17/", "KITU17.model3.json"); + LoadModelFromPath("Resources/Live2DModels/KITU17/", "KITU17.model3.json"); // 默认加载的模型 //ChangeScene(_sceneIndex); } @@ -140,7 +140,7 @@ void LAppLive2DManager::SetUpModel() if (fs::exists(modelJson)) _modelDir.PushBack(csmString(dirName.c_str())); } - /* 保持与原代码相同的排序 */ + // 保持与原代码相同的排序 qsort(_modelDir.GetPtr(), _modelDir.GetSize(), sizeof(csmString), CompareCsmString); #endif } @@ -162,7 +162,7 @@ LAppModel* LAppLive2DManager::GetModel(csmUint32 no) const return _models[no]; } - return NULL; + return nullptr; } /** @@ -229,7 +229,7 @@ void LAppLive2DManager::OnUpdate() const CubismMatrix44 projection; LAppModel* model = GetModel(i); - if (model->GetModel() == NULL) + if (model->GetModel() == nullptr) { LAppPal::PrintLogLn("Failed to model->GetModel()."); continue; @@ -247,7 +247,7 @@ void LAppLive2DManager::OnUpdate() const } // 必要があればここで乗算 - if (_viewMatrix != NULL) + if (_viewMatrix != nullptr) { projection.MultiplyByMatrix(_viewMatrix); } @@ -262,7 +262,7 @@ void LAppLive2DManager::OnUpdate() const LAppDelegate::GetInstance()->GetView()->PostModelDraw(*model); } } - +#include void LAppLive2DManager::LoadModelFromPath(const std::string& modelPath, const std::string& fileName) { csmString modelPathStr(modelPath.c_str()); @@ -272,6 +272,11 @@ void LAppLive2DManager::LoadModelFromPath(const std::string& modelPath, const st _models.PushBack(new LAppModel()); // 这样在加载的时候都使用的models[0]这一个位置,自行实现模型选择器要注意注意 _models[0]->LoadAssets(modelPathStr.GetRawString(), modelJsonName.GetRawString()); + // 加载完后根据模型大小来重新设置当前窗口大小 + const int width = static_cast(_models[0]->GetModel()->GetCanvasWidthPixel() / 15.0); + const int height = static_cast(_models[0]->GetModel()->GetCanvasHeightPixel() / 15.0); + AppContext::GetGLCore()->setWindowSize(width, height); + LAppPal::PrintLogLn("[APP]窗口尺寸重新设置为: W: %d H: %d", width, height); /* * 提供一个半透明表示模型的示例。 * 如果定义了USE_RENDER_TARGET或USE_MODEL_RENDER_TARGET, diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp index 73ff9ff..045bb8d 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppModel.cpp @@ -47,7 +47,7 @@ namespace { LAppModel::LAppModel() : CubismUserModel() - , _modelSetting(NULL) + , _modelSetting(nullptr) , _userTimeSeconds(0.0f) { if (MocConsistencyValidationEnable) @@ -101,7 +101,7 @@ void LAppModel::LoadAssets(const csmChar* dir, const csmChar* fileName) SetupModel(setting); - if (_model == NULL) + if (_model == nullptr) { LAppPal::PrintLogLn("Failed to LoadAssets()."); return; @@ -123,7 +123,7 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) csmSizeInt size; //Cubism Model - if (strcmp(_modelSetting->GetModelFileName(), "") != 0) + if (strcmp(_modelSetting->GetModelFileName(), "") != 0) // 如果模型文件名不为空 { csmString path = _modelSetting->GetModelFileName(); path = _modelHomeDir + path; @@ -153,10 +153,10 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) if (motion) { - if (_expressions[name] != NULL) + if (_expressions[name] != nullptr) { ACubismMotion::Delete(_expressions[name]); - _expressions[name] = NULL; + _expressions[name] = nullptr; } _expressions[name] = motion; } @@ -240,7 +240,7 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) } } - if (_modelSetting == NULL || _modelMatrix == NULL) + if (_modelSetting == nullptr || _modelMatrix == nullptr) { LAppPal::PrintLogLn("Failed to SetupModel()."); return; @@ -258,11 +258,11 @@ void LAppModel::SetupModel(ICubismModelSetting* setting) const csmChar* group = _modelSetting->GetMotionGroupName(i); PreloadMotionGroup(group); } - _motionManager->StopAllMotions(); _updating = false; _initialized = true; + LAppPal::PrintLogLn("[APP]当前模型像素大小: H: %lf W: %lf", GetModelCanvasHeightPixel(), GetModelCanvasWidthPixel()); } void LAppModel::PreloadMotionGroup(const csmChar* group) @@ -301,7 +301,7 @@ void LAppModel::PreloadMotionGroup(const csmChar* group) } tmpMotion->SetEffectIds(_eyeBlinkIds, _lipSyncIds); - if (_motions[name] != NULL) + if (_motions[name] != nullptr) { ACubismMotion::Delete(_motions[name]); } @@ -389,14 +389,14 @@ void LAppModel::Update() // まばたき 眨眼 if (!motionUpdated) { - if (_eyeBlink != NULL) + if (_eyeBlink != nullptr) { // メインモーションの更新がないとき 当主动作没有更新时 _eyeBlink->UpdateParameters(_model, deltaTimeSeconds); // 目パチ } } - if (_expressionManager != NULL) + if (_expressionManager != nullptr) { _expressionManager->UpdateMotion(_model, deltaTimeSeconds); // 表情でパラメータ更新(相対変化) } @@ -415,13 +415,13 @@ void LAppModel::Update() _model->AddParameterValue(_idParamEyeBallY, _dragY); // 呼吸など - if (_breath != NULL) + if (_breath != nullptr) { _breath->UpdateParameters(_model, deltaTimeSeconds); } // 物理演算の設定 - if (_physics != NULL) + if (_physics != nullptr) { _physics->Evaluate(_model, deltaTimeSeconds); } @@ -455,7 +455,7 @@ void LAppModel::Update() } // ポーズの設定 - if (_pose != NULL) + if (_pose != nullptr) { _pose->UpdateParameters(_model, deltaTimeSeconds); } @@ -516,7 +516,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt CubismMotion* motion = static_cast(_motions[name.GetRawString()]); csmBool autoDelete = false; - if (motion == NULL) + if (motion == nullptr) { csmString path = fileName; path = _modelHomeDir + path; @@ -524,7 +524,7 @@ CubismMotionQueueEntryHandle LAppModel::StartMotion(const csmChar* group, csmInt csmByte* buffer; csmSizeInt size; buffer = CreateBuffer(path.GetRawString(), &size); - motion = static_cast(LoadMotion(buffer, size, NULL, onFinishedMotionHandler)); + motion = static_cast(LoadMotion(buffer, size, nullptr, onFinishedMotionHandler)); if (motion) { @@ -618,7 +618,7 @@ int LAppModel::getTapBodyMotionCount() void LAppModel::DoDraw() { - if (_model == NULL) + if (_model == nullptr) { return; } @@ -628,7 +628,7 @@ void LAppModel::DoDraw() void LAppModel::Draw(CubismMatrix44& matrix) { - if (_model == NULL) + if (_model == nullptr) { return; } @@ -667,7 +667,7 @@ void LAppModel::SetExpression(const csmChar* expressionID) LAppPal::PrintLogLn("[APP]expression: [%s]", expressionID); } - if (motion != NULL) + if (motion != nullptr) { _expressionManager->StartMotionPriority(motion, false, PriorityForce); } diff --git a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp index ec0568c..48a3672 100644 --- a/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp +++ b/3rdparty/Live2D/Src/LAppLive2D/Src/LAppView.cpp @@ -25,7 +25,7 @@ LAppView::LAppView(): //_back(NULL), //_gear(NULL), //_power(NULL), - _renderSprite(NULL), + _renderSprite(nullptr), _renderTarget(SelectTarget_None) { _clearColor[0] = 1.0f; @@ -268,7 +268,7 @@ float LAppView::TransformScreenY(float deviceY) const void LAppView::PreModelDraw(LAppModel& refModel) { // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ - Csm::Rendering::CubismOffscreenSurface_OpenGLES2* useTarget = NULL; + Csm::Rendering::CubismOffscreenSurface_OpenGLES2* useTarget = nullptr; if (_renderTarget != SelectTarget_None) {// 別のレンダリングターゲットへ向けて描画する場合 @@ -299,7 +299,7 @@ void LAppView::PreModelDraw(LAppModel& refModel) void LAppView::PostModelDraw(LAppModel& refModel) { // 別のレンダリングターゲットへ向けて描画する場合の使用するフレームバッファ - Csm::Rendering::CubismOffscreenSurface_OpenGLES2* useTarget = NULL; + Csm::Rendering::CubismOffscreenSurface_OpenGLES2* useTarget = nullptr; if (_renderTarget != SelectTarget_None) {// 別のレンダリングターゲットへ向けて描画する場合 diff --git a/README.md b/README.md index 83cabe7..c446c26 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,13 @@ (本项目由Yosuga[Qt5] 发展更新而来,项目架构与代码都有所不同,最显著的特点是本项目支持多平台) 环境为: -cmake version 3.31.3 +- cmake version 3.5 -Qt6.6.3 +- C++ 20 -IDE: Clion +- Qt6.6.3 + +- IDE: Clion 如何构建本项目: diff --git a/main.cpp b/main.cpp index 9495f95..8ab92e0 100644 --- a/main.cpp +++ b/main.cpp @@ -18,7 +18,7 @@ int main(int argc, char *argv[]) // 设置日志过滤规则,将这个特定分类的警告级别设置为“关闭” QLoggingCategory::setFilterRules("qt.multimedia.ffmpeg.libsymbolsresolver.warning=false"); #endif - GLCore w(360, 480); + GLCore w(360, 480); // 创建默认的窗口 w.show(); - return a.exec(); + return QApplication::exec(); } diff --git a/src/Core/Inc/GLCore.h b/src/Core/Inc/GLCore.h index cb88673..947a29e 100644 --- a/src/Core/Inc/GLCore.h +++ b/src/Core/Inc/GLCore.h @@ -4,7 +4,7 @@ #include #include "menu.h" -class GLCore : public QOpenGLWidget +class GLCore final : public QOpenGLWidget { Q_OBJECT @@ -19,15 +19,18 @@ public: // 删除移动运算符 GLCore& operator=(GLCore&&) = delete; - ~GLCore(); + ~GLCore() override; // 帧率控制 void setFrameRate(double fps); - double getFrameRate(); + [[nodiscard]] double getFrameRate() const; // 帧率表 static QMap getFrameRateMap(); static QStringList getFrameRateList(); + // 安全地设置窗口的实际像素尺寸 + void setWindowSize(int w, int h); + void mouseMoveEvent(QMouseEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; diff --git a/src/Core/Src/GLCore.cpp b/src/Core/Src/GLCore.cpp index 0361286..870f1f1 100644 --- a/src/Core/Src/GLCore.cpp +++ b/src/Core/Src/GLCore.cpp @@ -61,7 +61,7 @@ GLCore::GLCore(int w, int h, QWidget *parent) TextRenderer::getInstance()->setGravity(600.0f); // 更快的下坠速度 TextRenderer::getInstance()->setDampFactor(0.85f); // 更强的弹性效果 - this->setWindowFlag(Qt::FramelessWindowHint); // 设置无边框窗口 + // this->setWindowFlag(Qt::FramelessWindowHint); // 设置无边框窗口 this->setWindowFlag(Qt::WindowStaysOnTopHint); // 设置窗口始终在顶部 this->setWindowFlag(Qt::Tool); // 隐藏应用程序图标 this->setAttribute(Qt::WA_TranslucentBackground); // 设置窗口背景透明 @@ -75,7 +75,7 @@ GLCore::GLCore(int w, int h, QWidget *parent) frameTimer->start(static_cast((1.0 / frameRate) * 1000)); // 使用成员变量计算间隔 - // 启用鼠标跟踪,不启用鼠标按下才会回调mouseMoveEvent函数 + // 启用鼠标跟踪,不启用的话鼠标按下才会回调mouseMoveEvent函数 this->setMouseTracking(true); // 连接一些必要的信号与槽 @@ -114,7 +114,7 @@ void GLCore::setFrameRate(double fps) } // 获取当前帧率 -double GLCore::getFrameRate() +double GLCore::getFrameRate() const { return frameRate; } @@ -163,8 +163,8 @@ void GLCore::closeEvent(QCloseEvent* event) void GLCore::mouseMoveEvent(QMouseEvent* event) { LAppDelegate::GetInstance()->GetView()->OnTouchesMoved( - event->position().x(), - event->position().y() + static_cast(event->position().x()), + static_cast(event->position().y()) ); if (isLeftPressed) { @@ -176,8 +176,8 @@ void GLCore::mouseMoveEvent(QMouseEvent* event) void GLCore::mousePressEvent(QMouseEvent* event) { LAppDelegate::GetInstance()->GetView()->OnTouchesBegan( - event->position().x(), - event->position().y() + static_cast(event->position().x()), + static_cast(event->position().y()) ); if (event->button() == Qt::LeftButton) { @@ -198,8 +198,8 @@ void GLCore::mousePressEvent(QMouseEvent* event) void GLCore::mouseReleaseEvent(QMouseEvent* event) { LAppDelegate::GetInstance()->GetView()->OnTouchesEnded( - event->position().x(), - event->position().y() + static_cast(event->position().x()), + static_cast(event->position().y()) ); if (event->button() == Qt::LeftButton) { @@ -218,16 +218,31 @@ void GLCore::initializeGL() void GLCore::paintGL() { - LAppDelegate::GetInstance()->update(); + LAppDelegate::GetInstance()->update(); // Live2D画面渲染 // 渲染文本 TextRenderer::getInstance()->update(); TextRenderer::getInstance()->render(); } -void GLCore::resizeGL(int w, int h) +void GLCore::resizeGL(const int w, const int h) { // 设置文本渲染器窗口大小 TextRenderer::getInstance()->setWindowSize(w, h); LAppDelegate::GetInstance()->resize(w, h); +} + +// 设置窗口大小,并触发 resizeGL 事件 +void GLCore::setWindowSize(const int w, const int h) +{ + // 检查是否需要更新,避免重复调用 + if (this->width() == w && this->height() == h) { + return; + } + + // 调用 QWidget::resize 或 setFixedSize 来改变窗口的实际尺寸 + setFixedSize(w, h); + + // 调用 setFixedSize 会自动触发 QOpenGLWidget 的 resizeEvent, + // 进而调用 resizeGL(w, h),无需手动调用 resizeGL } \ No newline at end of file diff --git a/src/Render/TextRender/Inc/TextRenderer.h b/src/Render/TextRender/Inc/TextRenderer.h index 22c0aaf..3703cab 100644 --- a/src/Render/TextRender/Inc/TextRenderer.h +++ b/src/Render/TextRender/Inc/TextRenderer.h @@ -1,9 +1,7 @@ // // Created by Administrator on 2025/2/16. // - -#ifndef AIRI_DESKTOPGRIL_TEXTRENDERER_H -#define AIRI_DESKTOPGRIL_TEXTRENDERER_H +#pragma once #include #include @@ -99,5 +97,3 @@ private: float gravity; /// 重力加速度(像素/秒²) float dampFactor; /// 碰撞阻尼系数 }; - -#endif //AIRI_DESKTOPGRIL_TEXTRENDERER_H diff --git a/src/Render/TextRender/Src/TextRenderer.cpp b/src/Render/TextRender/Src/TextRenderer.cpp index 485354e..5f93239 100644 --- a/src/Render/TextRender/Src/TextRenderer.cpp +++ b/src/Render/TextRender/Src/TextRenderer.cpp @@ -198,8 +198,8 @@ void TextRenderer::update() // 最终居中定位 int totalWidth = 0; - for (int w : instance.charWidths) totalWidth += w; - int startX = (windowWidth - totalWidth) / 2; + for (const int w : instance.charWidths) totalWidth += w; + const int startX = (windowWidth - totalWidth) / 2; int currentX = startX; instance.charPositions.clear();