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()); -}