From 7010b8acb65221772870e1720389d71652d6089f Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 21 Jan 2025 23:36:40 +0200 Subject: [PATCH] fix the freeze with openglwidget Signed-off-by: Trial97 --- launcher/CMakeLists.txt | 4 +- .../ui/dialogs/skins/SkinManageDialog.cpp | 22 +++--- launcher/ui/dialogs/skins/SkinManageDialog.h | 10 ++- launcher/ui/dialogs/skins/SkinManageDialog.ui | 16 +--- .../ui/dialogs/skins/draw/BoxGeometry.cpp | 2 - launcher/ui/dialogs/skins/draw/BoxGeometry.h | 2 +- ...nOpenGLWidget.cpp => SkinOpenGLWindow.cpp} | 76 ++++++++++++------- ...{SkinOpenGLWidget.h => SkinOpenGLWindow.h} | 15 +++- 8 files changed, 81 insertions(+), 66 deletions(-) rename launcher/ui/dialogs/skins/draw/{SkinOpenGLWidget.cpp => SkinOpenGLWindow.cpp} (78%) rename launcher/ui/dialogs/skins/draw/{SkinOpenGLWidget.h => SkinOpenGLWindow.h} (84%) diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index c79f5e600..cee30e47d 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -1077,8 +1077,8 @@ SET(LAUNCHER_SOURCES ui/dialogs/skins/SkinManageDialog.cpp ui/dialogs/skins/SkinManageDialog.h - ui/dialogs/skins/draw/SkinOpenGLWidget.h - ui/dialogs/skins/draw/SkinOpenGLWidget.cpp + ui/dialogs/skins/draw/SkinOpenGLWindow.h + ui/dialogs/skins/draw/SkinOpenGLWindow.cpp ui/dialogs/skins/draw/Scene.h ui/dialogs/skins/draw/Scene.cpp ui/dialogs/skins/draw/BoxGeometry.h diff --git a/launcher/ui/dialogs/skins/SkinManageDialog.cpp b/launcher/ui/dialogs/skins/SkinManageDialog.cpp index bace07c6b..2127fc9cc 100644 --- a/launcher/ui/dialogs/skins/SkinManageDialog.cpp +++ b/launcher/ui/dialogs/skins/SkinManageDialog.cpp @@ -17,7 +17,7 @@ */ #include "SkinManageDialog.h" -#include "ui/dialogs/skins/draw/SkinOpenGLWidget.h" +#include "ui/dialogs/skins/draw/SkinOpenGLWindow.h" #include "ui_SkinManageDialog.h" #include @@ -53,13 +53,12 @@ #include "ui/instanceview/InstanceDelegate.h" SkinManageDialog::SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct) - : QDialog(nullptr) - , m_acct(acct) - , m_ui(new Ui::SkinManageDialog) - , m_list(this, APPLICATION->settings()->get("SkinsDir").toString(), acct) + : QDialog(parent), m_acct(acct), m_ui(new Ui::SkinManageDialog), m_list(this, APPLICATION->settings()->get("SkinsDir").toString(), acct) { m_ui->setupUi(this); + m_skinPreview = new SkinOpenGLWindow(this, palette().color(QPalette::Normal, QPalette::Base)); + setWindowModality(Qt::WindowModal); auto contentsWidget = m_ui->listView; @@ -100,11 +99,14 @@ SkinManageDialog::SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct) m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK")); + + m_ui->skinLayout->insertWidget(0, QWidget::createWindowContainer(m_skinPreview, this)); } SkinManageDialog::~SkinManageDialog() { delete m_ui; + delete m_skinPreview; } void SkinManageDialog::activated(QModelIndex index) @@ -126,7 +128,7 @@ void SkinManageDialog::selectionChanged(QItemSelection selected, [[maybe_unused] if (!skin) return; - m_ui->selectedModel->updateScene(skin); + m_skinPreview->updateScene(skin); m_ui->capeCombo->setCurrentIndex(m_capesIdx.value(skin->getCapeId())); m_ui->steveBtn->setChecked(skin->getModel() == SkinModel::CLASSIC); m_ui->alexBtn->setChecked(skin->getModel() == SkinModel::SLIM); @@ -222,10 +224,10 @@ void SkinManageDialog::on_capeCombo_currentIndexChanged(int index) if (!cape.isNull()) { m_ui->capeImage->setPixmap(previewCape(cape).scaled(size() * (1. / 3), Qt::KeepAspectRatio, Qt::FastTransformation)); } - m_ui->selectedModel->updateCape(cape); + m_skinPreview->updateCape(cape); if (auto skin = getSelectedSkin(); skin) { skin->setCapeId(id.toString()); - m_ui->selectedModel->updateScene(skin); + m_skinPreview->updateScene(skin); } } @@ -233,7 +235,7 @@ void SkinManageDialog::on_steveBtn_toggled(bool checked) { if (auto skin = getSelectedSkin(); skin) { skin->setModel(checked ? SkinModel::CLASSIC : SkinModel::SLIM); - m_ui->selectedModel->updateScene(skin); + m_skinPreview->updateScene(skin); } } @@ -516,13 +518,11 @@ void SkinManageDialog::resizeEvent(QResizeEvent* event) QWidget::resizeEvent(event); QSize s = size() * (1. / 3); - m_ui->selectedModel->updateScene(getSelectedSkin()); auto id = m_ui->capeCombo->currentData(); auto cape = m_capes.value(id.toString(), {}); if (!cape.isNull()) { m_ui->capeImage->setPixmap(previewCape(cape).scaled(s, Qt::KeepAspectRatio, Qt::FastTransformation)); } - m_ui->selectedModel->updateCape(cape); } SkinModel* SkinManageDialog::getSelectedSkin() diff --git a/launcher/ui/dialogs/skins/SkinManageDialog.h b/launcher/ui/dialogs/skins/SkinManageDialog.h index cb3e494d8..c6a6c9fcd 100644 --- a/launcher/ui/dialogs/skins/SkinManageDialog.h +++ b/launcher/ui/dialogs/skins/SkinManageDialog.h @@ -25,20 +25,20 @@ #include "minecraft/auth/MinecraftAccount.h" #include "minecraft/skins/SkinList.h" #include "minecraft/skins/SkinModel.h" +#include "ui/dialogs/skins/draw/SkinOpenGLWindow.h" namespace Ui { class SkinManageDialog; } - -class SkinManageDialog : public QDialog { +class SkinManageDialog : public QDialog, public SkinProvider { Q_OBJECT public: explicit SkinManageDialog(QWidget* parent, MinecraftAccountPtr acct); virtual ~SkinManageDialog(); void resizeEvent(QResizeEvent* event) override; - SkinModel* getSelectedSkin(); - QHash capes(); + virtual SkinModel* getSelectedSkin() override; + virtual QHash capes() override; public slots: void selectionChanged(QItemSelection, QItemSelection); @@ -60,10 +60,12 @@ class SkinManageDialog : public QDialog { private: void setupCapes(); + private: MinecraftAccountPtr m_acct; Ui::SkinManageDialog* m_ui; SkinList m_list; QString m_selectedSkinKey; QHash m_capes; QHash m_capesIdx; + SkinOpenGLWindow* m_skinPreview = nullptr; }; diff --git a/launcher/ui/dialogs/skins/SkinManageDialog.ui b/launcher/ui/dialogs/skins/SkinManageDialog.ui index 58f7f723d..7e8b4bc46 100644 --- a/launcher/ui/dialogs/skins/SkinManageDialog.ui +++ b/launcher/ui/dialogs/skins/SkinManageDialog.ui @@ -19,14 +19,7 @@ - - - - - - false - - + @@ -185,13 +178,6 @@ - - - SkinOpenGLWidget - QOpenGLWidget -
ui/dialogs/skins/draw/SkinOpenGLWidget.h
-
-
diff --git a/launcher/ui/dialogs/skins/draw/BoxGeometry.cpp b/launcher/ui/dialogs/skins/draw/BoxGeometry.cpp index 9a5ad1ce2..7eb766ac1 100644 --- a/launcher/ui/dialogs/skins/draw/BoxGeometry.cpp +++ b/launcher/ui/dialogs/skins/draw/BoxGeometry.cpp @@ -182,8 +182,6 @@ QVector getCubeUVs(float u, float v, float width, float height, float namespace opengl { BoxGeometry::BoxGeometry(QVector3D size, QVector3D position) : m_indexBuf(QOpenGLBuffer::IndexBuffer), m_size(size), m_position(position) { - initializeOpenGLFunctions(); - // Generate 2 VBOs m_vertexBuf.create(); m_indexBuf.create(); diff --git a/launcher/ui/dialogs/skins/draw/BoxGeometry.h b/launcher/ui/dialogs/skins/draw/BoxGeometry.h index 1a245bc14..7f36cff1b 100644 --- a/launcher/ui/dialogs/skins/draw/BoxGeometry.h +++ b/launcher/ui/dialogs/skins/draw/BoxGeometry.h @@ -25,7 +25,7 @@ #include namespace opengl { -class BoxGeometry : protected QOpenGLFunctions { +class BoxGeometry { public: BoxGeometry(QVector3D size, QVector3D position); BoxGeometry(QVector3D size, QVector3D position, QPoint uv, QVector3D textureDim, QSize textureSize = { 64, 64 }); diff --git a/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp b/launcher/ui/dialogs/skins/draw/SkinOpenGLWindow.cpp similarity index 78% rename from launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp rename to launcher/ui/dialogs/skins/draw/SkinOpenGLWindow.cpp index f1222d63e..9fbbcee9f 100644 --- a/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.cpp +++ b/launcher/ui/dialogs/skins/draw/SkinOpenGLWindow.cpp @@ -26,34 +26,54 @@ #include #include "minecraft/skins/SkinModel.h" -#include "ui/dialogs/skins/SkinManageDialog.h" #include "ui/dialogs/skins/draw/BoxGeometry.h" #include "ui/dialogs/skins/draw/Scene.h" -SkinOpenGLWidget::~SkinOpenGLWidget() +SkinOpenGLWindow::SkinOpenGLWindow(SkinProvider* parent, QColor color) + : QOpenGLWindow(), QOpenGLFunctions(), m_baseColor(color), m_parent(parent) +{ + QSurfaceFormat format = QSurfaceFormat::defaultFormat(); + format.setDepthBufferSize(24); + setFormat(format); +} + +SkinOpenGLWindow::~SkinOpenGLWindow() { // Make sure the context is current when deleting the texture // and the buffers. makeCurrent(); - delete m_scene; - delete m_background; - m_backgroundTexture->destroy(); - delete m_backgroundTexture; - if (m_program->isLinked()) { - m_program->release(); + // double check if resources were initialized because they are not + // initialized together with the object + if (m_scene) { + delete m_scene; + } + if (m_background) { + delete m_background; + } + if (m_backgroundTexture) { + if (m_backgroundTexture->isCreated()) { + m_backgroundTexture->destroy(); + } + delete m_backgroundTexture; + } + if (m_program) { + if (m_program->isLinked()) { + m_program->release(); + } + m_program->removeAllShaders(); + delete m_program; } - m_program->removeAllShaders(); - delete m_program; doneCurrent(); } -void SkinOpenGLWidget::mousePressEvent(QMouseEvent* e) +void SkinOpenGLWindow::mousePressEvent(QMouseEvent* e) { // Save mouse press position m_mousePosition = QVector2D(e->pos()); m_isMousePressed = true; } -void SkinOpenGLWidget::mouseMoveEvent(QMouseEvent* event) + +void SkinOpenGLWindow::mouseMoveEvent(QMouseEvent* event) { if (m_isMousePressed) { int dx = event->x() - m_mousePosition.x(); @@ -72,12 +92,13 @@ void SkinOpenGLWidget::mouseMoveEvent(QMouseEvent* event) update(); // Trigger a repaint } } -void SkinOpenGLWidget::mouseReleaseEvent([[maybe_unused]] QMouseEvent* e) + +void SkinOpenGLWindow::mouseReleaseEvent([[maybe_unused]] QMouseEvent* e) { m_isMousePressed = false; } -void SkinOpenGLWidget::initializeGL() +void SkinOpenGLWindow::initializeGL() { initializeOpenGLFunctions(); @@ -89,11 +110,11 @@ void SkinOpenGLWidget::initializeGL() QImage skin, cape; bool slim = false; - if (auto p = dynamic_cast(parent()); p) { - if (auto s = p->getSelectedSkin()) { + if (m_parent) { + if (auto s = m_parent->getSelectedSkin()) { skin = s->getTexture(); slim = s->getModel() == SkinModel::SLIM; - cape = p->capes().value(s->getCapeId(), {}); + cape = m_parent->capes().value(s->getCapeId(), {}); } } @@ -102,7 +123,7 @@ void SkinOpenGLWidget::initializeGL() glEnable(GL_TEXTURE_2D); } -void SkinOpenGLWidget::initShaders() +void SkinOpenGLWindow::initShaders() { m_program = new QOpenGLShaderProgram(this); // Compile vertex shader @@ -122,7 +143,7 @@ void SkinOpenGLWidget::initShaders() close(); } -void SkinOpenGLWidget::resizeGL(int w, int h) +void SkinOpenGLWindow::resizeGL(int w, int h) { // Calculate aspect ratio qreal aspect = qreal(w) / qreal(h ? h : 1); @@ -136,7 +157,7 @@ void SkinOpenGLWidget::resizeGL(int w, int h) m_projection.perspective(fov, aspect, zNear, zFar); } -void SkinOpenGLWidget::paintGL() +void SkinOpenGLWindow::paintGL() { // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -171,7 +192,7 @@ void SkinOpenGLWidget::paintGL() m_program->release(); } -void SkinOpenGLWidget::updateScene(SkinModel* skin) +void SkinOpenGLWindow::updateScene(SkinModel* skin) { if (skin && m_scene) { m_scene->setMode(skin->getModel() == SkinModel::SLIM); @@ -179,7 +200,7 @@ void SkinOpenGLWidget::updateScene(SkinModel* skin) update(); } } -void SkinOpenGLWidget::updateCape(const QImage& cape) +void SkinOpenGLWindow::updateCape(const QImage& cape) { if (m_scene) { m_scene->setCapeVisible(!cape.isNull()); @@ -236,16 +257,16 @@ QImage generateChessboardImage(int width, int height, int tileSize, QColor baseC return image; } -void SkinOpenGLWidget::generateBackgroundTexture(int width, int height, int tileSize) +void SkinOpenGLWindow::generateBackgroundTexture(int width, int height, int tileSize) { - m_backgroundTexture = - new QOpenGLTexture(generateChessboardImage(width, height, tileSize, palette().color(QPalette::Normal, QPalette::Base))); + m_backgroundTexture = new QOpenGLTexture(generateChessboardImage(width, height, tileSize, m_baseColor)); m_backgroundTexture->setMinificationFilter(QOpenGLTexture::Nearest); m_backgroundTexture->setMagnificationFilter(QOpenGLTexture::Nearest); } -void SkinOpenGLWidget::renderBackground() +void SkinOpenGLWindow::renderBackground() { + glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); // Disable depth buffer writing m_backgroundTexture->bind(); QMatrix4x4 matrix; @@ -254,9 +275,10 @@ void SkinOpenGLWidget::renderBackground() m_background->draw(m_program); m_backgroundTexture->release(); glDepthMask(GL_TRUE); // Re-enable depth buffer writing + glEnable(GL_DEPTH_TEST); } -void SkinOpenGLWidget::wheelEvent(QWheelEvent* event) +void SkinOpenGLWindow::wheelEvent(QWheelEvent* event) { // Adjust distance based on scroll int delta = event->angleDelta().y(); // Positive for scroll up, negative for scroll down diff --git a/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.h b/launcher/ui/dialogs/skins/draw/SkinOpenGLWindow.h similarity index 84% rename from launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.h rename to launcher/ui/dialogs/skins/draw/SkinOpenGLWindow.h index 4c2292054..2b229de7e 100644 --- a/launcher/ui/dialogs/skins/draw/SkinOpenGLWidget.h +++ b/launcher/ui/dialogs/skins/draw/SkinOpenGLWindow.h @@ -22,18 +22,23 @@ #include #include #include -#include +#include #include #include "minecraft/skins/SkinModel.h" #include "ui/dialogs/skins/draw/BoxGeometry.h" #include "ui/dialogs/skins/draw/Scene.h" -class SkinOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { +class SkinProvider { + public: + virtual SkinModel* getSelectedSkin() = 0; + virtual QHash capes() = 0; +}; +class SkinOpenGLWindow : public QOpenGLWindow, protected QOpenGLFunctions { Q_OBJECT public: - SkinOpenGLWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent), QOpenGLFunctions() {} - virtual ~SkinOpenGLWidget(); + SkinOpenGLWindow(SkinProvider* parent, QColor color); + virtual ~SkinOpenGLWindow(); void updateScene(SkinModel* skin); void updateCape(const QImage& cape); @@ -68,4 +73,6 @@ class SkinOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { opengl::BoxGeometry* m_background = nullptr; QOpenGLTexture* m_backgroundTexture = nullptr; + QColor m_baseColor; + SkinProvider* m_parent = nullptr; };