QmlDesigner: Allow dragging bundle textures to Navigator

Fixes: QDS-8338
Change-Id: Id5d02c4e5ed84f3592c19299b1d33dbe9b5cc486
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2023-01-25 12:48:05 +02:00
parent d1848912a2
commit 0b8d2c15ca
7 changed files with 90 additions and 49 deletions

View File

@@ -5,14 +5,18 @@
#include <modelnode.h>
#include <QObject>
namespace QmlDesigner {
class AbstractView;
enum class AddTextureMode { Image, Texture, LightProbe };
class CreateTexture
class CreateTexture : public QObject
{
Q_OBJECT
public:
CreateTexture(AbstractView *view, bool importFiles = false);
ModelNode execute(const QString &filePath, AddTextureMode mode, int sceneId = -1);

View File

@@ -483,7 +483,7 @@ void MaterialBrowserView::importsChanged([[maybe_unused]] const QList<Import> &a
void MaterialBrowserView::customNotification(const AbstractView *view,
const QString &identifier,
const QList<ModelNode> &nodeList,
[[maybe_unused]] const QList<QVariant> &data)
const QList<QVariant> &data)
{
if (view == this)
return;
@@ -504,6 +504,9 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
});
} else if (identifier == "delete_selected_material") {
m_widget->deleteSelectedItem();
} else if (identifier == "apply_bundle_texture_to_model3D") {
m_appliedTexturePath = data.at(0).toString();
applyTextureToModel3D(nodeList.at(0));
} else if (identifier == "apply_texture_to_model3D") {
applyTextureToModel3D(nodeList.at(0), nodeList.at(1));
} else if (identifier == "apply_texture_to_material") {
@@ -557,7 +560,10 @@ void MaterialBrowserView::instancePropertyChanged(const QList<QPair<ModelNode, P
void MaterialBrowserView::applyTextureToModel3D(const QmlObjectNode &model3D, const ModelNode &texture)
{
if (!texture.isValid() || !model3D.isValid() || !model3D.modelNode().metaInfo().isQtQuick3DModel())
if (!texture.isValid() && m_appliedTexturePath.isEmpty())
return;
if (!model3D.isValid() || !model3D.modelNode().metaInfo().isQtQuick3DModel())
return;
BindingProperty matsProp = model3D.bindingProperty("materials");
@@ -573,42 +579,45 @@ void MaterialBrowserView::applyTextureToModel3D(const QmlObjectNode &model3D, co
void MaterialBrowserView::applyTextureToMaterial(const QList<ModelNode> &materials,
const ModelNode &texture)
{
if (materials.size() > 0) {
if (materials.isEmpty())
return;
if (texture.isValid())
m_appliedTextureId = texture.id();
m_textureModels.clear();
QStringList materialsModel;
for (const ModelNode &mat : std::as_const(materials)) {
QString matName = mat.variantProperty("objectName").value().toString();
materialsModel.append(QLatin1String("%1 (%2)").arg(matName, mat.id()));
QList<PropertyName> texProps;
for (const PropertyMetaInfo &p : mat.metaInfo().properties()) {
if (p.propertyType().isQtQuick3DTexture())
texProps.append(p.name());
}
m_textureModels.insert(mat.id(), texProps);
m_textureModels.clear();
QStringList materialsModel;
for (const ModelNode &mat : std::as_const(materials)) {
QString matName = mat.variantProperty("objectName").value().toString();
materialsModel.append(QLatin1String("%1 (%2)").arg(matName, mat.id()));
QList<PropertyName> texProps;
for (const PropertyMetaInfo &p : mat.metaInfo().properties()) {
if (p.propertyType().isQtQuick3DTexture())
texProps.append(p.name());
}
QString path = MaterialBrowserWidget::qmlSourcesPath() + "/ChooseMaterialProperty.qml";
m_chooseMatPropsView = new QQuickView;
m_chooseMatPropsView->setTitle(tr("Select a material property"));
m_chooseMatPropsView->setResizeMode(QQuickView::SizeRootObjectToView);
m_chooseMatPropsView->setMinimumSize({150, 100});
m_chooseMatPropsView->setMaximumSize({600, 400});
m_chooseMatPropsView->setWidth(450);
m_chooseMatPropsView->setHeight(300);
m_chooseMatPropsView->setFlags(Qt::Widget);
m_chooseMatPropsView->setModality(Qt::ApplicationModal);
m_chooseMatPropsView->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_chooseMatPropsView->rootContext()->setContextProperties({
{"rootView", QVariant::fromValue(this)},
{"materialsModel", QVariant::fromValue(materialsModel)},
{"propertiesModel", QVariant::fromValue(m_textureModels.value(materials.at(0).id()))},
});
m_chooseMatPropsView->setSource(QUrl::fromLocalFile(path));
m_chooseMatPropsView->installEventFilter(this);
m_chooseMatPropsView->show();
m_textureModels.insert(mat.id(), texProps);
}
QString path = MaterialBrowserWidget::qmlSourcesPath() + "/ChooseMaterialProperty.qml";
m_chooseMatPropsView = new QQuickView;
m_chooseMatPropsView->setTitle(tr("Select a material property"));
m_chooseMatPropsView->setResizeMode(QQuickView::SizeRootObjectToView);
m_chooseMatPropsView->setMinimumSize({150, 100});
m_chooseMatPropsView->setMaximumSize({600, 400});
m_chooseMatPropsView->setWidth(450);
m_chooseMatPropsView->setHeight(300);
m_chooseMatPropsView->setFlags(Qt::Widget);
m_chooseMatPropsView->setModality(Qt::ApplicationModal);
m_chooseMatPropsView->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_chooseMatPropsView->rootContext()->setContextProperties({
{"rootView", QVariant::fromValue(this)},
{"materialsModel", QVariant::fromValue(materialsModel)},
{"propertiesModel", QVariant::fromValue(m_textureModels.value(materials.at(0).id()))},
});
m_chooseMatPropsView->setSource(QUrl::fromLocalFile(path));
m_chooseMatPropsView->installEventFilter(this);
m_chooseMatPropsView->show();
}
void MaterialBrowserView::updatePropsModel(const QString &matId)
@@ -619,17 +628,27 @@ void MaterialBrowserView::updatePropsModel(const QString &matId)
void MaterialBrowserView::applyTextureToProperty(const QString &matId, const QString &propName)
{
QTC_ASSERT(!m_appliedTextureId.isEmpty(), return);
executeInTransaction(__FUNCTION__, [&] {
if (m_appliedTextureId.isEmpty() && !m_appliedTexturePath.isEmpty()) {
auto texCreator = new CreateTexture(this, true);
ModelNode tex = texCreator->execute(m_appliedTexturePath, AddTextureMode::Texture);
m_appliedTextureId = tex.id();
m_appliedTexturePath.clear();
texCreator->deleteLater();
}
QmlObjectNode mat = modelNodeForId(matId);
QTC_ASSERT(mat.isValid(), return);
QTC_ASSERT(!m_appliedTextureId.isEmpty(), return);
BindingProperty texProp = mat.bindingProperty(propName.toLatin1());
QTC_ASSERT(texProp.isValid(), return);
QmlObjectNode mat = modelNodeForId(matId);
QTC_ASSERT(mat.isValid(), return);
mat.setBindingProperty(propName.toLatin1(), m_appliedTextureId);
BindingProperty texProp = mat.bindingProperty(propName.toLatin1());
QTC_ASSERT(texProp.isValid(), return);
closeChooseMatPropsView();
mat.setBindingProperty(propName.toLatin1(), m_appliedTextureId);
closeChooseMatPropsView();
});
}
void MaterialBrowserView::closeChooseMatPropsView()
@@ -648,6 +667,7 @@ bool MaterialBrowserView::eventFilter(QObject *obj, QEvent *event)
} else if (event->type() == QEvent::Close) {
if (obj == m_chooseMatPropsView) {
m_appliedTextureId.clear();
m_appliedTexturePath.clear();
m_chooseMatPropsView->deleteLater();
}
}

View File

@@ -4,7 +4,6 @@
#pragma once
#include "abstractview.h"
#include "createtexture.h"
#include <QPointer>
#include <QSet>
@@ -53,7 +52,7 @@ public:
void active3DSceneChanged(qint32 sceneId) override;
void currentStateChanged(const ModelNode &node) override;
void applyTextureToModel3D(const QmlObjectNode &model3D, const ModelNode &texture);
void applyTextureToModel3D(const QmlObjectNode &model3D, const ModelNode &texture = {});
void applyTextureToMaterial(const QList<ModelNode> &materials, const ModelNode &texture);
@@ -87,6 +86,7 @@ private:
QPointer<QQuickView> m_chooseMatPropsView;
QHash<QString, QList<PropertyName>> m_textureModels;
QString m_appliedTextureId;
QString m_appliedTexturePath; // defers texture creation until dialog apply
int m_sceneId = -1;
};

View File

@@ -13,6 +13,7 @@
#include <metainfo.h>
#include <modelnodecontextmenu.h>
#include <qmldesignerconstants.h>
#include <qmlobjectnode.h>
#include <theme.h>
@@ -216,17 +217,23 @@ void NameItemDelegate::paint(QPainter *painter,
if (widget && !widget->dragType().isEmpty()) {
QByteArray dragType = widget->dragType();
const NodeMetaInfo metaInfo = node.metaInfo();
const NodeMetaInfo dragInfo = node.model()->metaInfo(dragType);
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(dragInfo, metaInfo, true);
if (!filter->propertyList.isEmpty()) {
bool validDrop = false;
if (dragType == Constants::MIME_TYPE_BUNDLE_TEXTURE) {
validDrop = metaInfo.isQtQuick3DModel();
} else {
const NodeMetaInfo dragInfo = node.model()->metaInfo(dragType);
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(dragInfo, metaInfo, true);
validDrop = !filter->propertyList.isEmpty();
delete filter;
}
if (validDrop) {
painter->setOpacity(0.5);
painter->fillRect(styleOption.rect.adjusted(0, delegateMargin, 0, -delegateMargin),
Theme::getColor(Theme::Color::DSnavigatorDropIndicatorBackground));
painter->setOpacity(1.0);
painter->setPen(Theme::getColor(Theme::Color::DSnavigatorTextSelected));
}
delete filter;
}
}

View File

@@ -453,6 +453,7 @@ QStringList NavigatorTreeModel::mimeTypes() const
Constants::MIME_TYPE_ITEM_LIBRARY_INFO,
Constants::MIME_TYPE_TEXTURE,
Constants::MIME_TYPE_MATERIAL,
Constants::MIME_TYPE_BUNDLE_TEXTURE,
Constants::MIME_TYPE_BUNDLE_MATERIAL,
Constants::MIME_TYPE_ASSETS});
@@ -553,6 +554,11 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
handleTextureDrop(mimeData, dropModelIndex);
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
handleMaterialDrop(mimeData, dropModelIndex);
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
QByteArray filePath = mimeData->data(Constants::MIME_TYPE_BUNDLE_TEXTURE);
ModelNode targetNode(modelNodeForIndex(dropModelIndex));
if (targetNode.metaInfo().isQtQuick3DModel())
m_view->emitCustomNotification("apply_bundle_texture_to_model3D", {targetNode}, {filePath}); // To MaterialBrowserView
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
ModelNode targetNode(modelNodeForIndex(dropModelIndex));
if (targetNode.isValid())

View File

@@ -267,6 +267,9 @@ void NavigatorView::dragStarted(QMimeData *mimeData)
m_widget->setDragType(matNode.metaInfo().typeName());
m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
m_widget->setDragType(Constants::MIME_TYPE_BUNDLE_TEXTURE);
m_widget->update();
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_MATERIAL)) {
QByteArray data = mimeData->data(Constants::MIME_TYPE_BUNDLE_MATERIAL);
QDataStream stream(data);

View File

@@ -511,6 +511,7 @@ void PropertyEditorValue::commitDrop(const QString &dropData)
bool needsImport = !imagePath.isChildOf(QmlDesigner::DocumentManager::currentResourcePath());
auto texCreator = new QmlDesigner::CreateTexture(m_modelNode.view(), needsImport);
texture = texCreator->execute(imagePath.toString(), QmlDesigner::AddTextureMode::Texture);
texCreator->deleteLater();
}
// assign the texture to the property