QmlDesigner: Allow drag from assets to 3D model in navigator and 3D view

Fixes: QDS-8784
Fixes: QDS-8785
Change-Id: Ib33fe615137c3c29d9071cab01ba26f6b4f751af
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2023-02-28 12:25:09 +02:00
parent 8aa9fae33a
commit 47cabc308e
8 changed files with 77 additions and 9 deletions

View File

@@ -36,7 +36,7 @@ class CreateTextures : public CreateTexture
{ {
public: public:
using CreateTexture::CreateTexture; using CreateTexture::CreateTexture;
void execute(const QStringList &filePaths, AddTextureMode mode, int sceneId) void execute(const QStringList &filePaths, AddTextureMode mode, int sceneId = -1)
{ {
for (const QString &path : filePaths) for (const QString &path : filePaths)
CreateTexture::execute(path, mode, sceneId); CreateTexture::execute(path, mode, sceneId);

View File

@@ -330,7 +330,7 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
setSelectedModelNode(createdNode); setSelectedModelNode(createdNode);
} else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) { } else if (m_nodeAtPosReqType == NodeAtPosReqType::MaterialDrop) {
bool isModel = modelNode.metaInfo().isQtQuick3DModel(); bool isModel = modelNode.metaInfo().isQtQuick3DModel();
if (m_droppedModelNode.isValid() && modelNode.isValid() && isModel) { if (m_droppedModelNode.isValid() && isModel) {
executeInTransaction(__FUNCTION__, [&] { executeInTransaction(__FUNCTION__, [&] {
assignMaterialTo3dModel(modelNode, m_droppedModelNode); assignMaterialTo3dModel(modelNode, m_droppedModelNode);
}); });
@@ -339,9 +339,14 @@ void Edit3DView::nodeAtPosReady(const ModelNode &modelNode, const QVector3D &pos
emitCustomNotification("drop_bundle_material", {modelNode}); // To ContentLibraryView emitCustomNotification("drop_bundle_material", {modelNode}); // To ContentLibraryView
} else if (m_nodeAtPosReqType == NodeAtPosReqType::TextureDrop) { } else if (m_nodeAtPosReqType == NodeAtPosReqType::TextureDrop) {
emitCustomNotification("apply_texture_to_model3D", {modelNode, m_droppedModelNode}); emitCustomNotification("apply_texture_to_model3D", {modelNode, m_droppedModelNode});
} else if (m_nodeAtPosReqType == NodeAtPosReqType::AssetDrop) {
bool isModel = modelNode.metaInfo().isQtQuick3DModel();
if (!m_droppedFile.isEmpty() && isModel)
emitCustomNotification("apply_asset_to_model3D", {modelNode}, {m_droppedFile}); // To MaterialBrowserView
} }
m_droppedModelNode = {}; m_droppedModelNode = {};
m_droppedFile.clear();
m_nodeAtPosReqType = NodeAtPosReqType::None; m_nodeAtPosReqType = NodeAtPosReqType::None;
} }
@@ -926,4 +931,11 @@ void Edit3DView::dropComponent(const ItemLibraryEntry &entry, const QPointF &pos
nodeAtPosReady({}, {}); // No need to actually resolve position for non-node items nodeAtPosReady({}, {}); // No need to actually resolve position for non-node items
} }
void Edit3DView::dropAsset(const QString &file, const QPointF &pos)
{
m_nodeAtPosReqType = NodeAtPosReqType::AssetDrop;
m_droppedFile = file;
emitView3DAction(View3DActionType::GetNodeAtPos, pos);
}
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -64,6 +64,7 @@ public:
void dropBundleMaterial(const QPointF &pos); void dropBundleMaterial(const QPointF &pos);
void dropTexture(const ModelNode &textureNode, const QPointF &pos); void dropTexture(const ModelNode &textureNode, const QPointF &pos);
void dropComponent(const ItemLibraryEntry &entry, const QPointF &pos); void dropComponent(const ItemLibraryEntry &entry, const QPointF &pos);
void dropAsset(const QString &file, const QPointF &pos);
private slots: private slots:
void onEntriesChanged(); void onEntriesChanged();
@@ -75,6 +76,7 @@ private:
MaterialDrop, MaterialDrop,
TextureDrop, TextureDrop,
ContextMenu, ContextMenu,
AssetDrop,
None None
}; };
@@ -124,6 +126,7 @@ private:
ModelCache<QImage> m_canvasCache; ModelCache<QImage> m_canvasCache;
ModelNode m_droppedModelNode; ModelNode m_droppedModelNode;
ItemLibraryEntry m_droppedEntry; ItemLibraryEntry m_droppedEntry;
QString m_droppedFile;
NodeAtPosReqType m_nodeAtPosReqType; NodeAtPosReqType m_nodeAtPosReqType;
QPoint m_contextMenuPos; QPoint m_contextMenuPos;
QTimer m_compressionTimer; QTimer m_compressionTimer;

