forked from qt-creator/qt-creator
QmlDesigner: Move the functions to handle assets drops
Moving those functions to ModelNodeOperations allows reuse in other views like e.g. the TextEditor. Change-Id: I7eee1c6080b4208ffaab6637f0debf78ec648c8e Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -12,20 +12,22 @@
|
|||||||
#include "addsignalhandlerdialog.h"
|
#include "addsignalhandlerdialog.h"
|
||||||
|
|
||||||
#include <bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
#include <nodelistproperty.h>
|
#include <choosefrompropertylistdialog.h>
|
||||||
#include <nodehints.h>
|
|
||||||
#include <nodemetainfo.h>
|
|
||||||
#include <modelnode.h>
|
|
||||||
#include <qmlitemnode.h>
|
|
||||||
#include <variantproperty.h>
|
|
||||||
#include <rewritingexception.h>
|
|
||||||
#include <rewritertransaction.h>
|
|
||||||
#include <documentmanager.h>
|
#include <documentmanager.h>
|
||||||
#include <qmlanchors.h>
|
#include <itemlibraryentry.h>
|
||||||
#include <nodelistproperty.h>
|
#include <materialutils.h>
|
||||||
#include <nodeproperty.h>
|
#include <modelnode.h>
|
||||||
#include <signalhandlerproperty.h>
|
#include <nodehints.h>
|
||||||
#include <nodeinstanceview.h>
|
#include <nodeinstanceview.h>
|
||||||
|
#include <nodelistproperty.h>
|
||||||
|
#include <nodemetainfo.h>
|
||||||
|
#include <nodeproperty.h>
|
||||||
|
#include <qmlanchors.h>
|
||||||
|
#include <qmlitemnode.h>
|
||||||
|
#include <rewritertransaction.h>
|
||||||
|
#include <rewritingexception.h>
|
||||||
|
#include <signalhandlerproperty.h>
|
||||||
|
#include <variantproperty.h>
|
||||||
|
|
||||||
#include <componentcore_constants.h>
|
#include <componentcore_constants.h>
|
||||||
#include <stylesheetmerger.h>
|
#include <stylesheetmerger.h>
|
||||||
@@ -1739,6 +1741,409 @@ void jumpToCodeOperation(const SelectionContext &selectionState)
|
|||||||
jumpToCode(selectionState.currentSingleSelectedNode());
|
jumpToCode(selectionState.currentSingleSelectedNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const ModelNode &node)
|
||||||
|
{
|
||||||
|
NodeAbstractProperty parentProp = targetProperty.parentProperty();
|
||||||
|
if (parentProp.isValid()) {
|
||||||
|
ModelNode targetModel = parentProp.parentModelNode();
|
||||||
|
parentProp.reparentHere(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetProp.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
if (targetProp.isValid()) {
|
||||||
|
// create a texture item lib
|
||||||
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
|
itemLibraryEntry.setName("Texture");
|
||||||
|
itemLibraryEntry.setType("QtQuick3D.Texture", 1, 0);
|
||||||
|
|
||||||
|
// set texture source
|
||||||
|
PropertyName prop = "source";
|
||||||
|
QString type = "QUrl";
|
||||||
|
QVariant val = imagePath;
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
|
||||||
|
// create a texture
|
||||||
|
ModelNode newModelNode = QmlItemNode::createQmlObjectNode(view,
|
||||||
|
itemLibraryEntry,
|
||||||
|
{},
|
||||||
|
targetProp,
|
||||||
|
false);
|
||||||
|
|
||||||
|
// Rename the node based on source image
|
||||||
|
QFileInfo fi(imagePath);
|
||||||
|
newModelNode.setIdWithoutRefactoring(
|
||||||
|
view->model()->generateNewId(fi.baseName(), "textureImage"));
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dropAsImage3dTexture(const ModelNode &targetNode,
|
||||||
|
const NodeAbstractProperty &targetProp,
|
||||||
|
const QString &imagePath,
|
||||||
|
ModelNode &newNode,
|
||||||
|
bool &outMoveNodesAfter)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
auto bindToProperty = [&](const PropertyName &propName, bool sibling) {
|
||||||
|
view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
||||||
|
newNode = createTextureNode(targetProp, imagePath);
|
||||||
|
if (newNode.isValid()) {
|
||||||
|
targetNode.bindingProperty(propName).setExpression(newNode.validId());
|
||||||
|
|
||||||
|
// If dropping an image on e.g. TextureInput, create a texture on the same level as
|
||||||
|
// target, as the target doesn't support Texture children (QTBUG-86219)
|
||||||
|
if (sibling)
|
||||||
|
outMoveNodesAfter = !moveNodeToParent(targetProp, newNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (targetNode.metaInfo().isQtQuick3DDefaultMaterial()
|
||||||
|
|| targetNode.metaInfo().isQtQuick3DPrincipledMaterial()
|
||||||
|
|| targetNode.metaInfo().isQtQuick3DSpecularGlossyMaterial()) {
|
||||||
|
// if dropping an image on a material, create a texture instead of image
|
||||||
|
// Show texture property selection dialog
|
||||||
|
auto dialog = ChooseFromPropertyListDialog::createIfNeeded(targetNode,
|
||||||
|
view->model()->metaInfo(
|
||||||
|
"QtQuick3D.Texture"),
|
||||||
|
Core::ICore::dialogParent());
|
||||||
|
if (!dialog)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dialog->exec();
|
||||||
|
|
||||||
|
if (dialog->result() == QDialog::Accepted) {
|
||||||
|
view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
||||||
|
newNode = createTextureNode(targetProp, imagePath);
|
||||||
|
if (newNode.isValid()) // Automatically set the texture to selected property
|
||||||
|
targetNode.bindingProperty(dialog->selectedProperty())
|
||||||
|
.setExpression(newNode.validId());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dialog;
|
||||||
|
return true;
|
||||||
|
} else if (targetNode.metaInfo().isQtQuick3DTextureInput()) {
|
||||||
|
bindToProperty("texture", true);
|
||||||
|
return newNode.isValid();
|
||||||
|
} else if (targetNode.metaInfo().isQtQuick3DParticles3DSpriteParticle3D()) {
|
||||||
|
bindToProperty("sprite", false);
|
||||||
|
return newNode.isValid();
|
||||||
|
} else if (targetNode.metaInfo().isQtQuick3DSceneEnvironment()) {
|
||||||
|
bindToProperty("lightProbe", false);
|
||||||
|
return newNode.isValid();
|
||||||
|
} else if (targetNode.metaInfo().isQtQuick3DTexture()) {
|
||||||
|
// if dropping an image on an existing texture, set the source
|
||||||
|
targetNode.variantProperty("source").setValue(imagePath);
|
||||||
|
return true;
|
||||||
|
} else if (targetNode.metaInfo().isQtQuick3DModel()) {
|
||||||
|
QTimer::singleShot(0, view, [targetNode, imagePath, view]() {
|
||||||
|
if (view && targetNode.isValid()) {
|
||||||
|
// To MaterialBrowserView. Done async to avoid custom notification in transaction
|
||||||
|
view->emitCustomNotification("apply_asset_to_model3D",
|
||||||
|
{targetNode},
|
||||||
|
{DocumentManager::currentFilePath()
|
||||||
|
.absolutePath()
|
||||||
|
.pathAppended(imagePath)
|
||||||
|
.cleanPath()
|
||||||
|
.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode handleItemLibraryEffectDrop(const QString &effectPath, const ModelNode &targetNode)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
if ((targetNode.hasParentProperty() && targetNode.parentProperty().name() == "layer.effect")
|
||||||
|
|| !targetNode.metaInfo().isQtQuickItem()) {
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ModelNodeOperations::validateEffect(effectPath)) {
|
||||||
|
bool layerEffect = ModelNodeOperations::useLayerEffect();
|
||||||
|
newModelNode = QmlItemNode::createQmlItemNodeForEffect(view,
|
||||||
|
targetNode,
|
||||||
|
effectPath,
|
||||||
|
layerEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleTextureDrop(const QMimeData *mimeData, const ModelNode &targetModelNode)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetModelNode.view();
|
||||||
|
QTC_ASSERT(view, return );
|
||||||
|
|
||||||
|
QmlObjectNode targetNode(targetModelNode);
|
||||||
|
|
||||||
|
if (!targetNode.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
qint32 internalId = mimeData->data(Constants::MIME_TYPE_TEXTURE).toInt();
|
||||||
|
ModelNode texNode = view->modelNodeForInternalId(internalId);
|
||||||
|
QTC_ASSERT(texNode.isValid(), return );
|
||||||
|
|
||||||
|
if (targetNode.modelNode().metaInfo().isQtQuick3DModel()) {
|
||||||
|
view->emitCustomNotification("apply_texture_to_model3D", {targetNode, texNode});
|
||||||
|
} else {
|
||||||
|
auto *dialog = ChooseFromPropertyListDialog::createIfNeeded(targetNode,
|
||||||
|
texNode,
|
||||||
|
Core::ICore::dialogParent());
|
||||||
|
if (dialog) {
|
||||||
|
bool soloProperty = dialog->isSoloProperty();
|
||||||
|
if (!soloProperty)
|
||||||
|
dialog->exec();
|
||||||
|
|
||||||
|
if (soloProperty || dialog->result() == QDialog::Accepted)
|
||||||
|
targetNode.setBindingProperty(dialog->selectedProperty(), texNode.id());
|
||||||
|
|
||||||
|
delete dialog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleMaterialDrop(const QMimeData *mimeData, const ModelNode &targetNode)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return );
|
||||||
|
|
||||||
|
if (!targetNode.metaInfo().isQtQuick3DModel())
|
||||||
|
return;
|
||||||
|
|
||||||
|
qint32 internalId = mimeData->data(Constants::MIME_TYPE_MATERIAL).toInt();
|
||||||
|
ModelNode matNode = view->modelNodeForInternalId(internalId);
|
||||||
|
|
||||||
|
view->executeInTransaction(__FUNCTION__, [&] {
|
||||||
|
MaterialUtils::assignMaterialTo3dModel(view, targetNode, matNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode handleItemLibraryImageDrop(const QString &imagePath,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
bool &outMoveNodesAfter)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
const QString imagePathRelative
|
||||||
|
= DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
|
||||||
|
imagePath); // relative to .ui.qml file
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
if (!dropAsImage3dTexture(targetNode,
|
||||||
|
targetProperty,
|
||||||
|
imagePathRelative,
|
||||||
|
newModelNode,
|
||||||
|
outMoveNodesAfter)) {
|
||||||
|
if (targetNode.metaInfo().isQtQuickImage() || targetNode.metaInfo().isQtQuickBorderImage()) {
|
||||||
|
// if dropping an image on an existing image, set the source
|
||||||
|
targetNode.variantProperty("source").setValue(imagePathRelative);
|
||||||
|
} else {
|
||||||
|
// create an image
|
||||||
|
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(view,
|
||||||
|
imagePath,
|
||||||
|
QPointF(),
|
||||||
|
targetProperty,
|
||||||
|
false);
|
||||||
|
if (NodeHints::fromModelNode(targetProperty.parentModelNode())
|
||||||
|
.canBeContainerFor(newItemNode.modelNode())) {
|
||||||
|
newModelNode = newItemNode.modelNode();
|
||||||
|
} else {
|
||||||
|
newItemNode.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode handleItemLibraryFontDrop(const QString &fontFamily,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
if (targetNode.metaInfo().isQtQuickText()) {
|
||||||
|
// if dropping into an existing Text, update font
|
||||||
|
targetNode.variantProperty("font.family").setValue(fontFamily);
|
||||||
|
} else {
|
||||||
|
// create a Text node
|
||||||
|
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont(view,
|
||||||
|
fontFamily,
|
||||||
|
QPointF(),
|
||||||
|
targetProperty,
|
||||||
|
false);
|
||||||
|
if (NodeHints::fromModelNode(targetProperty.parentModelNode())
|
||||||
|
.canBeContainerFor(newItemNode.modelNode())) {
|
||||||
|
newModelNode = newItemNode.modelNode();
|
||||||
|
} else {
|
||||||
|
newItemNode.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath,
|
||||||
|
bool isFragShader,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
bool &outMoveNodesAfter)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
|
||||||
|
shaderPath);
|
||||||
|
|
||||||
|
if (targetNode.metaInfo().isQtQuick3DShader()) {
|
||||||
|
// if dropping into an existing Shader, update
|
||||||
|
targetNode.variantProperty("stage").setEnumeration(isFragShader ? "Shader.Fragment"
|
||||||
|
: "Shader.Vertex");
|
||||||
|
targetNode.variantProperty("shader").setValue(relPath);
|
||||||
|
} else {
|
||||||
|
view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
|
||||||
|
// create a new Shader
|
||||||
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
|
itemLibraryEntry.setName("Shader");
|
||||||
|
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
|
||||||
|
|
||||||
|
// set shader properties
|
||||||
|
PropertyName prop = "shader";
|
||||||
|
QString type = "QUrl";
|
||||||
|
QVariant val = relPath;
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
prop = "stage";
|
||||||
|
type = "enum";
|
||||||
|
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
|
||||||
|
// create a texture
|
||||||
|
newModelNode = QmlItemNode::createQmlObjectNode(view,
|
||||||
|
itemLibraryEntry,
|
||||||
|
{},
|
||||||
|
targetProperty,
|
||||||
|
false);
|
||||||
|
|
||||||
|
// Rename the node based on shader source
|
||||||
|
QFileInfo fi(relPath);
|
||||||
|
newModelNode.setIdWithoutRefactoring(
|
||||||
|
view->model()->generateNewId(fi.baseName(), "shader"));
|
||||||
|
// Passes can't have children, so move shader node under parent
|
||||||
|
if (targetProperty.parentModelNode().metaInfo().isQtQuick3DPass()) {
|
||||||
|
BindingProperty listProp = targetNode.bindingProperty("shaders");
|
||||||
|
listProp.addModelNodeToArray(newModelNode);
|
||||||
|
outMoveNodesAfter = !moveNodeToParent(targetProperty, newModelNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode handleItemLibrarySoundDrop(const QString &soundPath,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
|
||||||
|
soundPath);
|
||||||
|
|
||||||
|
if (targetNode.metaInfo().isQtMultimediaSoundEffect()) {
|
||||||
|
// if dropping into on an existing SoundEffect, update
|
||||||
|
targetNode.variantProperty("source").setValue(relPath);
|
||||||
|
} else {
|
||||||
|
// create a new SoundEffect
|
||||||
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
|
itemLibraryEntry.setName("SoundEffect");
|
||||||
|
itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0);
|
||||||
|
|
||||||
|
// set source property
|
||||||
|
PropertyName prop = "source";
|
||||||
|
QString type = "QUrl";
|
||||||
|
QVariant val = relPath;
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
|
||||||
|
// create a texture
|
||||||
|
newModelNode = QmlItemNode::createQmlObjectNode(view,
|
||||||
|
itemLibraryEntry,
|
||||||
|
{},
|
||||||
|
targetProperty,
|
||||||
|
false);
|
||||||
|
|
||||||
|
// Rename the node based on source
|
||||||
|
QFileInfo fi(relPath);
|
||||||
|
newModelNode.setIdWithoutRefactoring(
|
||||||
|
view->model()->generateNewId(fi.baseName(), "soundEffect"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
bool &outMoveNodesAfter)
|
||||||
|
{
|
||||||
|
AbstractView *view = targetNode.view();
|
||||||
|
QTC_ASSERT(view, return {});
|
||||||
|
|
||||||
|
Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D"));
|
||||||
|
if (!view->model()->hasImport(import, true, true))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(
|
||||||
|
tex3DPath); // relative to qml file
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
if (!dropAsImage3dTexture(targetNode,
|
||||||
|
targetProperty,
|
||||||
|
imagePath,
|
||||||
|
newModelNode,
|
||||||
|
outMoveNodesAfter)) {
|
||||||
|
view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
|
||||||
|
// create a standalone Texture3D at drop location
|
||||||
|
newModelNode = createTextureNode(targetProperty, imagePath);
|
||||||
|
if (!NodeHints::fromModelNode(targetProperty.parentModelNode())
|
||||||
|
.canBeContainerFor(newModelNode))
|
||||||
|
newModelNode.destroy();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return newModelNode;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ModelNodeOperations
|
} // namespace ModelNodeOperations
|
||||||
|
|
||||||
} //QmlDesigner
|
} //QmlDesigner
|
||||||
|
@@ -133,6 +133,30 @@ bool validateEffect(const QString &effectPath);
|
|||||||
|
|
||||||
Utils::FilePath getImagesDefaultDirectory();
|
Utils::FilePath getImagesDefaultDirectory();
|
||||||
|
|
||||||
|
//Item Library and Assets related drop operations
|
||||||
|
ModelNode handleItemLibraryEffectDrop(const QString &effectPath, const ModelNode &targetNode);
|
||||||
|
void handleTextureDrop(const QMimeData *mimeData, const ModelNode &targetModelNode);
|
||||||
|
void handleMaterialDrop(const QMimeData *mimeData, const ModelNode &targetNode);
|
||||||
|
ModelNode handleItemLibraryImageDrop(const QString &imagePath,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
bool &outMoveNodesAfter);
|
||||||
|
ModelNode handleItemLibraryFontDrop(const QString &fontFamily,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode);
|
||||||
|
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath,
|
||||||
|
bool isFragShader,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
bool &outMoveNodesAfter);
|
||||||
|
ModelNode handleItemLibrarySoundDrop(const QString &soundPath,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode);
|
||||||
|
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath,
|
||||||
|
NodeAbstractProperty targetProperty,
|
||||||
|
const ModelNode &targetNode,
|
||||||
|
bool &outMoveNodesAfter);
|
||||||
|
|
||||||
// ModelNodePreviewImageOperations
|
// ModelNodePreviewImageOperations
|
||||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
||||||
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
|
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
|
||||||
|
@@ -554,9 +554,13 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
|||||||
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
|
if (mimeData->hasFormat(Constants::MIME_TYPE_ITEM_LIBRARY_INFO)) {
|
||||||
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
} else if (mimeData->hasFormat(Constants::MIME_TYPE_TEXTURE)) {
|
} else if (mimeData->hasFormat(Constants::MIME_TYPE_TEXTURE)) {
|
||||||
handleTextureDrop(mimeData, dropModelIndex);
|
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
||||||
|
ModelNode targetNode = modelNodeForIndex(rowModelIndex);
|
||||||
|
ModelNodeOperations::handleTextureDrop(mimeData, targetNode);
|
||||||
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
|
} else if (mimeData->hasFormat(Constants::MIME_TYPE_MATERIAL)) {
|
||||||
handleMaterialDrop(mimeData, dropModelIndex);
|
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
||||||
|
ModelNode targetNode = modelNodeForIndex(rowModelIndex);
|
||||||
|
ModelNodeOperations::handleMaterialDrop(mimeData, targetNode);
|
||||||
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
|
} else if (mimeData->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
|
||||||
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));
|
||||||
@@ -607,23 +611,36 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
|||||||
QString assetType = assetTypeAndData.first;
|
QString assetType = assetTypeAndData.first;
|
||||||
QString assetData = QString::fromUtf8(assetTypeAndData.second);
|
QString assetData = QString::fromUtf8(assetTypeAndData.second);
|
||||||
if (assetType == Constants::MIME_TYPE_ASSET_IMAGE) {
|
if (assetType == Constants::MIME_TYPE_ASSET_IMAGE) {
|
||||||
currNode = handleItemLibraryImageDrop(assetPath, targetProperty,
|
currNode
|
||||||
rowModelIndex, moveNodesAfter);
|
= ModelNodeOperations::handleItemLibraryImageDrop(assetPath,
|
||||||
|
targetProperty,
|
||||||
|
modelNodeForIndex(
|
||||||
|
rowModelIndex),
|
||||||
|
moveNodesAfter);
|
||||||
} else if (assetType == Constants::MIME_TYPE_ASSET_FONT) {
|
} else if (assetType == Constants::MIME_TYPE_ASSET_FONT) {
|
||||||
currNode = handleItemLibraryFontDrop(assetData, // assetData is fontFamily
|
currNode = ModelNodeOperations::handleItemLibraryFontDrop(
|
||||||
targetProperty, rowModelIndex);
|
assetData, // assetData is fontFamily
|
||||||
|
targetProperty,
|
||||||
|
modelNodeForIndex(rowModelIndex));
|
||||||
} else if (assetType == Constants::MIME_TYPE_ASSET_SHADER) {
|
} else if (assetType == Constants::MIME_TYPE_ASSET_SHADER) {
|
||||||
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f",
|
currNode = ModelNodeOperations::handleItemLibraryShaderDrop(
|
||||||
targetProperty, rowModelIndex,
|
assetPath,
|
||||||
moveNodesAfter);
|
assetData == "f",
|
||||||
|
targetProperty,
|
||||||
|
modelNodeForIndex(rowModelIndex),
|
||||||
|
moveNodesAfter);
|
||||||
} else if (assetType == Constants::MIME_TYPE_ASSET_SOUND) {
|
} else if (assetType == Constants::MIME_TYPE_ASSET_SOUND) {
|
||||||
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty,
|
currNode = ModelNodeOperations::handleItemLibrarySoundDrop(
|
||||||
rowModelIndex);
|
assetPath, targetProperty, modelNodeForIndex(rowModelIndex));
|
||||||
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
|
} else if (assetType == Constants::MIME_TYPE_ASSET_TEXTURE3D) {
|
||||||
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
|
currNode = ModelNodeOperations::handleItemLibraryTexture3dDrop(
|
||||||
rowModelIndex, moveNodesAfter);
|
assetPath,
|
||||||
|
targetProperty,
|
||||||
|
modelNodeForIndex(rowModelIndex),
|
||||||
|
moveNodesAfter);
|
||||||
} else if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
|
} else if (assetType == Constants::MIME_TYPE_ASSET_EFFECT) {
|
||||||
currNode = handleItemLibraryEffectDrop(assetPath, rowModelIndex);
|
currNode = ModelNodeOperations::handleItemLibraryEffectDrop(
|
||||||
|
assetPath, modelNodeForIndex(rowModelIndex));
|
||||||
moveNodesAfter = false;
|
moveNodesAfter = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,109 +802,6 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorTreeModel::handleTextureDrop(const QMimeData *mimeData, const QModelIndex &dropModelIndex)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return);
|
|
||||||
|
|
||||||
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
|
||||||
QmlObjectNode targetNode = modelNodeForIndex(rowModelIndex);
|
|
||||||
if (!targetNode.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
qint32 internalId = mimeData->data(Constants::MIME_TYPE_TEXTURE).toInt();
|
|
||||||
ModelNode texNode = m_view->modelNodeForInternalId(internalId);
|
|
||||||
QTC_ASSERT(texNode.isValid(), return);
|
|
||||||
|
|
||||||
if (targetNode.modelNode().metaInfo().isQtQuick3DModel()) {
|
|
||||||
m_view->emitCustomNotification("apply_texture_to_model3D", {targetNode, texNode});
|
|
||||||
} else {
|
|
||||||
auto *dialog = ChooseFromPropertyListDialog::createIfNeeded(targetNode, texNode, Core::ICore::dialogParent());
|
|
||||||
if (dialog) {
|
|
||||||
bool soloProperty = dialog->isSoloProperty();
|
|
||||||
if (!soloProperty)
|
|
||||||
dialog->exec();
|
|
||||||
|
|
||||||
if (soloProperty || dialog->result() == QDialog::Accepted)
|
|
||||||
targetNode.setBindingProperty(dialog->selectedProperty(), texNode.id());
|
|
||||||
|
|
||||||
delete dialog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigatorTreeModel::handleMaterialDrop(const QMimeData *mimeData, const QModelIndex &dropModelIndex)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return);
|
|
||||||
|
|
||||||
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
|
||||||
ModelNode targetNode = modelNodeForIndex(rowModelIndex);
|
|
||||||
if (!targetNode.metaInfo().isQtQuick3DModel())
|
|
||||||
return;
|
|
||||||
|
|
||||||
qint32 internalId = mimeData->data(Constants::MIME_TYPE_MATERIAL).toInt();
|
|
||||||
ModelNode matNode = m_view->modelNodeForInternalId(internalId);
|
|
||||||
|
|
||||||
m_view->executeInTransaction(__FUNCTION__, [&] {
|
|
||||||
MaterialUtils::assignMaterialTo3dModel(m_view, targetNode, matNode);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
|
|
||||||
NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex,
|
|
||||||
bool &outMoveNodesAfter)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return {});
|
|
||||||
|
|
||||||
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
|
||||||
|
|
||||||
const QString imagePathRelative = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(imagePath); // relative to .ui.qml file
|
|
||||||
|
|
||||||
ModelNode newModelNode;
|
|
||||||
|
|
||||||
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode, outMoveNodesAfter)) {
|
|
||||||
if (targetNode.metaInfo().isQtQuickImage() || targetNode.metaInfo().isQtQuickBorderImage()) {
|
|
||||||
// if dropping an image on an existing image, set the source
|
|
||||||
targetNode.variantProperty("source").setValue(imagePathRelative);
|
|
||||||
} else {
|
|
||||||
// create an image
|
|
||||||
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imagePath, QPointF(), targetProperty, false);
|
|
||||||
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
|
|
||||||
newModelNode = newItemNode.modelNode();
|
|
||||||
else
|
|
||||||
newItemNode.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModelNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamily,
|
|
||||||
NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return {});
|
|
||||||
|
|
||||||
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
|
||||||
|
|
||||||
ModelNode newModelNode;
|
|
||||||
|
|
||||||
if (targetNode.metaInfo().isQtQuickText()) {
|
|
||||||
// if dropping into an existing Text, update font
|
|
||||||
targetNode.variantProperty("font.family").setValue(fontFamily);
|
|
||||||
} else {
|
|
||||||
// create a Text node
|
|
||||||
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont(
|
|
||||||
m_view, fontFamily, QPointF(), targetProperty, false);
|
|
||||||
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
|
|
||||||
newModelNode = newItemNode.modelNode();
|
|
||||||
else
|
|
||||||
newItemNode.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModelNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigatorTreeModel::addImport(const QString &importName)
|
void NavigatorTreeModel::addImport(const QString &importName)
|
||||||
{
|
{
|
||||||
if (!ModelUtils::addImportWithCheck(importName, m_view->model()))
|
if (!ModelUtils::addImportWithCheck(importName, m_view->model()))
|
||||||
@@ -900,227 +814,12 @@ bool QmlDesigner::NavigatorTreeModel::moveNodeToParent(const NodeAbstractPropert
|
|||||||
NodeAbstractProperty parentProp = targetProperty.parentProperty();
|
NodeAbstractProperty parentProp = targetProperty.parentProperty();
|
||||||
if (parentProp.isValid()) {
|
if (parentProp.isValid()) {
|
||||||
ModelNode targetModel = parentProp.parentModelNode();
|
ModelNode targetModel = parentProp.parentModelNode();
|
||||||
int targetRowNumber = rowCount(indexForModelNode(targetModel));
|
parentProp.reparentHere(node);
|
||||||
moveNodesInteractive(parentProp, {node}, targetRowNumber, false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
|
|
||||||
NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex,
|
|
||||||
bool &outMoveNodesAfter)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return {});
|
|
||||||
|
|
||||||
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
|
||||||
ModelNode newModelNode;
|
|
||||||
|
|
||||||
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderPath);
|
|
||||||
|
|
||||||
if (targetNode.metaInfo().isQtQuick3DShader()) {
|
|
||||||
// if dropping into an existing Shader, update
|
|
||||||
targetNode.variantProperty("stage").setEnumeration(isFragShader ? "Shader.Fragment"
|
|
||||||
: "Shader.Vertex");
|
|
||||||
targetNode.variantProperty("shader").setValue(relPath);
|
|
||||||
} else {
|
|
||||||
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
|
|
||||||
// create a new Shader
|
|
||||||
ItemLibraryEntry itemLibraryEntry;
|
|
||||||
itemLibraryEntry.setName("Shader");
|
|
||||||
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
|
|
||||||
|
|
||||||
// set shader properties
|
|
||||||
PropertyName prop = "shader";
|
|
||||||
QString type = "QUrl";
|
|
||||||
QVariant val = relPath;
|
|
||||||
itemLibraryEntry.addProperty(prop, type, val);
|
|
||||||
prop = "stage";
|
|
||||||
type = "enum";
|
|
||||||
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
|
|
||||||
itemLibraryEntry.addProperty(prop, type, val);
|
|
||||||
|
|
||||||
// create a texture
|
|
||||||
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
|
|
||||||
targetProperty, false);
|
|
||||||
|
|
||||||
// Rename the node based on shader source
|
|
||||||
QFileInfo fi(relPath);
|
|
||||||
newModelNode.setIdWithoutRefactoring(
|
|
||||||
m_view->model()->generateNewId(fi.baseName(), "shader"));
|
|
||||||
// Passes can't have children, so move shader node under parent
|
|
||||||
if (targetProperty.parentModelNode().metaInfo().isQtQuick3DPass()) {
|
|
||||||
BindingProperty listProp = targetNode.bindingProperty("shaders");
|
|
||||||
listProp.addModelNodeToArray(newModelNode);
|
|
||||||
outMoveNodesAfter = !moveNodeToParent(targetProperty, newModelNode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModelNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPath,
|
|
||||||
NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return {});
|
|
||||||
|
|
||||||
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
|
||||||
ModelNode newModelNode;
|
|
||||||
|
|
||||||
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundPath);
|
|
||||||
|
|
||||||
if (targetNode.metaInfo().isQtMultimediaSoundEffect()) {
|
|
||||||
// if dropping into on an existing SoundEffect, update
|
|
||||||
targetNode.variantProperty("source").setValue(relPath);
|
|
||||||
} else {
|
|
||||||
// create a new SoundEffect
|
|
||||||
ItemLibraryEntry itemLibraryEntry;
|
|
||||||
itemLibraryEntry.setName("SoundEffect");
|
|
||||||
itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0);
|
|
||||||
|
|
||||||
// set source property
|
|
||||||
PropertyName prop = "source";
|
|
||||||
QString type = "QUrl";
|
|
||||||
QVariant val = relPath;
|
|
||||||
itemLibraryEntry.addProperty(prop, type, val);
|
|
||||||
|
|
||||||
// create a texture
|
|
||||||
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
|
|
||||||
targetProperty, false);
|
|
||||||
|
|
||||||
// Rename the node based on source
|
|
||||||
QFileInfo fi(relPath);
|
|
||||||
newModelNode.setIdWithoutRefactoring(
|
|
||||||
m_view->model()->generateNewId(fi.baseName(), "soundEffect"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModelNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath,
|
|
||||||
NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex,
|
|
||||||
bool &outMoveNodesAfter)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return {});
|
|
||||||
|
|
||||||
Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D"));
|
|
||||||
if (!m_view->model()->hasImport(import, true, true))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
|
||||||
|
|
||||||
const QString imagePath = DocumentManager::currentFilePath().toFileInfo().dir()
|
|
||||||
.relativeFilePath(tex3DPath); // relative to qml file
|
|
||||||
|
|
||||||
ModelNode newModelNode;
|
|
||||||
|
|
||||||
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode, outMoveNodesAfter)) {
|
|
||||||
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
|
|
||||||
// create a standalone Texture3D at drop location
|
|
||||||
newModelNode = createTextureNode(targetProperty, imagePath);
|
|
||||||
if (!NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newModelNode))
|
|
||||||
newModelNode.destroy();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModelNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::handleItemLibraryEffectDrop(const QString &effectPath, const QModelIndex &rowModelIndex)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(m_view, return {});
|
|
||||||
|
|
||||||
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
|
||||||
ModelNode newModelNode;
|
|
||||||
|
|
||||||
if ((targetNode.hasParentProperty() && targetNode.parentProperty().name() == "layer.effect")
|
|
||||||
|| !targetNode.metaInfo().isQtQuickItem())
|
|
||||||
return newModelNode;
|
|
||||||
|
|
||||||
if (ModelNodeOperations::validateEffect(effectPath)) {
|
|
||||||
bool layerEffect = ModelNodeOperations::useLayerEffect();
|
|
||||||
newModelNode = QmlItemNode::createQmlItemNodeForEffect(m_view, targetNode, effectPath, layerEffect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newModelNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
|
|
||||||
const NodeAbstractProperty &targetProp,
|
|
||||||
const QString &imagePath,
|
|
||||||
ModelNode &newNode,
|
|
||||||
bool &outMoveNodesAfter)
|
|
||||||
{
|
|
||||||
auto bindToProperty = [&](const PropertyName &propName, bool sibling) {
|
|
||||||
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
|
||||||
newNode = createTextureNode(targetProp, imagePath);
|
|
||||||
if (newNode.isValid()) {
|
|
||||||
targetNode.bindingProperty(propName).setExpression(newNode.validId());
|
|
||||||
|
|
||||||
// If dropping an image on e.g. TextureInput, create a texture on the same level as
|
|
||||||
// target, as the target doesn't support Texture children (QTBUG-86219)
|
|
||||||
if (sibling)
|
|
||||||
outMoveNodesAfter = !moveNodeToParent(targetProp, newNode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (targetNode.metaInfo().isQtQuick3DDefaultMaterial()
|
|
||||||
|| targetNode.metaInfo().isQtQuick3DPrincipledMaterial()
|
|
||||||
|| targetNode.metaInfo().isQtQuick3DSpecularGlossyMaterial()) {
|
|
||||||
// if dropping an image on a material, create a texture instead of image
|
|
||||||
// Show texture property selection dialog
|
|
||||||
auto dialog = ChooseFromPropertyListDialog::createIfNeeded(targetNode,
|
|
||||||
m_view->model()->metaInfo(
|
|
||||||
"QtQuick3D.Texture"),
|
|
||||||
Core::ICore::dialogParent());
|
|
||||||
if (!dialog)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dialog->exec();
|
|
||||||
|
|
||||||
if (dialog->result() == QDialog::Accepted) {
|
|
||||||
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
|
|
||||||
newNode = createTextureNode(targetProp, imagePath);
|
|
||||||
if (newNode.isValid()) // Automatically set the texture to selected property
|
|
||||||
targetNode.bindingProperty(dialog->selectedProperty()).setExpression(newNode.validId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
delete dialog;
|
|
||||||
return true;
|
|
||||||
} else if (targetNode.metaInfo().isQtQuick3DTextureInput()) {
|
|
||||||
bindToProperty("texture", true);
|
|
||||||
return newNode.isValid();
|
|
||||||
} else if (targetNode.metaInfo().isQtQuick3DParticles3DSpriteParticle3D()) {
|
|
||||||
bindToProperty("sprite", false);
|
|
||||||
return newNode.isValid();
|
|
||||||
} else if (targetNode.metaInfo().isQtQuick3DSceneEnvironment()) {
|
|
||||||
bindToProperty("lightProbe", false);
|
|
||||||
return newNode.isValid();
|
|
||||||
} else if (targetNode.metaInfo().isQtQuick3DTexture()) {
|
|
||||||
// if dropping an image on an existing texture, set the source
|
|
||||||
targetNode.variantProperty("source").setValue(imagePath);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targetProp,
|
ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targetProp,
|
||||||
const QString &imagePath)
|
const QString &imagePath)
|
||||||
{
|
{
|
||||||
|
@@ -93,21 +93,7 @@ private:
|
|||||||
int targetIndex, bool executeInTransaction = true);
|
int targetIndex, bool executeInTransaction = true);
|
||||||
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
void handleTextureDrop(const QMimeData *mimeData, const QModelIndex &dropModelIndex);
|
|
||||||
void handleMaterialDrop(const QMimeData *mimeData, const QModelIndex &dropModelIndex);
|
|
||||||
ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
|
||||||
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex);
|
|
||||||
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
|
|
||||||
NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex,
|
|
||||||
bool &outMoveNodesAfter);
|
|
||||||
ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex);
|
|
||||||
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
|
|
||||||
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
|
|
||||||
ModelNode handleItemLibraryEffectDrop(const QString &effectPath, const QModelIndex &rowModelIndex);
|
|
||||||
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
|
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
|
||||||
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
|
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
|
||||||
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
|
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
|
||||||
|
Reference in New Issue
Block a user