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 <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2019-11-29 17:28:11 +02:00
parent de141661df
commit 73d3df7908
5 changed files with 53 additions and 15 deletions

View File

@@ -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;
}

View File

@@ -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<QQuick3DNode *>();
if (componentNode)
return componentNode;
}
}
return pickNode;
}
}
}

View File

@@ -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();

View File

@@ -37,6 +37,7 @@
#ifdef QUICK3D_MODULE
#include <private/qquick3dnode_p.h>
#include <private/qquick3dmodel_p.h>
#include <private/qquick3dnode_p_p.h>
#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<QQuick3DNode *>(instance.internalObject()))
return static_cast<Quick3DNodeInstance *>(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<QQuick3DNode *>(instance.internalObject()))
return static_cast<Quick3DNodeInstance *>(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<void(QQuick3DNode *)> checkChildren;
checkChildren = [&](QQuick3DNode *checkNode) {
const auto childItems = checkNode->childItems();
for (auto child : childItems) {
if (auto childNode = qobject_cast<QQuick3DNode *>(child))
checkChildren(childNode);
}
if (auto checkModel = qobject_cast<QQuick3DModel *>(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)

View File

@@ -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