diff --git a/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc b/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc index c89e2806f6c..065f9e32cf3 100644 --- a/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc +++ b/share/qtcreator/qml/qmlpuppet/editor3d_qt6.qrc @@ -7,6 +7,8 @@ mockfiles/meshes/axishelper.mesh mockfiles/images/editor_camera.png mockfiles/images/editor_camera@2x.png + mockfiles/images/editor_particlesystem.png + mockfiles/images/editor_particlesystem@2x.png mockfiles/images/area.png mockfiles/images/area@2x.png mockfiles/images/directional.png @@ -33,6 +35,7 @@ mockfiles/qt6/LightGizmo.qml mockfiles/qt6/LightIconGizmo.qml mockfiles/qt6/LightModel.qml + mockfiles/qt6/ParticleSystemGizmo.qml mockfiles/qt6/Line3D.qml mockfiles/qt6/MaterialNodeView.qml mockfiles/qt6/ModelNode2DImageView.qml diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem.png new file mode 100644 index 00000000000..55d35bc5842 Binary files /dev/null and b/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem.png differ diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem@2x.png b/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem@2x.png new file mode 100644 index 00000000000..e66db81479c Binary files /dev/null and b/share/qtcreator/qml/qmlpuppet/mockfiles/images/editor_particlesystem@2x.png differ diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml index d79f1c0f5fb..ebc406c5ad7 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/EditView3D.qml @@ -54,6 +54,7 @@ Item { property var lightIconGizmos: [] property var cameraGizmos: [] + property var particleSystemIconGizmos: [] property var selectionBoxes: [] property rect viewPortRect: Qt.rect(0, 0, 1000, 1000) @@ -400,6 +401,45 @@ Item { } } + function addParticleSystemGizmo(scene, obj) + { + // Insert into first available gizmo if we don't already have gizmo for this object + var slotFound = -1; + for (var i = 0; i < particleSystemIconGizmos.length; ++i) { + if (!particleSystemIconGizmos[i].targetNode) { + slotFound = i; + } else if (particleSystemIconGizmos[i].targetNode === obj) { + particleSystemIconGizmos[i].scene = scene; + return; + } + } + + if (slotFound !== -1) { + particleSystemIconGizmos[slotFound].scene = scene; + particleSystemIconGizmos[slotFound].targetNode = obj; + particleSystemIconGizmos[slotFound].locked = _generalHelper.isLocked(obj); + particleSystemIconGizmos[slotFound].hidden = _generalHelper.isHidden(obj); + _generalHelper.registerGizmoTarget(obj); + return; + } + + // No free gizmos available, create a new one + var gizmoComponent = Qt.createComponent("ParticleSystemGizmo.qml"); + if (gizmoComponent.status === Component.Ready) { + _generalHelper.registerGizmoTarget(obj); + var gizmo = gizmoComponent.createObject(overlayView, + {"view3D": overlayView, "targetNode": obj, + "selectedNodes": selectedNodes, "scene": scene, + "activeScene": activeScene, + "locked": _generalHelper.isLocked(obj), + "hidden": _generalHelper.isHidden(obj)}); + particleSystemIconGizmos[particleSystemIconGizmos.length] = gizmo; + gizmo.clicked.connect(handleObjectClicked); + gizmo.selectedNodes = Qt.binding(function() {return selectedNodes;}); + gizmo.activeScene = Qt.binding(function() {return activeScene;}); + } + } + function releaseLightGizmo(obj) { for (var i = 0; i < lightIconGizmos.length; ++i) { @@ -424,6 +464,18 @@ Item { } } + function releaseParticleSystemGizmo(obj) + { + for (var i = 0; i < particleSystemIconGizmos.length; ++i) { + if (particleSystemIconGizmos[i].targetNode === obj) { + particleSystemIconGizmos[i].scene = null; + particleSystemIconGizmos[i].targetNode = null; + _generalHelper.unregisterGizmoTarget(obj); + return; + } + } + } + function updateLightGizmoScene(scene, obj) { for (var i = 0; i < lightIconGizmos.length; ++i) { @@ -444,6 +496,16 @@ Item { } } + function updateParticleSystemGizmoScene(scene, obj) + { + for (var i = 0; i < particleSystemIconGizmos.length; ++i) { + if (particleSystemIconGizmos[i].targetNode === obj) { + particleSystemIconGizmos[i].scene = scene; + return; + } + } + } + Component.onCompleted: { createEditView(); selectObjects([]); @@ -471,6 +533,13 @@ Item { return; } } + for (var i = 0; i < particleSystemIconGizmos.length; ++i) { + if (particleSystemIconGizmos[i].targetNode === node) { + particleSystemIconGizmos[i].locked = _generalHelper.isLocked(node); + return; + } + } + } function onHiddenStateChanged(node) { @@ -486,6 +555,12 @@ Item { return; } } + for (var i = 0; i < particleSystemIconGizmos.length; ++i) { + if (particleSystemIconGizmos[i].targetNode === node) { + particleSystemIconGizmos[i].hidden = _generalHelper.isHidden(node); + return; + } + } } } diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleSystemGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleSystemGizmo.qml new file mode 100644 index 00000000000..de591fcd217 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleSystemGizmo.qml @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +import QtQuick 6.0 +import QtQuick3D 6.0 + +IconGizmo { + id: particleSystemGizmo + iconSource: "qrc:///qtquickplugin/mockfiles/images/editor_particlesystem.png" +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri index 81c00b796e0..ff3ee9394b9 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/instances.pri @@ -9,6 +9,10 @@ versionAtLeast(QT_VERSION, 5.15.0) { QT *= quick3dassetimport-private DEFINES *= IMPORT_QUICK3D_ASSETS } + qtHaveModule(quick3dparticles) { + QT *= quick3dparticles-private + DEFINES *= QUICK3D_PARTICLES_MODULE + } } HEADERS += $$PWD/qt5nodeinstanceserver.h \ diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 426cd730ead..5177c34b5ab 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -103,6 +103,10 @@ #endif #endif +#ifdef QUICK3D_PARTICLES_MODULE +#include +#endif + #ifdef IMPORT_QUICK3D_ASSETS #include #endif @@ -618,6 +622,11 @@ void Qt5InformationNodeInstanceServer::handleNode3DDestroyed(QObject *obj) } else if (qobject_cast(obj)) { QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseLightGizmo", Q_ARG(QVariant, objectToVariant(obj))); +#ifdef QUICK3D_PARTICLES_MODULE + } else if (qobject_cast(obj)) { + QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleSystemGizmo", + Q_ARG(QVariant, objectToVariant(obj))); +#endif } removeNode3D(obj); #else @@ -720,6 +729,12 @@ void Qt5InformationNodeInstanceServer::resolveSceneRoots() QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateLightGizmoScene", Q_ARG(QVariant, objectToVariant(newRoot)), Q_ARG(QVariant, objectToVariant(node))); +#ifdef QUICK3D_PARTICLES_MODULE + } else if (qobject_cast(node)) { + QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleSystemGizmoScene", + Q_ARG(QVariant, objectToVariant(newRoot)), + Q_ARG(QVariant, objectToVariant(node))); +#endif } } ++it; @@ -1231,12 +1246,16 @@ void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos( { QHash cameras; QHash lights; + QHash particleSystems; for (const ServerNodeInstance &instance : instanceList) { if (instance.isSubclassOf("QQuick3DCamera")) cameras[find3DSceneRoot(instance)] << instance.internalObject(); else if (instance.isSubclassOf("QQuick3DAbstractLight")) lights[find3DSceneRoot(instance)] << instance.internalObject(); + else if (instance.isSubclassOf("QQuick3DParticleSystem")) + particleSystems[find3DSceneRoot(instance)] << instance.internalObject(); + } auto cameraIt = cameras.constBegin(); @@ -1259,6 +1278,16 @@ void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos( } ++lightIt; } + auto particleIt = particleSystems.constBegin(); + while (particleIt != particleSystems.constEnd()) { + const auto particleObjs = particleIt.value(); + for (auto &obj : particleObjs) { + QMetaObject::invokeMethod(m_editView3DData.rootItem, "addParticleSystemGizmo", + Q_ARG(QVariant, objectToVariant(particleIt.key())), + Q_ARG(QVariant, objectToVariant(obj))); + } + ++particleIt; + } } void Qt5InformationNodeInstanceServer::add3DViewPorts(const QList &instanceList) @@ -1740,6 +1769,9 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm #ifdef QUICK3D_MODULE if (qobject_cast(object) || qobject_cast(object) +#ifdef QUICK3D_PARTICLES_MODULE + || qobject_cast(object) +#endif || qobject_cast(object)) { return true; } diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt index 3dbb875ce41..924e3a838c1 100644 --- a/src/tools/qml2puppet/CMakeLists.txt +++ b/src/tools/qml2puppet/CMakeLists.txt @@ -160,6 +160,14 @@ extend_qtc_executable(qml2puppet DEFINES IMPORT_QUICK3D_ASSETS ) +find_package(Qt5 5.15.0 COMPONENTS Quick3DParticles QUIET) +extend_qtc_executable(qml2puppet + CONDITION TARGET Qt5::Quick3DParticles + FEATURE_INFO "Qt Quick 3D particles" + DEPENDS Qt5::Quick3DParticles Qt5::Quick3DParticlesPrivate + DEFINES QUICK3D_PARTICLES_MODULE +) + extend_qtc_executable(qml2puppet CONDITION Qt5_VERSION VERSION_GREATER_EQUAL 6.0.0 diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs index c2b57579563..7eff7ba02b7 100644 --- a/src/tools/qml2puppet/qml2puppet.qbs +++ b/src/tools/qml2puppet/qml2puppet.qbs @@ -18,11 +18,15 @@ QtcTool { Depends { name: "Qt.quick3d-private"; required: false } property bool useQuick3d: Utilities.versionCompare(Qt.core.version, "5.15") >= 0 && Qt["quick3d-private"].present + property bool useParticle3d: Utilities.versionCompare(Qt.core.version, "6.2") >= 0 + && Qt["quick3dparticles-private"].present cpp.defines: { var defines = base.filter(function(d) { return d != "QT_CREATOR"; }); if (useQuick3d) defines.push("QUICK3D_MODULE"); + if (useParticle3d) + defines.push("QUICK3D_PARTICLES_MODULE"); return defines; } Properties {