aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2021-12-10 13:08:58 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2021-12-13 11:26:15 +0000
commit553de191519601f645e4d488698d9df55f43e0b7 (patch)
treeb94a4b5fef94b575e9d88c832c0e56762aff5525
parent352e66531e366868e445a15319c64750b9bd4720 (diff)
QmlDesigner: Fix picking of Repeater3D/Loader3D generated nodes
There is no top level Repeater3D node with an actual instance when the Repeater3D is inside a component. The pick target was not correctly set in this case. Now we set pick target on every encountered Repeater3D object so we can propagate it to every object they create. The same was done for Loader3D, which also creates nodes dynamically. Fixes: QDS-5745 Change-Id: I537de28ff7426adaa29c2febc6c4b3416baeccb5 Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp55
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h8
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp15
3 files changed, 57 insertions, 21 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index 70dc4b8cc9..76b3475872 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -100,6 +100,7 @@
#include <QtQuick3D/private/qquick3dviewport_p.h>
#include <QtQuick3D/private/qquick3dscenerootnode_p.h>
#include <QtQuick3D/private/qquick3drepeater_p.h>
+#include <QtQuick3D/private/qquick3dloader_p.h>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include "../editor3d/qt5compat/qquick3darealight_p.h"
#endif
@@ -1227,7 +1228,7 @@ Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceC
m_inputEventTimer.setSingleShot(true);
m_renderModelNodeImageViewTimer.setSingleShot(true);
m_modelNode3DImageViewAsyncData.timer.setSingleShot(true);
- m_repeaterAddObjectTimer.setSingleShot(true);
+ m_dynamicAddObjectTimer.setSingleShot(true);
#ifdef FPS_COUNTER
if (!_fpsTimer) {
@@ -1253,7 +1254,7 @@ Qt5InformationNodeInstanceServer::~Qt5InformationNodeInstanceServer()
m_inputEventTimer.stop();
m_renderModelNodeImageViewTimer.stop();
m_modelNode3DImageViewAsyncData.timer.stop();
- m_repeaterAddObjectTimer.stop();
+ m_dynamicAddObjectTimer.stop();
if (m_editView3DData.rootItem)
m_editView3DData.rootItem->disconnect(this);
@@ -1397,20 +1398,27 @@ void Qt5InformationNodeInstanceServer::handleSelectionChangeTimeout()
changeSelection(m_lastSelectionChangeCommand);
}
-void Qt5InformationNodeInstanceServer::handleRepeaterAddObjectTimeout()
+void Qt5InformationNodeInstanceServer::handleDynamicAddObjectTimeout()
{
#ifdef QUICK3D_MODULE
- for (auto obj : std::as_const(m_addObjectRepeaters)) {
- if (auto repObj = qobject_cast<QQuick3DRepeater *>(obj)) {
- if (hasInstanceForObject(repObj)) {
- ServerNodeInstance instance = instanceForObject(repObj);
+ for (auto obj : std::as_const(m_dynamicObjectConstructors)) {
+ auto handleHiding = [this](QQuick3DNode *node) -> bool {
+ if (node && hasInstanceForObject(node)) {
+ ServerNodeInstance instance = instanceForObject(node);
handleInstanceHidden(instance, instance.internalInstance()->isHiddenInEditor(),
false);
+ return true;
}
+ return false;
+ };
+ auto nodeObj = qobject_cast<QQuick3DNode *>(obj);
+ if (!handleHiding(nodeObj)) {
+ if (auto pickTarget = obj->property("_pickTarget").value<QQuick3DNode *>())
+ handleHiding(pickTarget);
}
}
#endif
- m_addObjectRepeaters.clear();
+ m_dynamicObjectConstructors.clear();
}
void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos(
@@ -1664,8 +1672,8 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
this, &Qt5InformationNodeInstanceServer::handleInputEvents);
QObject::connect(&m_modelNode3DImageViewAsyncData.timer, &QTimer::timeout,
this, &Qt5InformationNodeInstanceServer::modelNode3DImageViewRenderStep);
- QObject::connect(&m_repeaterAddObjectTimer, &QTimer::timeout,
- this, &Qt5InformationNodeInstanceServer::handleRepeaterAddObjectTimeout);
+ QObject::connect(&m_dynamicAddObjectTimer, &QTimer::timeout,
+ this, &Qt5InformationNodeInstanceServer::handleDynamicAddObjectTimeout);
QString lastSceneId;
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
@@ -1824,7 +1832,7 @@ void Qt5InformationNodeInstanceServer::clearScene(const ClearSceneCommand &comma
m_parentChangedSet.clear();
m_completedComponentList.clear();
- m_addObjectRepeaters.clear();
+ m_dynamicObjectConstructors.clear();
}
void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &command)
@@ -2296,6 +2304,23 @@ void Qt5InformationNodeInstanceServer::handleInstanceHidden(const ServerNodeInst
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 1)
checkModel->setPickable(!edit3dHidden);
#endif
+ } else {
+ auto checkRepeater = qobject_cast<QQuick3DRepeater *>(checkNode);
+ auto checkLoader = qobject_cast<QQuick3DLoader *>(checkNode);
+ if (checkRepeater || checkLoader) {
+ // Repeaters/loaders may not yet have created their children, so we set
+ // _pickTarget on them and connect the notifier.
+ if (checkNode->property("_pickTarget").isNull()) {
+ if (checkRepeater) {
+ QObject::connect(checkRepeater, &QQuick3DRepeater::objectAdded,
+ this, &Qt5InformationNodeInstanceServer::handleDynamicAddObject);
+ } else {
+ QObject::connect(checkLoader, &QQuick3DLoader::loaded,
+ this, &Qt5InformationNodeInstanceServer::handleDynamicAddObject);
+ }
+ }
+ checkNode->setProperty("_pickTarget", QVariant::fromValue(node));
+ }
}
};
if (auto childNode = qobject_cast<QQuick3DNode *>(childItem))
@@ -2315,10 +2340,12 @@ bool Qt5InformationNodeInstanceServer::isInformationServer() const
return true;
}
-void Qt5InformationNodeInstanceServer::handleRepeaterAddObject()
+// This method should be connected to signals indicating a new object has been constructed outside
+// normal scene creation. E.g. QQuick3DRepeater::objectAdded.
+void Qt5InformationNodeInstanceServer::handleDynamicAddObject()
{
- m_addObjectRepeaters.insert(sender());
- m_repeaterAddObjectTimer.start();
+ m_dynamicObjectConstructors.insert(sender());
+ m_dynamicAddObjectTimer.start();
}
// update 3D view size when it changes in creator side
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index 439b7b17a3..b63b6ae6ed 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -82,7 +82,7 @@ public:
void handleInstanceHidden(const ServerNodeInstance &instance, bool enable, bool checkAncestors) override;
bool isInformationServer() const override;
- void handleRepeaterAddObject();
+ void handleDynamicAddObject();
private slots:
void handleSelectionChanged(const QVariant &objs);
@@ -109,7 +109,7 @@ protected:
private:
void handleObjectPropertyChangeTimeout();
void handleSelectionChangeTimeout();
- void handleRepeaterAddObjectTimeout();
+ void handleDynamicAddObjectTimeout();
void createEditView3D();
void create3DPreviewView();
void setup3DEditView(const QList<ServerNodeInstance> &instanceList,
@@ -176,7 +176,7 @@ private:
QTimer m_render3DEditViewTimer;
QTimer m_renderModelNodeImageViewTimer;
QTimer m_inputEventTimer;
- QTimer m_repeaterAddObjectTimer;
+ QTimer m_dynamicAddObjectTimer;
#ifdef QUICK3D_PARTICLES_MODULE
bool m_particleAnimationPlaying = true;
AnimationDriver *m_particleAnimationDriver = nullptr;
@@ -189,7 +189,7 @@ private:
QList<InputEventCommand> m_pendingInputEventCommands;
QObject *m_3dHelper = nullptr;
int m_need3DEditViewRender = 0;
- QSet<QObject *> m_addObjectRepeaters;
+ QSet<QObject *> m_dynamicObjectConstructors;
struct ModelNode3DImageViewAsyncData {
QTimer timer;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
index 783bfba87f..734eeee470 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp
@@ -41,6 +41,7 @@
#include <private/qquick3dmodel_p.h>
#include <private/qquick3dnode_p_p.h>
#include <private/qquick3drepeater_p.h>
+#include <private/qquick3dloader_p.h>
#endif
namespace QmlDesigner {
@@ -59,10 +60,18 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo
InstanceContainer::NodeFlags flags)
{
#ifdef QUICK3D_MODULE
- if (auto repObj = qobject_cast<QQuick3DRepeater *>(object())) {
+ QObject *obj = object();
+ auto repObj = qobject_cast<QQuick3DRepeater *>(obj);
+ auto loadObj = qobject_cast<QQuick3DLoader *>(obj);
+ if (repObj || loadObj) {
if (auto infoServer = qobject_cast<Qt5InformationNodeInstanceServer *>(nodeInstanceServer())) {
- QObject::connect(repObj, &QQuick3DRepeater::objectAdded,
- infoServer, &Qt5InformationNodeInstanceServer::handleRepeaterAddObject);
+ if (repObj) {
+ QObject::connect(repObj, &QQuick3DRepeater::objectAdded,
+ infoServer, &Qt5InformationNodeInstanceServer::handleDynamicAddObject);
+ } else {
+ QObject::connect(loadObj, &QQuick3DLoader::loaded,
+ infoServer, &Qt5InformationNodeInstanceServer::handleDynamicAddObject);
+ }
}
}
#endif