Files
magnum-boostrap-qtquick/src/magnum_item.cpp

139 lines
3.6 KiB
C++

#include <Magnum/GL/Framebuffer.h>
#include <Magnum/Platform/GLContext.h>
#include <QtCore/QRunnable>
#include <QtQuick/QQuickWindow>
#include <QOpenGLFramebufferObject>
#include "magnum_item.h"
#include "magnum_render.h"
using namespace std;
using namespace Magnum;
using namespace Math::Literals;
class MagnumFBORenderer : public QQuickFramebufferObject::Renderer {
public:
MagnumFBORenderer(QQuickWindow *window, MagnumRenderer *renderer) :
m_window(window),
m_renderer(renderer) {}
void render() override {
m_renderer->render();
m_window->resetOpenGLState();
update();
}
void synchronize(QQuickFramebufferObject *item) override {
auto mitem = static_cast<MagnumItem*>(item);
m_renderer->t(mitem->t());
m_renderer->hue(mitem->hue());
m_renderer->count(mitem->count());
m_renderer->lagging(mitem->lagging());
}
QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override {
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(4);
m_fbo = new QOpenGLFramebufferObject(size, format);
// ---
if (m_ctx == nullptr)
m_ctx = new Platform::GLContext();
Platform::GLContext::makeCurrent(m_ctx);
m_renderer->reset(
m_ctx,
GL::Framebuffer::wrap(
m_fbo->handle(), {{}, {size.width(),
size.height()}}),
Vector2i{m_window->width(), m_window->height()},
Vector2i{size.width(), size.height()});
return m_fbo;
}
private:
QQuickWindow *m_window;
QOpenGLFramebufferObject *m_fbo;
Platform::GLContext *m_ctx{};
MagnumRenderer *m_renderer;
};
MagnumItem::MagnumItem() : m_renderer(new MagnumRenderer()) {
setMirrorVertically(true);
setAcceptHoverEvents(true);
setAcceptedMouseButtons(Qt::AllButtons);
setFlag(ItemAcceptsInputMethod, true);
}
QQuickFramebufferObject::Renderer *MagnumItem::createRenderer() const {
return new MagnumFBORenderer(window(), m_renderer);
}
void MagnumItem::setT(qreal t) {
if (t == m_t) return;
m_t = t;
emit tChanged();
update();
}
void MagnumItem::setHue(qreal hue) {
if (hue == m_hue) return;
m_hue = hue;
emit hueChanged();
update();
}
void MagnumItem::setCount(qint8 count) {
if (count == m_count) return;
m_count = count;
emit countChanged();
update();
}
void MagnumItem::setLagging(qreal lagging) {
if (lagging == m_lagging) return;
m_lagging = lagging;
emit laggingChanged();
update();
}
void MagnumItem::mousePressEvent(QMouseEvent *evt) {
if (auto& camera = m_renderer->camera()) {
camera->initTransformation({evt->pos().x(), evt->pos().y()});
}
}
void MagnumItem::mouseMoveEvent(QMouseEvent *evt) {
if (!evt->buttons())
return;
if (auto& camera = m_renderer->camera()) {
if (evt->modifiers() & Qt::ShiftModifier) {
camera->translate({evt->pos().x(), evt->pos().y()});
} else {
camera->rotate({evt->pos().x(), evt->pos().y()});
}
}
}
void MagnumItem::wheelEvent(QWheelEvent *evt) {
if (auto& camera = m_renderer->camera()) {
const Float delta = evt->angleDelta().y();
if (Math::abs(delta) < 1.0e-2f)
return;
camera->zoom(delta*.01f);
}
}
class CleanupJob : public QRunnable {
public:
CleanupJob(MagnumRenderer *renderer) : m_renderer(renderer) {}
void run() override { delete m_renderer; }
private:
MagnumRenderer *m_renderer;
};
void MagnumItem::releaseResources() {
window()->scheduleRenderJob(
new CleanupJob(m_renderer),
QQuickWindow::BeforeSynchronizingStage);
m_renderer = nullptr;
}