qmlfrontend/game_view.cpp
author unC0Rr
Sun, 19 May 2024 15:55:26 +0200
changeset 16015 0e90bdfc2642
parent 16010 a73b9770467a
child 16017 e8afb1bf2779
permissions -rw-r--r--
Handle game view resize

#include "game_view.h"

#include <QtQuick/qquickwindow.h>

#include <QCursor>
#include <QOpenGLFramebufferObjectFormat>
#include <QQuickOpenGLUtils>
#include <QTimer>
#include <QtGui/QOpenGLContext>

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<GameView> m_gameView;
  QPointer<QQuickWindow> m_window;
  bool m_dirty{true};
  QSizeF m_gameViewSize;
};

void GameViewRenderer::render() {
  const auto engine = m_gameView->engineInstance();

  if (!engine) {
    return;
  }

  if (m_dirty) {
    m_dirty = false;
    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<GameView*>(fbo);
    m_window = fbo->window();
  }

  if (const auto currentSize = m_gameView->size();
      currentSize != m_gameViewSize) {
    m_gameViewSize = currentSize;
    m_dirty = true;
  }
}

GameView::GameView(QQuickItem* parent)
    : QQuickFramebufferObject(parent), m_delta(0) {
  setMirrorVertically(true);
}

void GameView::tick(quint32 delta) {
  m_delta = delta;

  if (window()) {
    QTimer* timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &GameView::update);
    timer->start(100);
  }
}

EngineInstance* GameView::engineInstance() const { return m_engineInstance; }

QQuickFramebufferObject::Renderer* GameView::createRenderer() const {
  return new GameViewRenderer{};
}

void GameView::setEngineInstance(EngineInstance* engineInstance) {
  if (m_engineInstance == engineInstance) {
    return;
  }

  m_engineInstance = engineInstance;

  Q_EMIT engineInstanceChanged(m_engineInstance);
}