diff --git a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h b/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h index cfe4529ba1b..95ca0d3ce25 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/puppettocreatorcommand.h @@ -40,6 +40,7 @@ public: ActiveSceneChanged, RenderModelNodePreviewImage, Import3DSupport, + ModelAtPos, None }; PuppetToCreatorCommand(Type type, const QVariant &data); diff --git a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h index a1dc133032e..13d39739437 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/view3dactioncommand.h @@ -59,9 +59,10 @@ public: SelectBackgroundColor, SelectGridColor, ResetBackgroundColor, + GetModelAtPos }; - explicit View3DActionCommand(Type type, const QVariant &value); + View3DActionCommand(Type type, const QVariant &value); View3DActionCommand() = default; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 0d351214561..4448e2cee1f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -2319,6 +2319,32 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c m_particleAnimationDriver->setSeekerPosition(static_cast(command).position()); break; #endif +#ifdef QUICK3D_MODULE + case View3DActionCommand::GetModelAtPos: { + // pick a Quick3DModel at view position + auto helper = qobject_cast(m_3dHelper); + if (!helper) + return; + + QQmlProperty editViewProp(m_editView3DData.rootItem, "editView", context()); + QObject *obj = qvariant_cast(editViewProp.read()); + QQuick3DViewport *editView = qobject_cast(obj); + + QPointF pos = command.value().toPointF(); + QQuick3DModel *hitModel = helper->pickViewAt(editView, pos.x(), pos.y()).objectHit(); + + // filter out picks of models created dynamically or inside components + QQuick3DModel *resolvedPick = qobject_cast(helper->resolvePick(hitModel)); + + if (resolvedPick) { + ServerNodeInstance instance = instanceForObject(resolvedPick); + nodeInstanceClient()->handlePuppetToCreatorCommand( + {PuppetToCreatorCommand::ModelAtPos, QVariant(instance.instanceId())}); + } + return; + } +#endif + default: break; } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index cc6058782ed..bcce905b4fa 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -239,6 +239,16 @@ void Edit3DView::customNotification(const AbstractView *view, const QString &ide resetPuppet(); } +void Edit3DView::modelAtPosReady(const ModelNode &modelNode) +{ + if (!m_droppedMaterial.isValid() || !modelNode.isValid()) + return; + + executeInTransaction(__FUNCTION__, [&] { + assignMaterialTo3dModel(modelNode, m_droppedMaterial); + }); +} + void Edit3DView::sendInputEvent(QInputEvent *e) const { if (nodeInstanceView()) @@ -605,5 +615,10 @@ void Edit3DView::addQuick3DImport() tr("Could not add QtQuick3D import to project.")); } +void Edit3DView::dropMaterial(const ModelNode &matNode, const QPointF &pos) +{ + m_droppedMaterial = matNode; + QmlDesignerPlugin::instance()->viewManager().nodeInstanceView()->view3DAction({View3DActionCommand::GetModelAtPos, pos}); } +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.h b/src/plugins/qmldesigner/components/edit3d/edit3dview.h index b817c20d1a4..4d96a7549f3 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.h +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.h @@ -64,6 +64,7 @@ public: void modelAboutToBeDetached(Model *model) override; void importsChanged(const QList &addedImports, const QList &removedImports) override; void customNotification(const AbstractView *view, const QString &identifier, const QList &nodeList, const QList &data) override; + void modelAtPosReady(const ModelNode &modelNode) override; void sendInputEvent(QInputEvent *e) const; void edit3DViewResized(const QSize &size) const; @@ -78,8 +79,7 @@ public: void setSeeker(SeekerSlider *slider); void addQuick3DImport(); - -protected: + void dropMaterial(const ModelNode &matNode, const QPointF &pos); private: void createEdit3DWidget(); @@ -118,6 +118,7 @@ private: SeekerSlider *m_seeker = nullptr; int particlemode; ModelCache m_canvasCache; + ModelNode m_droppedMaterial; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index afa05dd67e2..a6672b9f164 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -242,12 +242,28 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent) { const DesignerActionManager &actionManager = QmlDesignerPlugin::instance() ->viewManager().designerActionManager(); - if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())) + if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()) + || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) { dragEnterEvent->acceptProposedAction(); + } } void Edit3DWidget::dropEvent(QDropEvent *dropEvent) { + // handle dropping materials + if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)) { + QByteArray data = dropEvent->mimeData()->data(Constants::MIME_TYPE_MATERIAL); + QDataStream stream(data); + qint32 internalId; + stream >> internalId; + ModelNode matNode = m_view->modelNodeForInternalId(internalId); + + if (matNode.isValid()) + m_view->dropMaterial(matNode, dropEvent->position()); + return; + } + + // handle dropping external assets const DesignerActionManager &actionManager = QmlDesignerPlugin::instance() ->viewManager().designerActionManager(); QHash addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData()); diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 890b5c0e9cf..3c4eca04413 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -165,6 +165,7 @@ public: void emitUpdateActiveScene3D(const QVariantMap &sceneState); void emitModelNodelPreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); void emitImport3DSupportChanged(const QVariantMap &supportMap); + void emitModelAtPosResult(const ModelNode &modelNode); void sendTokenToInstances(const QString &token, int number, const QVector &nodeVector); @@ -229,6 +230,7 @@ public: virtual void renderImage3DChanged(const QImage &image); virtual void updateActiveScene3D(const QVariantMap &sceneState); virtual void updateImport3DSupport(const QVariantMap &supportMap); + virtual void modelAtPosReady(const ModelNode &modelNode); virtual void modelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); virtual void dragStarted(QMimeData *mimeData); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 6a7ad61276d..f92df89a9db 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1691,6 +1691,10 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand } else if (command.type() == PuppetToCreatorCommand::Import3DSupport) { const QVariantMap supportMap = qvariant_cast(command.data()); emitImport3DSupportChanged(supportMap); + } else if (command.type() == PuppetToCreatorCommand::ModelAtPos) { + ModelNode modelNode = modelNodeForInternalId(command.data().toUInt()); + if (modelNode.isValid()) + emitModelAtPosResult(modelNode); } } diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 23c018f7cb3..310dcdcdab1 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -403,6 +403,9 @@ void AbstractView::updateImport3DSupport(const QVariantMap & /*supportMap*/) { } +// a Quick3DModel that is picked at the requested position in the 3D Editor +void AbstractView::modelAtPosReady(const ModelNode & /*modelNode*/) {} + void AbstractView::modelNodePreviewPixmapChanged(const ModelNode & /*node*/, const QPixmap & /*pixmap*/) { } @@ -794,6 +797,12 @@ void AbstractView::emitImport3DSupportChanged(const QVariantMap &supportMap) model()->d->notifyImport3DSupportChanged(supportMap); } +void AbstractView::emitModelAtPosResult(const ModelNode &modelNode) +{ + if (model()) + model()->d->notifyModelAtPosResult(modelNode); +} + void AbstractView::emitRewriterEndTransaction() { if (model()) diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index bd92ac643fb..772149a33d9 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -589,6 +589,11 @@ void ModelPrivate::notifyImport3DSupportChanged(const QVariantMap &supportMap) notifyInstanceChanges([&](AbstractView *view) { view->updateImport3DSupport(supportMap); }); } +void ModelPrivate::notifyModelAtPosResult(const ModelNode &modelNode) +{ + notifyInstanceChanges([&](AbstractView *view) { view->modelAtPosReady(modelNode); }); +} + void ModelPrivate::notifyDragStarted(QMimeData *mimeData) { notifyInstanceChanges([&](AbstractView *view) { view->dragStarted(mimeData); }); diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index 09595670534..c6ed24f681f 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -182,6 +182,7 @@ public: void notifyUpdateActiveScene3D(const QVariantMap &sceneState); void notifyModelNodePreviewPixmapChanged(const ModelNode &node, const QPixmap &pixmap); void notifyImport3DSupportChanged(const QVariantMap &supportMap); + void notifyModelAtPosResult(const ModelNode &modelNode); void notifyDragStarted(QMimeData *mimeData); void notifyDragEnded();