From e774aa238be546812754d7ab5497f8603fe51f62 Mon Sep 17 00:00:00 2001 From: Samuel Ghinet Date: Thu, 24 Nov 2022 19:23:03 +0200 Subject: Add "Add Texture" and "Add Light Probe" actions to Assets Library When the user right-clicks on an image asset, "Add Light probe" now appears in the context menu. When the user right-clicks one or more image assets, "Add texture" or "Add textures" becomes available. Task-number: QDS-8344 Change-Id: Ia8d8379be2a0a285b33e4a230e08527c18756b47 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- .../itemLibraryQmlSources/AssetsContextMenu.qml | 26 ++++- src/plugins/qmldesigner/CMakeLists.txt | 1 + src/plugins/qmldesigner/components/addtexture.h | 10 ++ .../assetslibrary/assetslibrarymodel.cpp | 12 ++- .../components/assetslibrary/assetslibrarymodel.h | 1 + .../components/assetslibrary/assetslibraryview.cpp | 12 ++- .../assetslibrary/assetslibrarywidget.cpp | 11 ++ .../components/assetslibrary/assetslibrarywidget.h | 4 + .../contentlibrary/contentlibraryview.cpp | 50 +-------- .../contentlibrary/contentlibrarywidget.h | 6 +- .../materialbrowser/materialbrowserview.cpp | 117 ++++++++++++++++++++- .../materialbrowser/materialbrowserview.h | 8 ++ 12 files changed, 200 insertions(+), 58 deletions(-) create mode 100644 src/plugins/qmldesigner/components/addtexture.h diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml index 87c0966366..6dedaf7901 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/AssetsContextMenu.qml @@ -50,8 +50,13 @@ StudioControls.Menu { function openContextMenuForFile(fileIndex, dirModelIndex, selectedAssetPathsList, onFolderCreated) { - var numSelected = selectedAssetPathsList.filter(p => p).length - deleteFileItem.text = numSelected > 1 ? qsTr("Delete Files") : qsTr("Delete File") + if (selectedAssetPathsList.length > 1) { + deleteFileItem.text = qsTr("Delete Files") + addTexturesItem.text = qsTr("Add Textures") + } else { + deleteFileItem.text = qsTr("Delete File") + addTexturesItem.text = qsTr("Add Texture") + } root.__onFolderCreated = onFolderCreated root.__selectedAssetPathsList = selectedAssetPathsList @@ -83,6 +88,23 @@ StudioControls.Menu { height: visible ? StudioTheme.Values.border : 0 } + StudioControls.MenuItem { + id: addTexturesItem + text: qsTr("Add Texture") + visible: root.__fileIndex && assetsModel.allFilePathsAreImages(root.__selectedAssetPathsList) + height: addTexturesItem.visible ? addTexturesItem.implicitHeight : 0 + onTriggered: rootView.addTextures(root.__selectedAssetPathsList) + } + + StudioControls.MenuItem { + id: addLightProbes + text: qsTr("Add Light Probe") + visible: root.__fileIndex && root.__selectedAssetPathsList.length === 1 + && assetsModel.allFilePathsAreImages(root.__selectedAssetPathsList) + height: addLightProbes.visible ? addLightProbes.implicitHeight : 0 + onTriggered: rootView.addLightProbe(root.__selectedAssetPathsList[0]) + } + StudioControls.MenuItem { id: deleteFileItem text: qsTr("Delete File") diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 7abed7212d..01fd880263 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -588,6 +588,7 @@ extend_qtc_plugin(QmlDesigner PUBLIC_INCLUDES components DEFINES QMLDESIGNERCOMPONENTS_LIBRARY SOURCES + addtexture.h qmldesignercomponents_global.h ) diff --git a/src/plugins/qmldesigner/components/addtexture.h b/src/plugins/qmldesigner/components/addtexture.h new file mode 100644 index 0000000000..8547b4bf84 --- /dev/null +++ b/src/plugins/qmldesigner/components/addtexture.h @@ -0,0 +1,10 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 + +#pragma once + +namespace QmlDesigner { + +enum class AddTextureMode { Image, Texture, LightProbe }; + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp index 83683096e9..864660a147 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.cpp @@ -10,10 +10,11 @@ #include "assetslibrarymodel.h" -#include #include +#include #include +#include #include namespace QmlDesigner { @@ -179,6 +180,15 @@ bool AssetsLibraryModel::deleteFolderRecursively(const QModelIndex &folderIndex) return ok; } +bool AssetsLibraryModel::allFilePathsAreImages(const QStringList &filePaths) const +{ + return Utils::allOf(filePaths, [](const QString &path) { + const QString suffix = "*." + path.split('.').last().toLower(); + + return AssetsLibraryModel::supportedImageSuffixes().contains(suffix); + }); +} + bool AssetsLibraryModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { QString path = m_sourceFsModel->filePath(sourceParent); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h index 82cf2b3ca2..f73d7fb7e3 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarymodel.h @@ -44,6 +44,7 @@ public: Q_INVOKABLE bool renameFolder(const QString &folderPath, const QString &newName); Q_INVOKABLE bool addNewFolder(const QString &folderPath); Q_INVOKABLE bool deleteFolderRecursively(const QModelIndex &folderIndex); + Q_INVOKABLE bool allFilePathsAreImages(const QStringList &filePaths) const; int columnCount(const QModelIndex &parent = QModelIndex()) const override { diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp index 56a536c82e..94e8c6412e 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibraryview.cpp @@ -2,8 +2,9 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 #include "assetslibraryview.h" + #include "assetslibrarywidget.h" -#include "metainfo.h" +#include "qmldesignerplugin.h" #include #include #include @@ -22,9 +23,7 @@ #include #include #include -#include #include -#include namespace QmlDesigner { @@ -60,6 +59,13 @@ WidgetInfo AssetsLibraryView::widgetInfo() if (m_widget.isNull()) { m_widget = new AssetsLibraryWidget{imageCacheData()->asynchronousFontImageCache, imageCacheData()->synchronousFontImageCache}; + + connect(m_widget, &AssetsLibraryWidget::addTexturesRequested, this, + [&] (const QStringList &filePaths, AddTextureMode mode) { + // to MaterialBrowserView + emitCustomNotification("add_textures", {}, {"AssetsLibraryView::widgetInfo", + filePaths, QVariant::fromValue(mode), false}); + }); } return createWidgetInfo(m_widget.data(), "Assets", WidgetInfo::LeftPane, 0, tr("Assets")); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index 2858febe9f..05ebb72986 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -148,6 +148,17 @@ bool AssetsLibraryWidget::qtVersionIsAtLeast6_4() const return (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)); } + +void AssetsLibraryWidget::addTextures(const QStringList &filePaths) +{ + emit addTexturesRequested(filePaths, AddTextureMode::Texture); +} + +void AssetsLibraryWidget::addLightProbe(const QString &filePath) +{ + emit addTexturesRequested({filePath}, AddTextureMode::LightProbe); +} + void AssetsLibraryWidget::invalidateThumbnail(const QString &id) { m_assetsIconProvider->invalidateThumbnail(id); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h index 1c19c65a3e..4d8737518a 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h @@ -4,6 +4,7 @@ #pragma once #include +#include "addtexture.h" #include "assetslibrarymodel.h" #include @@ -72,6 +73,8 @@ public: Q_INVOKABLE void openEffectMaker(const QString &filePath); Q_INVOKABLE bool qtVersionIsAtLeast6_4() const; Q_INVOKABLE void invalidateThumbnail(const QString &id); + Q_INVOKABLE void addTextures(const QStringList &filePaths); + Q_INVOKABLE void addLightProbe(const QString &filePaths); signals: void itemActivated(const QString &itemName); @@ -79,6 +82,7 @@ signals: const QList &complexFilePaths, const QString &targetDirPath); void directoryCreated(const QString &path); + void addTexturesRequested(const QStringList &filePaths, QmlDesigner::AddTextureMode mode); protected: bool eventFilter(QObject *obj, QEvent *event) override; diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index 5e9f572c7a..58c677039f 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -55,53 +55,9 @@ WidgetInfo ContentLibraryView::widgetInfo() m_draggedBundleTexture = tex; }); connect(m_widget, &ContentLibraryWidget::addTextureRequested, this, - [&] (const QString texPath, ContentLibraryWidget::AddTextureMode mode) { - executeInTransaction("ContentLibraryView::widgetInfo", [&] { - // copy image to project - AddFilesResult result = ModelNodeOperations::addImageToProject({texPath}, "images", false); - - if (result.status() == AddFilesResult::Failed) { - Core::AsynchronousMessageBox::warning(tr("Failed to Add Texture"), - tr("Could not add %1 to project.").arg(texPath)); - return; - } - - if (mode == ContentLibraryWidget::AddTextureMode::Image) - return; - - // create a texture from the image - ModelNode matLib = materialLibraryNode(); - if (!matLib.isValid()) - return; - - NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.Texture"); - - QString sourceVal = QLatin1String("images/%1").arg(texPath.split('/').last()); - ModelNode texNode = getTextureDefaultInstance(sourceVal); - if (!texNode.isValid()) { - texNode = createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), - metaInfo.minorVersion()); - texNode.validId(); - VariantProperty sourceProp = texNode.variantProperty("source"); - sourceProp.setValue(sourceVal); - matLib.defaultNodeListProperty().reparentHere(texNode); - } - - // assign the texture as scene environment's light probe - if (mode == ContentLibraryWidget::AddTextureMode::LightProbe && m_sceneId != -1) { - QmlObjectNode sceneEnv = resolveSceneEnv(); - if (sceneEnv.isValid()) { - sceneEnv.setBindingProperty("lightProbe", texNode.id()); - sceneEnv.setVariantProperty("backgroundMode", - QVariant::fromValue(Enumeration("SceneEnvironment", - "SkyBox"))); - } - } - QTimer::singleShot(0, this, [this, texNode]() { - if (model() && texNode.isValid()) - emitCustomNotification("selected_texture_changed", {texNode}); - }); - }); + [&] (const QString &texPath, AddTextureMode mode) { + emitCustomNotification("add_texture", {}, {"ContentLibraryView::widgetInfo", + texPath, QVariant::fromValue(mode), true}); }); connect(m_widget, &ContentLibraryWidget::updateSceneEnvStateRequested, diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h index b6b24c4dec..f6866e0309 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibrarywidget.h @@ -3,6 +3,8 @@ #pragma once +#include "addtexture.h" + #include #include @@ -55,12 +57,10 @@ public: Q_INVOKABLE void addLightProbe(QmlDesigner::ContentLibraryTexture *tex); Q_INVOKABLE void updateSceneEnvState(); - enum class AddTextureMode { Image, Texture, LightProbe }; - signals: void bundleMaterialDragStarted(QmlDesigner::ContentLibraryMaterial *bundleMat); void bundleTextureDragStarted(QmlDesigner::ContentLibraryTexture *bundleTex); - void addTextureRequested(const QString texPath, QmlDesigner::ContentLibraryWidget::AddTextureMode mode); + void addTextureRequested(const QString texPath, QmlDesigner::AddTextureMode mode); void updateSceneEnvStateRequested(); void hasQuick3DImportChanged(); void hasMaterialLibraryChanged(); diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index cba8f32199..39b9efe13a 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -4,9 +4,10 @@ #include "materialbrowserview.h" #include "bindingproperty.h" -#include "materialbrowserwidget.h" #include "materialbrowsermodel.h" #include "materialbrowsertexturesmodel.h" +#include "materialbrowserwidget.h" +#include "modelnodeoperations.h" #include "nodeabstractproperty.h" #include "nodemetainfo.h" #include "qmlobjectnode.h" @@ -14,11 +15,11 @@ #include #include -#include #include #include #include +#include #include #include @@ -449,7 +450,119 @@ void MaterialBrowserView::customNotification(const AbstractView *view, applyTextureToModel3D(nodeList.at(0), nodeList.at(1)); } else if (identifier == "apply_texture_to_material") { applyTextureToMaterial({nodeList.at(0)}, nodeList.at(1)); + } else if (identifier == "add_textures") { + if (data.size() != 4) { + qWarning() << "Wrong number of arguments passed to add_textures: " << data.size(); + return; + } + + QByteArray identifier = data.at(0).toByteArray(); + QStringList filePaths = data.at(1).toStringList(); + AddTextureMode mode = data.at(2).value(); + bool addToProject = data.at(3).toBool(); + + executeInTransaction(identifier, [&] { + addTextures(filePaths, mode, addToProject); + }); + } else if (identifier == "add_texture") { + if (data.size() != 4) { + qWarning() << "Wrong number of arguments passed to add_texture: " << data.size(); + return; + } + + QByteArray identifier = data.at(0).toByteArray(); + QString filePath = data.at(1).toString(); + AddTextureMode mode = data.at(2).value(); + bool addToProject = data.at(3).toBool(); + + executeInTransaction(identifier, [&] { + addOneTexture(filePath, mode, addToProject); + }); + } +} + +void MaterialBrowserView::addOneTexture(const QString &texPath, AddTextureMode mode, bool addToProject) +{ + if (addToProject) { + // copy image to project + AddFilesResult result = ModelNodeOperations::addImageToProject({texPath}, "images", false); + + if (result.status() == AddFilesResult::Failed) { + Core::AsynchronousMessageBox::warning(tr("Failed to Add Texture"), + tr("Could not add %1 to project.").arg(texPath)); + return; + } + } + + if (mode == AddTextureMode::Image) + return; + + // create a texture from the image + ModelNode matLib = materialLibraryNode(); + if (!matLib.isValid()) + return; + + NodeMetaInfo metaInfo = model()->metaInfo("QtQuick3D.Texture"); + + QString sourceVal = QLatin1String("images/%1").arg(texPath.split('/').last()); + ModelNode texNode = getTextureDefaultInstance(sourceVal); + if (!texNode.isValid()) { + texNode = createModelNode("QtQuick3D.Texture", metaInfo.majorVersion(), + metaInfo.minorVersion()); + texNode.validId(); + VariantProperty sourceProp = texNode.variantProperty("source"); + sourceProp.setValue(sourceVal); + matLib.defaultNodeListProperty().reparentHere(texNode); + } + + // assign the texture as scene environment's light probe + if (mode == AddTextureMode::LightProbe && m_sceneId != -1) { + QmlObjectNode sceneEnv = resolveSceneEnv(); + if (sceneEnv.isValid()) { + sceneEnv.setBindingProperty("lightProbe", texNode.id()); + sceneEnv.setVariantProperty("backgroundMode", + QVariant::fromValue(Enumeration("SceneEnvironment", + "SkyBox"))); + } } + QTimer::singleShot(0, this, [this, texNode]() { + if (model() && texNode.isValid()) + emitCustomNotification("selected_texture_changed", {texNode}); + }); +} + +void MaterialBrowserView::active3DSceneChanged(qint32 sceneId) +{ + m_sceneId = sceneId; +} + +ModelNode MaterialBrowserView::resolveSceneEnv() +{ + ModelNode activeSceneEnv; + + if (m_sceneId != -1) { + ModelNode activeScene = active3DSceneNode(); + if (activeScene.isValid()) { + QmlObjectNode view3D; + if (activeScene.metaInfo().isQtQuick3DView3D()) { + view3D = activeScene; + } else { + ModelNode sceneParent = activeScene.parentProperty().parentModelNode(); + if (sceneParent.metaInfo().isQtQuick3DView3D()) + view3D = sceneParent; + } + if (view3D.isValid()) + activeSceneEnv = modelNodeForId(view3D.expression("environment")); + } + } + + return activeSceneEnv; +} + +void MaterialBrowserView::addTextures(const QStringList &filePaths, AddTextureMode mode, bool addToProject) +{ + for (const QString &texPath : filePaths) + addOneTexture(texPath, mode, addToProject); } void MaterialBrowserView::instancesCompleted(const QVector &completedNodeList) diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h index e8f1160f2f..5b16c0e626 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h @@ -4,6 +4,7 @@ #pragma once #include "abstractview.h" +#include "addtexture.h" #include #include @@ -51,6 +52,8 @@ public: void applyTextureToModel3D(const QmlObjectNode &model3D, const ModelNode &texture); void applyTextureToMaterial(const QList &materials, const ModelNode &texture); + void active3DSceneChanged(qint32 sceneId) override; + Q_INVOKABLE void updatePropsModel(const QString &matId); Q_INVOKABLE void applyTextureToProperty(const QString &matId, const QString &propName); Q_INVOKABLE void closeChooseMatPropsView(); @@ -64,6 +67,10 @@ private: bool isTexture(const ModelNode &node) const; void loadPropertyGroups(); void requestPreviews(); + ModelNode resolveSceneEnv(); + + void addOneTexture(const QString &filePath, AddTextureMode mode, bool addToProject); + void addTextures(const QStringList &texturePaths, AddTextureMode mode, bool addToProject); AsynchronousImageCache &m_imageCache; QPointer m_widget; @@ -79,6 +86,7 @@ private: QPointer m_chooseMatPropsView; QHash> m_textureModels; QString m_appliedTextureId; + int m_sceneId = -1; }; } // namespace QmlDesigner -- cgit v1.2.1