diff --git a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h index 06df0f79754..206fb760956 100644 --- a/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h +++ b/src/libs/qmlpuppetcommunication/interfaces/nodeinstanceglobal.h @@ -56,7 +56,8 @@ enum class View3DActionType { EditCameraMove, EditCameraStopAllMoves, SetLastSceneEnvData, - Import3dUpdatePreviewImage + Import3dUpdatePreviewImage, + Import3dRotatePreviewModel }; constexpr bool isNanotraceEnabled() diff --git a/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.cpp b/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.cpp index 87014cbe603..608bf42eb36 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.cpp @@ -5,6 +5,7 @@ #include #include +#include #include namespace QmlDesigner { @@ -52,5 +53,30 @@ void Import3dCanvas::resizeEvent(QResizeEvent *) emit requestImageUpdate(); } +void Import3dCanvas::mousePressEvent(QMouseEvent *e) +{ + if (e->buttons() == Qt::LeftButton) + m_dragPos = e->position(); + else + m_dragPos = {}; +} + +void Import3dCanvas::mouseReleaseEvent(QMouseEvent *) +{ + m_dragPos = {}; +} + +void Import3dCanvas::mouseMoveEvent(QMouseEvent *e) +{ + if (m_dragPos.isNull()) + return; + + const QPointF curPos = e->position(); + const QPointF delta = curPos - m_dragPos; + + m_dragPos = curPos; + + emit requestRotation(delta); +} } diff --git a/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.h b/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.h index 22bcc04d70f..72fb19acffc 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.h +++ b/src/plugins/qmldesigner/components/itemlibrary/import3dcanvas.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include namespace QmlDesigner { @@ -20,13 +20,18 @@ public: signals: void requestImageUpdate(); + void requestRotation(const QPointF &delta); protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; private: QImage m_image; + QPointF m_dragPos; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp index 4e49cd2b807..8af81a7b82e 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.cpp @@ -221,6 +221,8 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog( this, &ItemLibraryAssetImportDialog::updateUi); connect(canvas(), &Import3dCanvas::requestImageUpdate, this, &ItemLibraryAssetImportDialog::onRequestImageUpdate); + connect(canvas(), &Import3dCanvas::requestRotation, + this, &ItemLibraryAssetImportDialog::onRequestRotation); connect(&m_importer, &ItemLibraryAssetImporter::errorReported, this, &ItemLibraryAssetImportDialog::addError); @@ -856,9 +858,10 @@ Rectangle { width: %1 height: %2 - property string sceneModelName: "%3" + property alias sceneNode: sceneNode property alias view3d: view3d property string extents + property string sceneModelName: "%3" gradient: Gradient { GradientStop { position: 1.0; color: "#222222" } @@ -877,9 +880,9 @@ Rectangle { PerspectiveCamera { id: viewCamera - z: 600 - y: 600 x: 600 + y: 600 + z: 600 eulerRotation.x: -45 eulerRotation.y: -45 clipFar: 100000 @@ -889,6 +892,10 @@ Rectangle { DirectionalLight { rotation: viewCamera.rotation } + + Node { + id: sceneNode + } } Text { @@ -1041,7 +1048,8 @@ void ItemLibraryAssetImportDialog::onImportReadyForPreview(const QString &path, ui->acceptButton->setEnabled(true); ui->importButton->setEnabled(true); - addInfo(tr("Generating import preview for %1.").arg(compName)); + addInfo(tr("Import is ready for preview.")); + addInfo(tr("Click \"Accept\" to finish the import or adjust options an click \"Import\" to import again.")); } void ItemLibraryAssetImportDialog::onRequestImageUpdate() @@ -1050,6 +1058,12 @@ void ItemLibraryAssetImportDialog::onRequestImageUpdate() m_nodeInstanceView->view3DAction(View3DActionType::Import3dUpdatePreviewImage, canvas()->size()); } +void ItemLibraryAssetImportDialog::onRequestRotation(const QPointF &delta) +{ + if (m_nodeInstanceView) + m_nodeInstanceView->view3DAction(View3DActionType::Import3dRotatePreviewModel, delta); +} + void ItemLibraryAssetImportDialog::onImportNearlyFinished() { // Canceling import is no longer doable @@ -1063,18 +1077,28 @@ void ItemLibraryAssetImportDialog::onImportFinished() QString interruptStr = tr("Import interrupted."); addError(interruptStr); setImportProgress(0, interruptStr); + if (m_explicitClose) + QTimer::singleShot(1000, this, &ItemLibraryAssetImportDialog::doClose); } else { QString doneStr = tr("Import done."); addInfo(doneStr); setImportProgress(100, doneStr); if (m_closeOnFinish) { // Add small delay to allow user to visually confirm import finishing - QTimer::singleShot(1000, this, &ItemLibraryAssetImportDialog::onClose); + QTimer::singleShot(1000, this, &ItemLibraryAssetImportDialog::doClose); } } } void ItemLibraryAssetImportDialog::onClose() +{ + ui->importButton->setEnabled(false); + ui->acceptButton->setEnabled(false); + m_explicitClose = true; + doClose(); +} + +void ItemLibraryAssetImportDialog::doClose() { if (m_importer.isImporting()) { addInfo(tr("Canceling import.")); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h index efbd189c2fd..635be6db696 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimportdialog.h @@ -68,9 +68,11 @@ private: void setImportProgress(int value, const QString &text); void onImportReadyForPreview(const QString &path, const QString &compName); void onRequestImageUpdate(); + void onRequestRotation(const QPointF &delta); void onImportNearlyFinished(); void onImportFinished(); void onClose(); + void doClose(); void onAccept(); void toggleAdvanced(); @@ -116,5 +118,6 @@ private: OptionsData m_advancedData; bool m_advancedMode = false; int m_dialogHeight = 350; + bool m_explicitClose = false; }; } diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp index 1ccea6049c8..3baf91c1464 100644 --- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp +++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.cpp @@ -462,17 +462,19 @@ QVector4D GeneralHelper::approachNode( // a selection box for bound calculations to work. This is used to focus the view for // various preview image generations, where doing things asynchronously is not good // and recalculating bounds for every frame is not a problem. -QVector3D GeneralHelper::calculateNodeBoundsAndFocusCamera( - QQuick3DCamera *camera, QQuick3DNode *node, QQuick3DViewport *viewPort, - float defaultLookAtDistance, bool closeUp) +void GeneralHelper::calculateBoundsAndFocusCamera(QQuick3DCamera *camera, QQuick3DNode *node, + QQuick3DViewport *viewPort, + float defaultLookAtDistance, + bool closeUp, QVector3D &lookAt, + QVector3D &extents) { QVector3D minBounds; QVector3D maxBounds; getBounds(viewPort, node, minBounds, maxBounds); - QVector3D extents = maxBounds - minBounds; - QVector3D lookAt = minBounds + (extents / 2.f); + extents = maxBounds - minBounds; + lookAt = minBounds + (extents / 2.f); float maxExtent = qSqrt(qreal(extents.x()) * qreal(extents.x()) + qreal(extents.y()) * qreal(extents.y()) + qreal(extents.z()) * qreal(extents.z())); @@ -506,8 +508,17 @@ QVector3D GeneralHelper::calculateNodeBoundsAndFocusCamera( perspectiveCamera->setClipFar(maxDist * 1.01); } } +} - return extents; +void GeneralHelper::calculateNodeBoundsAndFocusCamera(QQuick3DCamera *camera, QQuick3DNode *node, + QQuick3DViewport *viewPort, + float defaultLookAtDistance, + bool closeUp) +{ + QVector3D extents; + QVector3D lookAt; + calculateBoundsAndFocusCamera(camera, node, viewPort, defaultLookAtDistance, closeUp, + lookAt, extents); } // Aligns any cameras found in nodes list to a camera. diff --git a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h index 996a06488f4..f1b57f4122f 100644 --- a/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h +++ b/src/tools/qml2puppet/qml2puppet/editor3d/generalhelper.h @@ -72,11 +72,12 @@ public: bool closeUp = false); Q_INVOKABLE QVector4D approachNode(QQuick3DCamera *camera, float defaultLookAtDistance, QObject *node, QQuick3DViewport *viewPort); - Q_INVOKABLE QVector3D calculateNodeBoundsAndFocusCamera(QQuick3DCamera *camera, - QQuick3DNode *node, - QQuick3DViewport *viewPort, - float defaultLookAtDistance, - bool closeUp); + void calculateBoundsAndFocusCamera(QQuick3DCamera *camera, QQuick3DNode *node, + QQuick3DViewport *viewPort, float defaultLookAtDistance, + bool closeUp, QVector3D &lookAt, QVector3D &extents); + Q_INVOKABLE void calculateNodeBoundsAndFocusCamera(QQuick3DCamera *camera, QQuick3DNode *node, + QQuick3DViewport *viewPort, + float defaultLookAtDistance, bool closeUp); Q_INVOKABLE void alignCameras(QQuick3DCamera *camera, const QVariant &nodes); Q_INVOKABLE QVector4D alignView(QQuick3DCamera *camera, const QVariant &nodes, const QVector3D &lookAtPoint, float defaultLookAtDistance); diff --git a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h index 65542dedc25..09c87b3af92 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h +++ b/src/tools/qml2puppet/qml2puppet/instances/nodeinstanceserver.h @@ -258,6 +258,7 @@ protected: void setRenderTimerInterval(int timerInterval); int renderTimerInterval() const; void setSlowRenderTimerInterval(int timerInterval); + TimerMode timerMode() const { return m_timerMode; } virtual void initializeView() = 0; virtual void initializeAuxiliaryViews(); diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp index b5afa949ec2..5d45a881af5 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.cpp @@ -68,6 +68,19 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc } break; } + case View3DActionType::Import3dRotatePreviewModel: { + QObject *obj = rootItem(); + QQmlProperty sceneNodeProp(obj, "sceneNode", context()); + auto sceneNode = sceneNodeProp.read().value(); + if (sceneNode) { + QPointF delta = command.value().toPointF(); + m_generalHelper->orbitCamera(m_view3D->camera(), m_view3D->camera()->eulerRotation(), + m_lookAt, {}, {float(delta.x()), float(delta.y()), 0.f}); + m_keepRendering = true; + startRenderTimer(); + } + break; + } default: break; } @@ -75,12 +88,10 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc void Qt5Import3dNodeInstanceServer::startRenderTimer() { - if (timerId() != 0) - killTimer(timerId()); + if (m_keepRendering && timerMode() == TimerMode::NormalTimer) + return; - int timerId = startTimer(renderTimerInterval()); - - setTimerId(timerId); + NodeInstanceServer::startRenderTimer(); } void Qt5Import3dNodeInstanceServer::cleanup() @@ -126,24 +137,28 @@ void Qt5Import3dNodeInstanceServer::render() m_view3D = qobject_cast(viewObj); if (m_view3D) { QQmlProperty sceneModelNameProp(obj, "sceneModelName", context()); - QString sceneModelName = sceneModelNameProp.read().toString(); - QFileInfo fi(fileUrl().toLocalFile()); - QString compPath = fi.absolutePath() + '/' + sceneModelName + ".qml"; - QQmlComponent comp(engine(), compPath, QQmlComponent::PreferSynchronous); - m_previewNode = qobject_cast(comp.create(context())); - if (m_previewNode) { - engine()->setObjectOwnership(m_previewNode, QJSEngine::CppOwnership); - m_previewNode->setParent(m_view3D); - m_view3D->setImportScene(m_previewNode); + QQmlProperty sceneNodeProp(obj, "sceneNode", context()); + auto sceneNode = sceneNodeProp.read().value(); + if (sceneNode) { + QString sceneModelName = sceneModelNameProp.read().toString(); + QFileInfo fi(fileUrl().toLocalFile()); + QString compPath = fi.absolutePath() + '/' + sceneModelName + ".qml"; + QQmlComponent comp(engine(), compPath, QQmlComponent::PreferSynchronous); + m_previewNode = qobject_cast(comp.create(context())); + if (m_previewNode) { + engine()->setObjectOwnership(m_previewNode, QJSEngine::CppOwnership); + m_previewNode->setParentItem(sceneNode); + m_previewNode->setParent(sceneNode); + } } } } // Render scene once to ensure geometries are intialized so bounds calculations work correctly if (m_renderCount == 2 && m_view3D) { - QVector3D extents = - m_generalHelper->calculateNodeBoundsAndFocusCamera(m_view3D->camera(), m_previewNode, - m_view3D, 1040, false); + QVector3D extents; + m_generalHelper->calculateBoundsAndFocusCamera(m_view3D->camera(), m_previewNode, + m_view3D, 1050, false, m_lookAt, extents); auto getExtentStr = [&extents](int idx) -> QString { int prec = 0; float val = extents[idx]; @@ -176,7 +191,11 @@ void Qt5Import3dNodeInstanceServer::render() nodeInstanceClient()->handlePuppetToCreatorCommand( {PuppetToCreatorCommand::Import3DPreviewImage, QVariant::fromValue(imgContainer)}); - slowDownRenderTimer(); // No more renders needed for now + + if (!m_keepRendering) + slowDownRenderTimer(); + + m_keepRendering = false; } #else slowDownRenderTimer(); diff --git a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h index bc3506ea3c0..a68401ef9fd 100644 --- a/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h +++ b/src/tools/qml2puppet/qml2puppet/instances/qt5import3dnodeinstanceserver.h @@ -35,11 +35,13 @@ private: void cleanup(); int m_renderCount = 0; + bool m_keepRendering = false; #ifdef QUICK3D_MODULE QQuick3DViewport *m_view3D = nullptr; Internal::GeneralHelper *m_generalHelper = nullptr; QQuick3DNode *m_previewNode = nullptr; + QVector3D m_lookAt; #endif };