View File

@@ -28,6 +28,7 @@
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <toolbox.h> #include <toolbox.h>
#include <utils/asset.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/utilsicons.h> #include <utils/utilsicons.h>
@@ -498,10 +499,18 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance() const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager(); ->viewManager().designerActionManager();
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()) if (dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ASSETS)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL) || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL) const auto urls = dragEnterEvent->mimeData()->urls();
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_TEXTURE)) { if (!urls.isEmpty()) {
Asset asset(urls.first().toLocalFile());
if (asset.isTexture3D() || asset.isImage())
dragEnterEvent->acceptProposedAction();
}
} else if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_MATERIAL)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_TEXTURE)) {
dragEnterEvent->acceptProposedAction(); dragEnterEvent->acceptProposedAction();
} else if (dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) { } else if (dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
QByteArray data = dragEnterEvent->mimeData()->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO); QByteArray data = dragEnterEvent->mimeData()->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
@@ -552,6 +561,14 @@ void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
return; return;
} }
// handle dropping image assets
if (dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_ASSETS)
|| dropEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
m_view->dropAsset(dropEvent->mimeData()->urls().first().toLocalFile(), pos);
m_view->model()->endDrag();
return;
}
// handle dropping external assets // handle dropping external assets
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance() const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
->viewManager().designerActionManager(); ->viewManager().designerActionManager();

View File

