#include #include #include #include #include #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(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; }