From 73d3df79088a06e8e59b1da0b0eb39d6cd3eba8f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 29 Nov 2019 17:28:11 +0200 Subject: [PATCH] QmlDesigner: Make imported models selectable Import creates an opaque Component, which can contain one or more pickable models. We mark all instanceless models pickable according to the parent instance pickable status and specify the parent instance as the pick target using a dynamic property. Change-Id: I05b96ee48eb8f246c50b2254d620b621e2437aa5 Fixes: QDS-1282 Reviewed-by: Mahmoud Badri Reviewed-by: Thomas Hartmann --- .../qml/qmlpuppet/mockfiles/EditView3D.qml | 3 +- .../qml2puppet/editor3d/generalhelper.cpp | 14 ++++++ .../qml2puppet/editor3d/generalhelper.h | 2 + .../instances/quick3dnodeinstance.cpp | 47 ++++++++++++++----- .../instances/quick3dnodeinstance.h | 2 +- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml index 5de0f253481..d64005d1f64 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml @@ -249,7 +249,8 @@ Window { acceptedButtons: Qt.LeftButton onClicked: { var pickResult = editView.pick(mouse.x, mouse.y); - handleObjectClicked(pickResult.objectHit, mouse.modifiers & Qt.ControlModifier); + handleObjectClicked(_generalHelper.resolvePick(pickResult.objectHit), + mouse.modifiers & Qt.ControlModifier); if (!pickResult.objectHit) mouse.accepted = false; } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index b104d53a8fe..150b8e9ab19 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -204,6 +204,20 @@ void GeneralHelper::delayedPropertySet(QObject *obj, int delay, const QString &p }); } +QQuick3DNode *GeneralHelper::resolvePick(QQuick3DNode *pickNode) +{ + if (pickNode) { + // Check if the picked node actually specifies another node as the pick target + QVariant componentVar = pickNode->property("_pickTarget"); + if (componentVar.isValid()) { + auto componentNode = componentVar.value(); + if (componentNode) + return componentNode; + } + } + return pickNode; +} + } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h index 47449351900..890b824aa69 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.h @@ -67,6 +67,8 @@ public: float oldZoom, bool updateZoom = true); Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property, const QVariant& value); + Q_INVOKABLE QQuick3DNode *resolvePick(QQuick3DNode *pickNode); + signals: void overlayUpdateNeeded(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp index f35d1659311..4c725749e2e 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp @@ -37,6 +37,7 @@ #ifdef QUICK3D_MODULE #include +#include #include #endif @@ -73,7 +74,7 @@ QQuick3DNode *Quick3DNodeInstance::quick3DNode() const #endif } -void Quick3DNodeInstance::setPickable(bool enable, bool checkParent, bool applyToChildren) +void Quick3DNodeInstance::setPickable(bool enable, bool checkParent, bool applyToChildInstances) { #ifdef QUICK3D_MODULE auto node = quick3DNode(); @@ -90,22 +91,42 @@ void Quick3DNodeInstance::setPickable(bool enable, bool checkParent, bool applyT } if (!parentHidden) { - if (applyToChildren) { - auto getQuick3DInstance = [this](QQuick3DObject *obj) -> Quick3DNodeInstance * { - if (nodeInstanceServer()->hasInstanceForObject(obj)) { - ServerNodeInstance instance = nodeInstanceServer()->instanceForObject(obj); - if (instance.isValid() && qobject_cast(instance.internalObject())) - return static_cast(instance.internalInstance().data()); - } - return nullptr; - }; - const auto childItems = node->childItems(); - for (auto childItem : childItems) { - if (auto quick3dInstance = getQuick3DInstance(childItem)) { + auto getQuick3DInstance = [this](QQuick3DObject *obj) -> Quick3DNodeInstance * { + if (nodeInstanceServer()->hasInstanceForObject(obj)) { + ServerNodeInstance instance = nodeInstanceServer()->instanceForObject(obj); + if (instance.isValid() && qobject_cast(instance.internalObject())) + return static_cast(instance.internalInstance().data()); + } + return nullptr; + }; + const auto childItems = node->childItems(); + for (auto childItem : childItems) { + if (auto quick3dInstance = getQuick3DInstance(childItem)) { + if (applyToChildInstances) { // Don't override explicit block in children if (!QQuick3DNodePrivate::get(quick3dInstance->quick3DNode())->m_isHiddenInEditor) quick3dInstance->setPickable(enable, false, true); } + } else { + // Children of components do not have instances, but will still need to be + // pickable. These need to be set even if applyToChildInstances is false. + std::function checkChildren; + checkChildren = [&](QQuick3DNode *checkNode) { + const auto childItems = checkNode->childItems(); + for (auto child : childItems) { + if (auto childNode = qobject_cast(child)) + checkChildren(childNode); + } + if (auto checkModel = qobject_cast(checkNode)) { + QVariant value; + if (enable) + value = QVariant::fromValue(node); + // Specify the actual pick target with dynamic property + checkModel->setProperty("_pickTarget", value); + checkModel->setPickable(enable); + } + }; + checkChildren(node); } } if (nodeType == QQuick3DObject::Model) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h index 27e2488eb3f..7b48ea9193f 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h @@ -53,7 +53,7 @@ protected: private: Qt5NodeInstanceServer *qt5NodeInstanceServer() const; QQuick3DNode *quick3DNode() const; - void setPickable(bool enable, bool checkParent, bool applyToChildren); + void setPickable(bool enable, bool checkParent, bool applyToChildInstances); }; } // namespace Internal