@@ -21,6 +21,9 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -517,7 +520,7 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
}); });
} else if (identifier == "delete_selected_material") { } else if (identifier == "delete_selected_material") {
m_widget->deleteSelectedItem(); m_widget->deleteSelectedItem();
} else if (identifier == "apply_bundle_texture_to_model3D") { } else if (identifier == "apply_asset_to_model3D") {
m_appliedTexturePath = data.at(0).toString(); m_appliedTexturePath = data.at(0).toString();
applyTextureToModel3D(nodeList.at(0)); applyTextureToModel3D(nodeList.at(0));
} else if (identifier == "apply_texture_to_model3D") { } else if (identifier == "apply_texture_to_model3D") {
@@ -645,7 +648,16 @@ void MaterialBrowserView::applyTextureToProperty(const QString &matId, const QSt
{ {
executeInTransaction(__FUNCTION__, [&] { executeInTransaction(__FUNCTION__, [&] {
if (m_appliedTextureId.isEmpty() && !m_appliedTexturePath.isEmpty()) { if (m_appliedTextureId.isEmpty() && !m_appliedTexturePath.isEmpty()) {
auto texCreator = new CreateTexture(this, true); bool import = true;
using namespace ProjectExplorer;
if (Project *proj = ProjectTree::currentProject()) {
Utils::FilePath projDir = proj->projectFilePath().parentDir().pathAppended("content");
if (m_appliedTexturePath.startsWith(projDir.toString()))
import = false;
}
auto texCreator = new CreateTexture(this, import);
ModelNode tex = texCreator->execute(m_appliedTexturePath, AddTextureMode::Texture); ModelNode tex = texCreator->execute(m_appliedTexturePath, AddTextureMode::Texture);
m_appliedTextureId = tex.id(); m_appliedTextureId = tex.id();
m_appliedTexturePath.clear(); m_appliedTexturePath.clear();

View File

@@ -221,6 +221,11 @@ void NameItemDelegate::paint(QPainter *painter,
bool validDrop = false; bool validDrop = false;
if (dragType == Constants::MIME_TYPE_BUNDLE_TEXTURE) { if (dragType == Constants::MIME_TYPE_BUNDLE_TEXTURE) {
validDrop = metaInfo.isQtQuick3DModel(); validDrop = metaInfo.isQtQuick3DModel();
} else if (dragType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
validDrop = metaInfo.isQtQuick3DModel() || metaInfo.isQtQuick3DTexture();
} else if (dragType == Constants::MIME_TYPE_ASSET_IMAGE) {
validDrop = metaInfo.isQtQuick3DModel() || metaInfo.isQtQuick3DTexture()
|| metaInfo.isQtQuickImage() || metaInfo.isQtQuickBorderImage();
} else { } else {
const NodeMetaInfo dragInfo = node.model()->metaInfo(dragType); const NodeMetaInfo dragInfo = node.model()->metaInfo(dragType);
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(dragInfo, metaInfo, true); ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(dragInfo, metaInfo, true);

View File

@@ -558,7 +558,7 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
QByteArray filePath = mimeData->data(Constants::MIME_TYPE_BUNDLE_TEXTURE); QByteArray filePath = mimeData->data(Constants::MIME_TYPE_BUNDLE_TEXTURE);
ModelNode targetNode(modelNodeForIndex(dropModelIndex)); ModelNode targetNode(modelNodeForIndex(dropModelIndex));
if (targetNode.metaInfo().isQtQuick3DModel()) if (targetNode.metaInfo().isQtQuick3DModel())
m_view->emitCustomNotification("apply_bundle_texture_to_model3D", {targetNode}, {filePath}); // To MaterialBrowserView m_view->emitCustomNotification("apply_asset_to_model3D", {targetNode}, {filePath}); // To MaterialBrowserView
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) { } else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
ModelNode targetNode(modelNodeForIndex(dropModelIndex)); ModelNode targetNode(modelNodeForIndex(dropModelIndex));
if (targetNode.isValid()) if (targetNode.isValid())
@@ -636,6 +636,9 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
} }
} }
if (m_view && m_view->model())
m_view->model()->endDrag();
return true; return true;
} }
@@ -1120,6 +1123,16 @@ bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
// if dropping an image on an existing texture, set the source // if dropping an image on an existing texture, set the source
targetNode.variantProperty("source").setValue(imagePath); targetNode.variantProperty("source").setValue(imagePath);
return true; return true;
} else if (targetNode.metaInfo().isQtQuick3DModel()) {
QTimer::singleShot(0, this, [this, targetNode, imagePath]() {
if (m_view && targetNode.isValid()) {
// To MaterialBrowserView. Done async to avoid custom notification in transaction
m_view->emitCustomNotification(
"apply_asset_to_model3D", {targetNode},
{DocumentManager::currentFilePath().absolutePath().pathAppended(imagePath).cleanPath().toString()});
}
});
return true;
} }
return false; return false;

View File

@@ -288,6 +288,12 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
// specific type // specific type
m_widget->setDragType(Storage::Info::EffectMaker); m_widget->setDragType(Storage::Info::EffectMaker);
m_widget->update(); m_widget->update();
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
m_widget->setDragType(Constants::MIME_TYPE_ASSET_TEXTURE3D);
m_widget->update();
} else if (assetType == Constants::MIME_TYPE_ASSET_IMAGE) {
m_widget->setDragType(Constants::MIME_TYPE_ASSET_IMAGE);
m_widget->update();
} }
} }
} }