/*========================================================================= Program: Visualization Toolkit Module: QQuickVTKRenderItem.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "QQuickVTKRenderItem.h" // vtk includes #include "QQuickVTKInteractiveWidget.h" #include "QQuickVTKInteractorAdapter.h" #include "vtkImageData.h" #include "vtkRenderWindow.h" // Qt includes #include //------------------------------------------------------------------------------------------------- QQuickVTKRenderItem::QQuickVTKRenderItem(QQuickItem* parent) : Superclass(parent) { // Accept mouse events setAcceptHoverEvents(true); setAcceptedMouseButtons(Qt::AllButtons); setFlag(QQuickItem::ItemIsFocusScope); setFlag(QQuickItem::ItemHasContents); QObject::connect( this, &QQuickItem::windowChanged, this, &QQuickVTKRenderItem::handleWindowChanged); } //------------------------------------------------------------------------------------------------- QQuickVTKRenderWindow* QQuickVTKRenderItem::renderWindow() const { return this->m_renderWindow; } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::setRenderWindow(QQuickVTKRenderWindow* w) { if (this->m_renderWindow == w) { return; } if (this->m_renderWindow) { this->m_renderWindow->renderWindow()->RemoveRenderer(this->m_renderer); } this->m_renderWindow = w; if (this->m_renderWindow && this->m_renderWindow->renderWindow()) { this->m_renderWindow->renderWindow()->AddRenderer(this->m_renderer); } this->m_renderWindow->render(); } //------------------------------------------------------------------------------------------------- vtkRenderer* QQuickVTKRenderItem::renderer() const { return this->m_renderer; } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::setViewport(const QRectF& rect) { if (!this->m_renderWindow) { return; } double viewport[4]; this->m_renderWindow->mapToViewport(rect, viewport); m_renderer->SetViewport(viewport); } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::sync() { if (!this->isVisible()) { return; } if (!this->m_renderWindow) { return; } // Forward the synchronize call to the window this->m_renderWindow->sync(); // Explicitly set the viewport for each render window // This is done after the window sync to ensure that the window size is set up. QRectF rect(0, 0, this->width(), this->height()); rect = this->mapRectToScene(rect); this->setViewport(rect); // Now synchronize all the widgets for (auto it = this->m_widgets.constBegin(); it < this->m_widgets.constEnd(); ++it) { (*it)->sync(this->renderer()); } } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::paint() { if (!this->isVisible()) { return; } if (!this->m_renderWindow) { return; } // Forward the paint call to the window this->m_renderWindow->paint(); } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::init() { if (!this->isVisible()) { return; } if (!this->m_renderWindow) { return; } // Forward the init call to the window this->m_renderWindow->init(); } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::cleanup() { if (!this->isVisible()) { return; } if (!this->m_renderWindow) { return; } this->m_renderer->ReleaseGraphicsResources(this->m_renderWindow->renderWindow()); // Forward the cleanup call to the window this->m_renderWindow->cleanup(); } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::handleWindowChanged(QQuickWindow* w) { if (this->window()) { QObject::disconnect( this->window(), &QQuickWindow::beforeSynchronizing, this, &QQuickVTKRenderItem::sync); #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) QObject::disconnect( window(), &QQuickWindow::beforeRendering, this, &QQuickVTKRenderItem::paint); #else QObject::disconnect( window(), &QQuickWindow::beforeRenderPassRecording, this, &QQuickVTKRenderItem::paint); #endif QObject::disconnect( window(), &QQuickWindow::sceneGraphInvalidated, this, &QQuickVTKRenderItem::cleanup); } if (w) { QObject::connect(w, &QQuickWindow::beforeSynchronizing, this, &QQuickVTKRenderItem::sync, Qt::DirectConnection); #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) QObject::connect( w, &QQuickWindow::beforeRendering, this, &QQuickVTKRenderItem::paint, Qt::DirectConnection); #else // Separate the steps between initialization and actual rendering QObject::connect( w, &QQuickWindow::beforeRendering, this, &QQuickVTKRenderItem::init, Qt::DirectConnection); QObject::connect(w, &QQuickWindow::beforeRenderPassRecording, this, &QQuickVTKRenderItem::paint, Qt::DirectConnection); #endif QObject::connect(w, &QQuickWindow::sceneGraphInvalidated, this, &QQuickVTKRenderItem::cleanup, Qt::DirectConnection); } } //------------------------------------------------------------------------------------------------- #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) void QQuickVTKRenderItem::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) #else void QQuickVTKRenderItem::geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) #endif { if (!this->renderWindow()) { return; } this->renderWindow()->interactorAdapter()->QueueGeometryChanged(newGeometry, oldGeometry); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) Superclass::geometryChanged(newGeometry, oldGeometry); #else Superclass::geometryChange(newGeometry, oldGeometry); #endif } //------------------------------------------------------------------------------------------------- bool QQuickVTKRenderItem::event(QEvent* ev) { if (!ev) { return false; } switch (ev->type()) { case QEvent::HoverEnter: case QEvent::HoverLeave: case QEvent::HoverMove: { this->renderWindow()->interactorAdapter()->QueueHoverEvent( this, static_cast(ev)); break; } case QEvent::KeyPress: case QEvent::KeyRelease: { this->renderWindow()->interactorAdapter()->QueueKeyEvent(this, static_cast(ev)); break; } case QEvent::FocusIn: case QEvent::FocusOut: { this->renderWindow()->interactorAdapter()->QueueFocusEvent( this, static_cast(ev)); break; } case QEvent::MouseMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: { this->renderWindow()->interactorAdapter()->QueueMouseEvent( this, static_cast(ev)); break; } #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: { this->renderWindow()->interactorAdapter()->QueueWheelEvent( this, static_cast(ev)); break; } #endif default: { return this->Superclass::event(ev); } } ev->accept(); return true; } //------------------------------------------------------------------------------------------------- vtkSmartPointer QQuickVTKRenderItem::captureScreenshot() { if (!this->renderWindow()) { return nullptr; } return this->renderWindow()->captureScreenshot(this->m_renderer->GetViewport()); } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::addWidget(QQuickVTKInteractiveWidget* w) { this->m_widgets.push_back(w); this->update(); } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::removeWidget(QQuickVTKInteractiveWidget* w) { this->m_widgets.removeOne(w); this->update(); } //------------------------------------------------------------------------------------------------- QQuickVTKInteractiveWidget* QQuickVTKRenderItem::widgetByName(QString name) const { for (auto it = this->m_widgets.constBegin(); it < this->m_widgets.constEnd(); ++it) { if ((*it)->objectName().compare(name) == 0) { return (*it); } } return nullptr; } //------------------------------------------------------------------------------------------------- void QQuickVTKRenderItem::removeWidgetByName(QString name) { auto w = this->widgetByName(name); if (!w) { return; } this->removeWidget(w); }