QmlDesigner: Implement drag-n-drop materials to the 3D Editor

Fixes: QDS-7011
Change-Id: Id6e4aea2c19561ea861507480636ae2358ece067
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Mahmoud Badri
2022-07-01 11:35:09 +03:00
parent b5a34902d0
commit 5a9a6804ee
11 changed files with 85 additions and 4 deletions

View File

@@ -40,6 +40,7 @@ public:
ActiveSceneChanged,
RenderModelNodePreviewImage,
Import3DSupport,
ModelAtPos,
None };
PuppetToCreatorCommand(Type type, const QVariant &data);

View File

@@ -59,9 +59,10 @@ public:
SelectBackgroundColor,
SelectGridColor,
ResetBackgroundColor,
GetModelAtPos
};
explicit View3DActionCommand(Type type, const QVariant &value);
View3DActionCommand(Type type, const QVariant &value);
View3DActionCommand() = default;

View File

@@ -2319,6 +2319,32 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
m_particleAnimationDriver->setSeekerPosition(static_cast<const View3DSeekActionCommand &>(command).position());
break;
#endif
#ifdef QUICK3D_MODULE
case View3DActionCommand::GetModelAtPos: {
// pick a Quick3DModel at view position
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
if (!helper)
return;
QQmlProperty editViewProp(m_editView3DData.rootItem, "editView", context());
QObject *obj = qvariant_cast<QObject *>(editViewProp.read());
QQuick3DViewport *editView = qobject_cast<QQuick3DViewport *>(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<QQuick3DModel *>(helper->resolvePick(hitModel));
if (resolvedPick) {
ServerNodeInstance instance = instanceForObject(resolvedPick);
nodeInstanceClient()->handlePuppetToCreatorCommand(
{PuppetToCreatorCommand::ModelAtPos, QVariant(instance.instanceId())});
}
return;
}
#endif
default:
break;
}

View File

@@ -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

View File

@@ -64,6 +64,7 @@ public:
void modelAboutToBeDetached(Model *model) override;
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &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<QImage> m_canvasCache;
ModelNode m_droppedMaterial;
};
} // namespace QmlDesigner

View File

@@ -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<QString, QStringList> addedAssets = actionManager.handleExternalAssetsDrop(dropEvent->mimeData());

View File

@@ -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<ModelNode> &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);

View File

@@ -1691,6 +1691,10 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
} else if (command.type() == PuppetToCreatorCommand::Import3DSupport) {
const QVariantMap supportMap = qvariant_cast<QVariantMap>(command.data());
emitImport3DSupportChanged(supportMap);
} else if (command.type() == PuppetToCreatorCommand::ModelAtPos) {
ModelNode modelNode = modelNodeForInternalId(command.data().toUInt());
if (modelNode.isValid())
emitModelAtPosResult(modelNode);
}
}

View File

@@ -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())

View File

@@ -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); });

View File

@@ -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();