# HG changeset patch # User unC0Rr # Date 1713541495 -7200 # Node ID a73b9770467af40ef0735ef56af65b40aa5e1318 # Parent 1f9f971adec4bdf7d2de2485f1534305947d30de Port QML frontend to Qt6, use rendering to framebuffer object diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/CMakeLists.txt --- a/qmlfrontend/CMakeLists.txt Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/CMakeLists.txt Fri Apr 19 17:44:55 2024 +0200 @@ -9,7 +9,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -find_package(Qt5 COMPONENTS Core Quick REQUIRED) +find_package(Qt6 COMPONENTS Core Quick REQUIRED) add_executable(${PROJECT_NAME} "main.cpp" "qml.qrc" "hwengine.cpp" "hwengine.h" @@ -25,4 +25,4 @@ "rooms_model.cpp" "rooms_model.h" ) -target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Network Qt5::Quick) +target_link_libraries(${PROJECT_NAME} Qt6::Core Qt6::Network Qt6::Quick) diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/Page1Form.ui.qml --- a/qmlfrontend/Page1Form.ui.qml Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/Page1Form.ui.qml Fri Apr 19 17:44:55 2024 +0200 @@ -20,6 +20,7 @@ RowLayout { Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: false Button { id: button1 @@ -80,6 +81,10 @@ Layout.fillWidth: true Layout.fillHeight: true + + MouseArea { + anchors.fill: parent + } } } diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/game_view.cpp --- a/qmlfrontend/game_view.cpp Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/game_view.cpp Fri Apr 19 17:44:55 2024 +0200 @@ -1,15 +1,67 @@ #include "game_view.h" #include + #include +#include +#include #include #include -#include + +class GameViewRenderer : public QQuickFramebufferObject::Renderer { + public: + explicit GameViewRenderer() = default; + + GameViewRenderer(const GameViewRenderer&) = delete; + GameViewRenderer(GameViewRenderer&&) = delete; + GameViewRenderer& operator=(const GameViewRenderer&) = delete; + GameViewRenderer& operator=(GameViewRenderer&&) = delete; + + void render() override; + QOpenGLFramebufferObject* createFramebufferObject(const QSize& size) override; + void synchronize(QQuickFramebufferObject* fbo) override; + + QPointer m_gameView; + QPointer m_window; + bool m_inited{false}; +}; + +void GameViewRenderer::render() { + const auto engine = m_gameView->engineInstance(); + + if (!engine) { + return; + } + + if (!m_inited) { + m_inited = true; + engine->setOpenGLContext(QOpenGLContext::currentContext()); + } + + engine->renderFrame(); + + QQuickOpenGLUtils::resetOpenGLState(); +} + +QOpenGLFramebufferObject* GameViewRenderer::createFramebufferObject( + const QSize& size) { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + format.setSamples(8); + auto fbo = new QOpenGLFramebufferObject(size, format); + return fbo; +} + +void GameViewRenderer::synchronize(QQuickFramebufferObject* fbo) { + if (!m_gameView) { + m_gameView = qobject_cast(fbo); + m_window = fbo->window(); + } +} GameView::GameView(QQuickItem* parent) - : QQuickItem(parent), m_delta(0), m_windowChanged(true) { - connect(this, &QQuickItem::windowChanged, this, - &GameView::handleWindowChanged); + : QQuickFramebufferObject(parent), m_delta(0) { + setMirrorVertically(true); } void GameView::tick(quint32 delta) { @@ -17,98 +69,23 @@ if (window()) { QTimer* timer = new QTimer(this); - connect(timer, &QTimer::timeout, window(), &QQuickWindow::update); + connect(timer, &QTimer::timeout, this, &GameView::update); timer->start(100); - - // window()->update(); } } EngineInstance* GameView::engineInstance() const { return m_engineInstance; } -void GameView::handleWindowChanged(QQuickWindow* win) { - if (win) { - connect(win, &QQuickWindow::beforeSynchronizing, this, &GameView::sync, - Qt::DirectConnection); - connect(win, &QQuickWindow::sceneGraphInvalidated, this, &GameView::cleanup, - Qt::DirectConnection); - - win->setClearBeforeRendering(false); - - m_windowChanged = true; - } +QQuickFramebufferObject::Renderer* GameView::createRenderer() const { + return new GameViewRenderer{}; } -void GameView::cleanup() { m_renderer.reset(); } - void GameView::setEngineInstance(EngineInstance* engineInstance) { if (m_engineInstance == engineInstance) { return; } - cleanup(); m_engineInstance = engineInstance; - emit engineInstanceChanged(m_engineInstance); + Q_EMIT engineInstanceChanged(m_engineInstance); } - -void GameView::sync() { - if (!m_renderer && m_engineInstance) { - m_engineInstance->setOpenGLContext(window()->openglContext()); - m_renderer.reset(new GameViewRenderer()); - m_renderer->setEngineInstance(m_engineInstance); - connect(window(), &QQuickWindow::beforeRendering, m_renderer.data(), - &GameViewRenderer::paint, Qt::DirectConnection); - } - - if (m_windowChanged || (m_viewportSize != size())) { - m_windowChanged = false; - - if (m_engineInstance) - m_engineInstance->setOpenGLContext(window()->openglContext()); - - m_viewportSize = size().toSize(); - m_centerPoint = QPoint(m_viewportSize.width(), m_viewportSize.height()) / 2; - } - - if (m_engineInstance) { - const auto delta = mapFromGlobal(QCursor::pos()).toPoint() - m_centerPoint; - - m_engineInstance->moveCamera(delta); - - QCursor::setPos(window()->screen(), mapToGlobal(m_centerPoint).toPoint()); - } - - if (m_renderer) { - m_renderer->tick(m_delta); - } -} - -GameViewRenderer::GameViewRenderer() - : QObject(), m_delta(0), m_engineInstance(nullptr) {} - -GameViewRenderer::~GameViewRenderer() {} - -void GameViewRenderer::tick(quint32 delta) { m_delta = delta; } - -void GameViewRenderer::setEngineInstance(EngineInstance* engineInstance) { - m_engineInstance = engineInstance; -} - -void GameViewRenderer::paint() { - if (m_delta == 0) { - return; - } - - if (m_engineInstance) { - m_engineInstance->advance(m_delta); - m_engineInstance->renderFrame(); - } - - // m_window->resetOpenGLState(); -} - -void GameViewRenderer::onViewportSizeChanged(QQuickWindow* window) { - if (m_engineInstance) - m_engineInstance->setOpenGLContext(window->openglContext()); -} diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/game_view.h --- a/qmlfrontend/game_view.h Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/game_view.h Fri Apr 19 17:44:55 2024 +0200 @@ -1,34 +1,13 @@ #ifndef GAMEVIEW_H #define GAMEVIEW_H -#include - #include +#include #include -#include -#include #include "engine_instance.h" -class GameViewRenderer : public QObject, protected QOpenGLFunctions { - Q_OBJECT - public: - explicit GameViewRenderer(); - ~GameViewRenderer() override; - - void tick(quint32 delta); - void setEngineInstance(EngineInstance* engineInstance); - - public slots: - void paint(); - void onViewportSizeChanged(QQuickWindow* window); - - private: - quint32 m_delta; - QPointer m_engineInstance; -}; - -class GameView : public QQuickItem { +class GameView : public QQuickFramebufferObject { Q_OBJECT Q_PROPERTY(EngineInstance* engineInstance READ engineInstance WRITE @@ -41,21 +20,16 @@ EngineInstance* engineInstance() const; - signals: + Renderer* createRenderer() const override; + + Q_SIGNALS: void engineInstanceChanged(EngineInstance* engineInstance); - public slots: - void sync(); - void cleanup(); + public Q_SLOTS: void setEngineInstance(EngineInstance* engineInstance); - private slots: - void handleWindowChanged(QQuickWindow* win); - private: quint32 m_delta; - QScopedPointer m_renderer; - bool m_windowChanged; QPointer m_engineInstance; QSize m_viewportSize; QPoint m_centerPoint; diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/hwengine.h --- a/qmlfrontend/hwengine.h Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/hwengine.h Fri Apr 19 17:44:55 2024 +0200 @@ -4,12 +4,11 @@ #include #include -#include "engine_interface.h" #include "game_config.h" +#include "preview_acceptor.h" class QQmlEngine; class EngineInstance; -class PreviewAcceptor; class HWEngine : public QObject { Q_OBJECT @@ -24,7 +23,7 @@ public: explicit HWEngine(QObject* parent = nullptr); - ~HWEngine(); + ~HWEngine() override; Q_INVOKABLE void getPreview(); Q_INVOKABLE EngineInstance* runQuickGame(); diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/main.cpp --- a/qmlfrontend/main.cpp Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/main.cpp Fri Apr 19 17:44:55 2024 +0200 @@ -18,7 +18,6 @@ } int main(int argc, char* argv[]) { - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; @@ -34,14 +33,15 @@ qmlRegisterType("Hedgewars.Engine", 1, 0, "HWEngine"); qmlRegisterType("Hedgewars.Engine", 1, 0, "GameView"); qmlRegisterType("Hedgewars.Engine", 1, 0, "NetSession"); - qmlRegisterUncreatableType("Hedgewars.Engine", 1, 0, - "EngineInstance", - "Create by HWEngine run methods"); + qmlRegisterUncreatableType( + "Hedgewars.Engine", 1, 0, "EngineInstance", + QStringLiteral("Create by HWEngine run methods")); qmlRegisterUncreatableMetaObject(Engine::staticMetaObject, "Hedgewars.Engine", - 1, 0, "Engine", "Namespace: only enums"); + 1, 0, "Engine", + QStringLiteral("Namespace: only enums")); - engine.load(QUrl(QLatin1String("qrc:/main.qml"))); + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); diff -r 1f9f971adec4 -r a73b9770467a qmlfrontend/players_model.cpp --- a/qmlfrontend/players_model.cpp Fri Apr 05 13:10:55 2024 +0100 +++ b/qmlfrontend/players_model.cpp Fri Apr 19 17:44:55 2024 +0200 @@ -23,7 +23,7 @@ QVariant PlayersListModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= rowCount() || index.column() != 0) - return QVariant(QVariant::Invalid); + return QVariant{}; return m_data.at(index.row()).value(role); } @@ -270,8 +270,8 @@ } void PlayersListModel::updateSortData(const QModelIndex &index) { - QString result = - QString("%1%2%3%4%5%6") + const auto result = + QStringLiteral("%1%2%3%4%5%6") // room admins go first, then server admins, then friends .arg(1 - index.data(RoomAdmin).toInt()) .arg(1 - index.data(ServerAdmin).toInt()) @@ -320,11 +320,12 @@ if (!txt.open(QIODevice::ReadOnly)) return; QTextStream stream(&txt); - stream.setCodec("UTF-8"); while (!stream.atEnd()) { QString str = stream.readLine(); - if (str.startsWith(";") || str.isEmpty()) continue; + if (str.startsWith(';') || str.isEmpty()) { + continue; + } set.insert(str.trimmed()); } @@ -351,7 +352,6 @@ if (!txt.open(QIODevice::WriteOnly | QIODevice::Truncate)) return; QTextStream stream(&txt); - stream.setCodec("UTF-8"); stream << "; this list is used by Hedgewars - do not edit it unless you know " "what you're doing!"