diff options
53 files changed, 550 insertions, 130 deletions
diff --git a/.qmake.conf b/.qmake.conf index a9c5f436b..0bd995808 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -3,4 +3,4 @@ QT3D_BUILD_ROOT = $$shadowed($$PWD) load(qt_build_config) -MODULE_VERSION = 5.11.2 +MODULE_VERSION = 5.12.0 @@ -1,4 +1,4 @@ -requires(qtConfig(opengl)) +requires(qtConfig(opengl):!html5) CONFIG += examples_need_tools load(qt_parts) diff --git a/src/core/changes/qnodecreatedchange_p.h b/src/core/changes/qnodecreatedchange_p.h index cb1470970..5e4c5b91d 100644 --- a/src/core/changes/qnodecreatedchange_p.h +++ b/src/core/changes/qnodecreatedchange_p.h @@ -53,10 +53,10 @@ #include <Qt3DCore/private/qscenechange_p.h> #include <Qt3DCore/private/qt3dcore_global_p.h> -struct QMetaObject; - QT_BEGIN_NAMESPACE +struct QMetaObject; + namespace Qt3DCore { class QNode; diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp index d0ed58efd..64ea65087 100644 --- a/src/core/nodes/qentity.cpp +++ b/src/core/nodes/qentity.cpp @@ -52,6 +52,8 @@ #include <Qt3DCore/private/qcomponent_p.h> #include <Qt3DCore/private/qscene_p.h> +#include <QQueue> + QT_BEGIN_NAMESPACE namespace Qt3DCore { @@ -233,6 +235,20 @@ QNodeCreatedChangeBasePtr QEntity::createNodeCreationChange() const Q_D(const QEntity); data.parentEntityId = parentEntity() ? parentEntity()->id() : Qt3DCore::QNodeId(); + + // Find all child entities + QQueue<QNode *> queue; + queue.append(childNodes().toList()); + data.childEntityIds.reserve(queue.size()); + while (!queue.isEmpty()) { + auto *child = queue.dequeue(); + auto *childEntity = qobject_cast<QEntity *>(child); + if (childEntity != nullptr) + data.childEntityIds.push_back(childEntity->id()); + else + queue.append(child->childNodes().toList()); + } + data.componentIdsAndTypes.reserve(d->m_components.size()); const QComponentVector &components = d->m_components; for (QComponent *c : components) { diff --git a/src/core/nodes/qentity_p.h b/src/core/nodes/qentity_p.h index ef35d83a1..8fe03cd6b 100644 --- a/src/core/nodes/qentity_p.h +++ b/src/core/nodes/qentity_p.h @@ -91,6 +91,7 @@ struct QEntityData { Qt3DCore::QNodeId parentEntityId; QVector<QNodeIdTypePair> componentIdsAndTypes; + Qt3DCore::QNodeIdVector childEntityIds; }; } diff --git a/src/quick3d/imports/animation/importsanimation.pro b/src/quick3d/imports/animation/importsanimation.pro index 5492a4f39..7b637dd3c 100644 --- a/src/quick3d/imports/animation/importsanimation.pro +++ b/src/quick3d/imports/animation/importsanimation.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = quick3danimationplugin TARGETPATH = Qt3D/Animation -IMPORT_VERSION = 2.2 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += core-private qml qml-private 3dcore 3drender 3danimation 3dquick 3dquickrender 3dquickanimation 3dquick-private 3dquickanimation-private diff --git a/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp b/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp index 017e2a453..5656ef570 100644 --- a/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp +++ b/src/quick3d/imports/animation/qt3dquick3danimationplugin.cpp @@ -100,6 +100,9 @@ void Qt3DQuick3DAnimationPlugin::registerTypes(const char *uri) qmlRegisterUncreatableType<Qt3DAnimation::QAbstractChannelMapping>(uri, 2, 10, "AbstractChannelMapping", QStringLiteral("QAbstractChannelMapping is abstract")); qmlRegisterType<Qt3DAnimation::QSkeletonMapping>(uri, 2, 10, "SkeletonMapping"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } QT_END_NAMESPACE diff --git a/src/quick3d/imports/animation/qt3dquick3danimationplugin.h b/src/quick3d/imports/animation/qt3dquick3danimationplugin.h index 3800194ce..42e0efbef 100644 --- a/src/quick3d/imports/animation/qt3dquick3danimationplugin.h +++ b/src/quick3d/imports/animation/qt3dquick3danimationplugin.h @@ -42,13 +42,6 @@ #include <QtQml/qqmlextensionplugin.h> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt3D_Animation); -#endif -} - QT_BEGIN_NAMESPACE class Qt3DQuick3DAnimationPlugin : public QQmlExtensionPlugin @@ -56,7 +49,7 @@ class Qt3DQuick3DAnimationPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") public: - Qt3DQuick3DAnimationPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + Qt3DQuick3DAnimationPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { } void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/imports/core/importscore.pro b/src/quick3d/imports/core/importscore.pro index 6f43d8c99..4ff71488a 100644 --- a/src/quick3d/imports/core/importscore.pro +++ b/src/quick3d/imports/core/importscore.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = quick3dcoreplugin TARGETPATH = Qt3D/Core -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += core-private qml qml-private quick quick-private 3dcore 3dcore-private 3dquick 3dquick-private diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp index 05d99f05f..76d78c8fa 100644 --- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp +++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp @@ -54,6 +54,8 @@ #include <Qt3DQuick/private/qquaternionanimation_p.h> #include <Qt3DQuick/private/qt3dquick_global_p.h> +#include <QtQml/qqml.h> + QT_BEGIN_NAMESPACE void Qt3DQuick3DCorePlugin::registerTypes(const char *uri) @@ -64,6 +66,7 @@ void Qt3DQuick3DCorePlugin::registerTypes(const char *uri) Qt3DCore::Quick::registerExtendedType<Qt3DCore::QEntity, Qt3DCore::Quick::Quick3DEntity>("QEntity", "Qt3D.Core/Entity", uri, 2, 0, "Entity"); qmlRegisterType<Qt3DCore::Quick::Quick3DEntityLoader>(uri, 2, 0, "EntityLoader"); + qmlRegisterRevision<Qt3DCore::Quick::Quick3DEntityLoader, 12>(uri, 2, 12); qmlRegisterType<Qt3DCore::Quick::Quick3DNodeInstantiator>(uri, 2, 0, "NodeInstantiator"); qmlRegisterType<Qt3DCore::QTransform>(uri, 2, 0, "Transform"); qmlRegisterType<Qt3DCore::QArmature>(uri, 2, 10, "Armature"); @@ -79,6 +82,9 @@ void Qt3DQuick3DCorePlugin::registerTypes(const char *uri) qmlRegisterExtendedUncreatableType<Qt3DCore::QNode, Qt3DCore::Quick::Quick3DNodeV9, 9>(uri, 2, 9, "Node", QStringLiteral("Node is a base class")); Qt3DCore::Quick::registerExtendedType<Qt3DCore::QJoint, Qt3DCore::Quick::Quick3DJoint>("QJoint", "Qt3D.Core/Joint", uri, 2, 10, "Joint"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } Qt3DQuick3DCorePlugin::~Qt3DQuick3DCorePlugin() diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.h b/src/quick3d/imports/core/qt3dquick3dcoreplugin.h index 99c6ab525..afc092bbb 100644 --- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.h +++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.h @@ -42,13 +42,6 @@ #include <QtQml/QQmlExtensionPlugin> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt3D_Core); -#endif -} - QT_BEGIN_NAMESPACE class Qt3DQuick3DCorePlugin : public QQmlExtensionPlugin @@ -56,7 +49,7 @@ class Qt3DQuick3DCorePlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - Qt3DQuick3DCorePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); } + Qt3DQuick3DCorePlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { } ~Qt3DQuick3DCorePlugin(); void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/imports/extras/importsextras.pro b/src/quick3d/imports/extras/importsextras.pro index 22f753ee0..ea5b39a89 100644 --- a/src/quick3d/imports/extras/importsextras.pro +++ b/src/quick3d/imports/extras/importsextras.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = quick3dextrasplugin TARGETPATH = Qt3D/Extras -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += core-private qml qml-private quick quick-private 3dcore 3dcore-private 3dquick 3dquick-private 3dextras 3dlogic 3dquickextras 3dquickextras-private diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp index 9a3e76923..a4ced963a 100644 --- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp +++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp @@ -141,6 +141,9 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DExtras::QExtrudedTextMesh>(uri, 2, 9, "ExtrudedTextMesh"); qmlRegisterType<Qt3DExtras::QText2DEntity>(uri, 2, 9, "Text2DEntity"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h index b7c1f5f87..95b5a8717 100644 --- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h +++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.h @@ -45,8 +45,7 @@ static void initResources() { #ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt3D_Extras); - Q_INIT_RESOURCE(extras); + Q_INIT_RESOURCE(extras); // from the Qt3DQuickExtras module #endif } diff --git a/src/quick3d/imports/input/importsinput.pro b/src/quick3d/imports/input/importsinput.pro index 83a7797f9..2b0dd0354 100644 --- a/src/quick3d/imports/input/importsinput.pro +++ b/src/quick3d/imports/input/importsinput.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = quick3dinputplugin TARGETPATH = Qt3D/Input -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += core-private qml 3dcore 3dinput 3dinput-private 3dquickinput-private diff --git a/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp b/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp index 5719a2b98..ba2e0661c 100644 --- a/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp +++ b/src/quick3d/imports/input/qt3dquick3dinputplugin.cpp @@ -104,6 +104,9 @@ void Qt3DQuick3DInputPlugin::registerTypes(const char *uri) #ifdef HAVE_QGAMEPAD qmlRegisterType<Qt3DInput::QGamepadInput>(uri, 2, 0, "GamepadInput"); #endif + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } QT_END_NAMESPACE diff --git a/src/quick3d/imports/input/qt3dquick3dinputplugin.h b/src/quick3d/imports/input/qt3dquick3dinputplugin.h index e02710696..b2399af30 100644 --- a/src/quick3d/imports/input/qt3dquick3dinputplugin.h +++ b/src/quick3d/imports/input/qt3dquick3dinputplugin.h @@ -42,13 +42,6 @@ #include <QtQml/QQmlExtensionPlugin> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt3D_Input); -#endif -} - QT_BEGIN_NAMESPACE class Qt3DQuick3DInputPlugin : public QQmlExtensionPlugin @@ -56,7 +49,7 @@ class Qt3DQuick3DInputPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - Qt3DQuick3DInputPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { initResources(); } + Qt3DQuick3DInputPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent) { } void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/imports/logic/importslogic.pro b/src/quick3d/imports/logic/importslogic.pro index c2b33f665..955a4fd61 100644 --- a/src/quick3d/imports/logic/importslogic.pro +++ b/src/quick3d/imports/logic/importslogic.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = quick3dlogicplugin TARGETPATH = Qt3D/Logic -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += core-private qml 3dcore 3dlogic diff --git a/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp b/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp index f97bc8fc6..0fbe64002 100644 --- a/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp +++ b/src/quick3d/imports/logic/qt3dquick3dlogicplugin.cpp @@ -47,6 +47,9 @@ QT_BEGIN_NAMESPACE void Qt3DQuick3DLogicPlugin::registerTypes(const char *uri) { qmlRegisterType<Qt3DLogic::QFrameAction>(uri, 2, 0, "FrameAction"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } QT_END_NAMESPACE diff --git a/src/quick3d/imports/logic/qt3dquick3dlogicplugin.h b/src/quick3d/imports/logic/qt3dquick3dlogicplugin.h index 8f4a2fe39..d59d7d09d 100644 --- a/src/quick3d/imports/logic/qt3dquick3dlogicplugin.h +++ b/src/quick3d/imports/logic/qt3dquick3dlogicplugin.h @@ -42,13 +42,6 @@ #include <QtQml/QQmlExtensionPlugin> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt3D_Logic); -#endif -} - QT_BEGIN_NAMESPACE class Qt3DQuick3DLogicPlugin : public QQmlExtensionPlugin @@ -56,7 +49,7 @@ class Qt3DQuick3DLogicPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - Qt3DQuick3DLogicPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + Qt3DQuick3DLogicPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { } void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/imports/render/importsrender.pro b/src/quick3d/imports/render/importsrender.pro index cc34ff3df..a8d68c8ee 100644 --- a/src/quick3d/imports/render/importsrender.pro +++ b/src/quick3d/imports/render/importsrender.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = quick3drenderplugin TARGETPATH = Qt3D/Render -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += core-private qml qml-private 3dcore 3drender 3drender-private 3dquick 3dquick-private 3dquickrender-private diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp index 4b30bcd2f..9e889816c 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp @@ -296,6 +296,9 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DRender::QStencilOperation>(uri, 2, 0, "StencilOperation"); qmlRegisterType<Qt3DRender::QStencilMask>(uri, 2, 0, "StencilMask"); qmlRegisterType<Qt3DRender::QLineWidth>(uri, 2, 10, "LineWidth"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } QT_END_NAMESPACE diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.h b/src/quick3d/imports/render/qt3dquick3drenderplugin.h index 11802b179..68a5cade5 100644 --- a/src/quick3d/imports/render/qt3dquick3drenderplugin.h +++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.h @@ -42,13 +42,6 @@ #include <QtQml/QQmlExtensionPlugin> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_Qt3D_Render); -#endif -} - QT_BEGIN_NAMESPACE class Qt3DQuick3DRenderPlugin : public QQmlExtensionPlugin @@ -56,7 +49,7 @@ class Qt3DQuick3DRenderPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - Qt3DQuick3DRenderPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + Qt3DQuick3DRenderPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { } void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/imports/scene2d/importsscene2d.pro b/src/quick3d/imports/scene2d/importsscene2d.pro index 32fbc5b1b..1582d4ee4 100644 --- a/src/quick3d/imports/scene2d/importsscene2d.pro +++ b/src/quick3d/imports/scene2d/importsscene2d.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qtquickscene2dplugin TARGETPATH = QtQuick/Scene2D -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += qml quick 3dcore 3drender 3drender-private 3dinput 3dlogic 3dquickscene2d 3dquickscene2d-private diff --git a/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp b/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp index 4e6245d2d..0c410e84b 100644 --- a/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp +++ b/src/quick3d/imports/scene2d/qtquickscene2dplugin.cpp @@ -53,6 +53,9 @@ Q_COREAPP_STARTUP_FUNCTION(initScene2dPlugin) void QtQuickScene2DPlugin::registerTypes(const char *uri) { qmlRegisterExtendedType<Qt3DRender::Quick::QScene2D, Qt3DRender::Render::Quick::QQuick3DScene2D>(uri, 2, 9, "Scene2D"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } QT_END_NAMESPACE diff --git a/src/quick3d/imports/scene2d/qtquickscene2dplugin.h b/src/quick3d/imports/scene2d/qtquickscene2dplugin.h index 7e97fd662..22a4e9b7a 100644 --- a/src/quick3d/imports/scene2d/qtquickscene2dplugin.h +++ b/src/quick3d/imports/scene2d/qtquickscene2dplugin.h @@ -39,13 +39,6 @@ #include <QtQml/qqmlextensionplugin.h> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_QtQuick_Scene2D); -#endif -} - QT_BEGIN_NAMESPACE class QtQuickScene2DPlugin : public QQmlExtensionPlugin @@ -53,7 +46,7 @@ class QtQuickScene2DPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - QtQuickScene2DPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + QtQuickScene2DPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { } void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/imports/scene3d/importsscene3d.pro b/src/quick3d/imports/scene3d/importsscene3d.pro index e41dc8c84..cf8d7cacf 100644 --- a/src/quick3d/imports/scene3d/importsscene3d.pro +++ b/src/quick3d/imports/scene3d/importsscene3d.pro @@ -1,7 +1,7 @@ CXX_MODULE = qml TARGET = qtquickscene3dplugin TARGETPATH = QtQuick/Scene3D -IMPORT_VERSION = 2.0 +IMPORT_VERSION = 2.$$QT_MINOR_VERSION QT += qml quick 3dcore 3drender 3drender-private diff --git a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp index 6b9ec96f8..d7b985e9f 100644 --- a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp +++ b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp @@ -48,6 +48,9 @@ QT_BEGIN_NAMESPACE void QtQuickScene3DPlugin::registerTypes(const char *uri) { qmlRegisterType<Qt3DRender::Scene3DItem>(uri, 2, 0, "Scene3D"); + + // Auto-increment the import to stay in sync with ALL future Qt minor versions + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); } QT_END_NAMESPACE diff --git a/src/quick3d/imports/scene3d/qtquickscene3dplugin.h b/src/quick3d/imports/scene3d/qtquickscene3dplugin.h index 44a69a805..c70b8358b 100644 --- a/src/quick3d/imports/scene3d/qtquickscene3dplugin.h +++ b/src/quick3d/imports/scene3d/qtquickscene3dplugin.h @@ -42,13 +42,6 @@ #include <QtQml/QQmlExtensionPlugin> -static void initResources() -{ -#ifdef QT_STATIC - Q_INIT_RESOURCE(qmake_QtQuick_Scene3D); -#endif -} - QT_BEGIN_NAMESPACE class QtQuickScene3DPlugin : public QQmlExtensionPlugin @@ -56,7 +49,7 @@ class QtQuickScene3DPlugin : public QQmlExtensionPlugin Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - QtQuickScene3DPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + QtQuickScene3DPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { } void registerTypes(const char *uri) override; }; diff --git a/src/quick3d/quick3d/items/quick3dentityloader.cpp b/src/quick3d/quick3d/items/quick3dentityloader.cpp index 48f2af658..61801e8df 100644 --- a/src/quick3d/quick3d/items/quick3dentityloader.cpp +++ b/src/quick3d/quick3d/items/quick3dentityloader.cpp @@ -192,6 +192,24 @@ void Quick3DEntityLoader::setSource(const QUrl &url) d->loadFromSource(); } +QQmlComponent *Quick3DEntityLoader::sourceComponent() const +{ + Q_D(const Quick3DEntityLoader); + return d->m_sourceComponent; +} + +void Quick3DEntityLoader::setSourceComponent(QQmlComponent *component) +{ + Q_D(Quick3DEntityLoader); + if (d->m_sourceComponent == component) + return; + + d->clear(); + d->m_sourceComponent = component; + emit sourceComponentChanged(); + d->loadComponent(d->m_sourceComponent); +} + /*! \qmlproperty Status Qt3DCore::EntityLoader::status @@ -214,6 +232,7 @@ Quick3DEntityLoaderPrivate::Quick3DEntityLoaderPrivate() m_incubator(nullptr), m_context(nullptr), m_component(nullptr), + m_sourceComponent(nullptr), m_entity(nullptr), m_status(Quick3DEntityLoader::Null) { @@ -233,10 +252,11 @@ void Quick3DEntityLoaderPrivate::clear() m_entity = nullptr; } - if (m_component) { + // Only delete m_component if we were loading from a URL otherwise it means + // m_component = m_sourceComponent which we don't own. + if (m_component && m_component != m_sourceComponent) delete m_component; - m_component = nullptr; - } + m_component = nullptr; if (m_context) { delete m_context; @@ -271,17 +291,36 @@ void Quick3DEntityLoaderPrivate::loadComponent(const QUrl &source) m_component->loadUrl(source, QQmlComponent::Asynchronous); } +void Quick3DEntityLoaderPrivate::loadComponent(QQmlComponent *component) +{ + Q_Q(Quick3DEntityLoader); + + Q_ASSERT(m_entity == nullptr); + Q_ASSERT(m_component == nullptr); + Q_ASSERT(m_context == nullptr); + + m_component = component; + _q_componentStatusChanged(m_component ? m_component->status() : QQmlComponent::Null); +} + void Quick3DEntityLoaderPrivate::_q_componentStatusChanged(QQmlComponent::Status status) { Q_Q(Quick3DEntityLoader); Q_ASSERT(m_entity == nullptr); - Q_ASSERT(m_component != nullptr); Q_ASSERT(m_context == nullptr); Q_ASSERT(m_incubator == nullptr); - auto owner = _q_findQmlOwner(q); + qDebug() << Q_FUNC_INFO << status; + + if (!m_component) { + clear(); + emit q->entityChanged(); + return; + } + + auto owner = _q_findQmlOwner(q); if (!m_component->errors().isEmpty()) { QQmlEnginePrivate::warning(owner.engine, m_component->errors()); clear(); diff --git a/src/quick3d/quick3d/items/quick3dentityloader_p.h b/src/quick3d/quick3d/items/quick3dentityloader_p.h index 6a2fe5473..beb72ba79 100644 --- a/src/quick3d/quick3d/items/quick3dentityloader_p.h +++ b/src/quick3d/quick3d/items/quick3dentityloader_p.h @@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE +class QQmlComponent; + namespace Qt3DCore { class QEntity; @@ -74,6 +76,7 @@ class QT3DQUICKSHARED_PRIVATE_EXPORT Quick3DEntityLoader : public QEntity Q_PROPERTY(QObject *entity READ entity NOTIFY entityChanged) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(QQmlComponent *sourceComponent WRITE setSourceComponent NOTIFY sourceComponentChanged REVISION 12) public: enum Status { Null = 0, @@ -91,11 +94,15 @@ public: QUrl source() const; void setSource(const QUrl &url); + QQmlComponent *sourceComponent() const; + void setSourceComponent(QQmlComponent *components); + Status status() const; Q_SIGNALS: void entityChanged(); void sourceChanged(); + void sourceComponentChanged(); void statusChanged(Status status); private: diff --git a/src/quick3d/quick3d/items/quick3dentityloader_p_p.h b/src/quick3d/quick3d/items/quick3dentityloader_p_p.h index 4d067f0e6..b37990d34 100644 --- a/src/quick3d/quick3d/items/quick3dentityloader_p_p.h +++ b/src/quick3d/quick3d/items/quick3dentityloader_p_p.h @@ -79,6 +79,7 @@ public: void clear(); void loadFromSource(); void loadComponent(const QUrl &source); + void loadComponent(QQmlComponent *component); void _q_componentStatusChanged(QQmlComponent::Status status); void setStatus(Quick3DEntityLoader::Status status); @@ -89,6 +90,7 @@ public: Quick3DEntityLoaderIncubator *m_incubator; QQmlContext *m_context; QQmlComponent *m_component; + QQmlComponent *m_sourceComponent; QEntity *m_entity; Quick3DEntityLoader::Status m_status; }; diff --git a/src/quick3d/quick3d/qt3dquick_global.cpp b/src/quick3d/quick3d/qt3dquick_global.cpp index cef480240..aa2a94860 100644 --- a/src/quick3d/quick3d/qt3dquick_global.cpp +++ b/src/quick3d/quick3d/qt3dquick_global.cpp @@ -276,7 +276,7 @@ public: float matVals[16]; QV4::ScopedValue v(scope); for (quint32 i = 0; i < 16; ++i) { - v = array->getIndexed(i); + v = array->get(i); if (!v->isNumber()) return QMatrix4x4(); matVals[i] = v->asDouble(); diff --git a/src/render/backend/managers.cpp b/src/render/backend/managers.cpp index 6e8c1376d..3b1f8e910 100644 --- a/src/render/backend/managers.cpp +++ b/src/render/backend/managers.cpp @@ -88,7 +88,7 @@ void SkeletonManager::addDirtySkeleton(DirtyFlag dirtyFlag, HSkeleton skeletonHa } } -QVector<HSkeleton> SkeletonManager::dirtySkeletons(DirtyFlag dirtyFlag) +QVector<HSkeleton> SkeletonManager::takeDirtySkeletons(DirtyFlag dirtyFlag) { switch (dirtyFlag) { case SkeletonDataDirty: diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h index 312889a43..b62e2f3e0 100644 --- a/src/render/backend/managers_p.h +++ b/src/render/backend/managers_p.h @@ -414,7 +414,7 @@ public: }; void addDirtySkeleton(DirtyFlag dirtyFlag, HSkeleton skeletonHandle); - QVector<HSkeleton> dirtySkeletons(DirtyFlag dirtyFlag); + QVector<HSkeleton> takeDirtySkeletons(DirtyFlag dirtyFlag); private: QVector<HSkeleton> m_dirtyDataSkeletons; diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp index 0a60edef7..3cf19d0d8 100644 --- a/src/render/framegraph/qframegraphnode.cpp +++ b/src/render/framegraph/qframegraphnode.cpp @@ -41,6 +41,12 @@ #include "qframegraphnode_p.h" #include <Qt3DRender/qframegraphnodecreatedchange.h> +#include <Qt3DCore/QNode> + +#include <QQueue> + +using namespace Qt3DCore; + QT_BEGIN_NAMESPACE namespace Qt3DRender { @@ -190,7 +196,10 @@ QFrameGraphNode::~QFrameGraphNode() } /*! - Returns a pointer to the parent. + Returns a pointer to the parent frame graph node. + + If the parent of this node is not a frame graph node, + this method will recursively look for a parent node that is a frame graph node. */ QFrameGraphNode *QFrameGraphNode::parentFrameGraphNode() const { @@ -205,6 +214,31 @@ QFrameGraphNode *QFrameGraphNode::parentFrameGraphNode() const return parentFGNode; } +/*! + * Returns a list of the children that are frame graph nodes. + * If this function encounters a child node that is not a frame graph node, + * it will go through the children of the child node and look for frame graph nodes. + * If any of these are not frame graph nodes, they will be further searched as + * if they were direct children of this node. + */ +QVector<QFrameGraphNode *> QFrameGraphNodePrivate::childFrameGraphNodes() const +{ + Q_Q(const QFrameGraphNode); + QVector<QFrameGraphNode *> result; + QQueue<QNode *> queue; + queue.append(q->childNodes().toList()); + result.reserve(queue.size()); + while (!queue.isEmpty()) { + auto *child = queue.dequeue(); + auto *childFGNode = qobject_cast<QFrameGraphNode *>(child); + if (childFGNode != nullptr) + result.push_back(childFGNode); + else + queue.append(child->childNodes().toList()); + } + return result; +} + /*! \internal */ QFrameGraphNode::QFrameGraphNode(QFrameGraphNodePrivate &dd, QNode *parent) : QNode(dd, parent) diff --git a/src/render/framegraph/qframegraphnode_p.h b/src/render/framegraph/qframegraphnode_p.h index 00cc53626..c03017638 100644 --- a/src/render/framegraph/qframegraphnode_p.h +++ b/src/render/framegraph/qframegraphnode_p.h @@ -65,9 +65,12 @@ class QFrameGraphNodePrivate : public Qt3DCore::QNodePrivate { public: QFrameGraphNodePrivate(); + QVector<QFrameGraphNode *> childFrameGraphNodes() const; + + static QFrameGraphNodePrivate *get(QFrameGraphNode *node) { return node->d_func(); } + static const QFrameGraphNodePrivate *get(const QFrameGraphNode *node) { return node->d_func(); } Q_DECLARE_PUBLIC(QFrameGraphNode) - QList<QFrameGraphNode *> m_fgChildren; }; } // namespace Qt3DRender diff --git a/src/render/framegraph/qframegraphnodecreatedchange.cpp b/src/render/framegraph/qframegraphnodecreatedchange.cpp index ef51d5228..464c98bc3 100644 --- a/src/render/framegraph/qframegraphnodecreatedchange.cpp +++ b/src/render/framegraph/qframegraphnodecreatedchange.cpp @@ -36,7 +36,9 @@ #include "qframegraphnodecreatedchange.h" #include "qframegraphnodecreatedchange_p.h" + #include <Qt3DRender/qframegraphnode.h> +#include <Qt3DRender/private/qframegraphnode_p.h> QT_BEGIN_NAMESPACE @@ -45,6 +47,7 @@ namespace Qt3DRender { QFrameGraphNodeCreatedChangeBasePrivate::QFrameGraphNodeCreatedChangeBasePrivate(const QFrameGraphNode *node) : Qt3DCore::QNodeCreatedChangeBasePrivate(node) , m_parentFrameGraphNodeId(Qt3DCore::qIdForNode(node->parentFrameGraphNode())) + , m_childFrameGraphNodeIds(Qt3DCore::qIdsForNodes(QFrameGraphNodePrivate::get(node)->childFrameGraphNodes())) { } diff --git a/src/render/framegraph/qframegraphnodecreatedchange_p.h b/src/render/framegraph/qframegraphnodecreatedchange_p.h index 9aa396b8f..c0437afc5 100644 --- a/src/render/framegraph/qframegraphnodecreatedchange_p.h +++ b/src/render/framegraph/qframegraphnodecreatedchange_p.h @@ -49,6 +49,7 @@ // #include <Qt3DCore/private/qnodecreatedchange_p.h> +#include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE @@ -62,6 +63,16 @@ public: QFrameGraphNodeCreatedChangeBasePrivate(const QFrameGraphNode *node); Qt3DCore::QNodeId m_parentFrameGraphNodeId; + Qt3DCore::QNodeIdVector m_childFrameGraphNodeIds; + + static QFrameGraphNodeCreatedChangeBasePrivate *get(QFrameGraphNodeCreatedChangeBase *change) + { + return change->d_func(); + } + static const QFrameGraphNodeCreatedChangeBasePrivate *get(const QFrameGraphNodeCreatedChangeBase *change) + { + return change->d_func(); + } }; } // Qt3DRender diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 09cb75e46..ccec826ff 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -481,7 +481,7 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) // which should likely be renamed to something more generic or we introduce // another synchronizing job for skeleton loading const QVector<Render::HSkeleton> skeletonsToLoad = - manager->skeletonManager()->dirtySkeletons(Render::SkeletonManager::SkeletonDataDirty); + manager->skeletonManager()->takeDirtySkeletons(Render::SkeletonManager::SkeletonDataDirty); for (const auto &skeletonHandle : skeletonsToLoad) { auto loadSkeletonJob = Render::LoadSkeletonJobPtr::create(skeletonHandle); loadSkeletonJob->setNodeManagers(manager); diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h index b76c8389f..e9378e3c5 100644 --- a/src/render/materialsystem/shaderbuilder_p.h +++ b/src/render/materialsystem/shaderbuilder_p.h @@ -61,7 +61,7 @@ namespace Qt3DRender { namespace Render { -class Q_AUTOTEST_EXPORT ShaderBuilder : public BackendNode +class QT3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilder : public BackendNode { public: enum ShaderType { diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp index 1e2035c01..59b5701f8 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp @@ -226,7 +226,7 @@ QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode) const auto shaderCode = shaderNode->shaderCode(); QString logs; for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) { - const QShaderProgram::ShaderType type = static_cast<const QShaderProgram::ShaderType>(i); + const QShaderProgram::ShaderType type = static_cast<QShaderProgram::ShaderType>(i); if (!shaderCode.at(i).isEmpty()) { // Note: logs only return the error but not all the shader code // we could append it diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 7319fd0e5..c9ba6409d 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -243,11 +243,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) Renderer::~Renderer() { - // If using a threaded rendering approach, tell the thread to exit - // and wait for it to be done - m_running.fetchAndStoreOrdered(0); + Q_ASSERT(m_running.fetchAndStoreOrdered(0) == 0); if (m_renderThread) - m_renderThread->wait(); + Q_ASSERT(m_renderThread->isFinished()); delete m_renderQueue; delete m_defaultRenderStateSet; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 6bb3597ea..971edcb39 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -3,7 +3,8 @@ TEMPLATE = subdirs SUBDIRS = \ coretest \ core \ - cmake + cmake \ + global installed_cmake.depends = cmake diff --git a/tests/auto/core/qentity/tst_qentity.cpp b/tests/auto/core/qentity/tst_qentity.cpp index efebb26ef..e27cd1fc9 100644 --- a/tests/auto/core/qentity/tst_qentity.cpp +++ b/tests/auto/core/qentity/tst_qentity.cpp @@ -556,30 +556,55 @@ void tst_Entity::removeSeveralTimesSameComponent() void tst_Entity::checkCloning_data() { QTest::addColumn<Qt3DCore::QEntity *>("entity"); + QTest::addColumn<QVector<QNodeId>>("childEntityIds"); + QTest::addColumn<int>("creationChangeCount"); - QTest::newRow("defaultConstructed") << new MyEntity(); + { + QTest::newRow("defaultConstructed") << new MyEntity() << QVector<QNodeId>() << 1; + } + + { + Qt3DCore::QEntity *entityWithComponents = new MyEntity(); + Qt3DCore::QComponent *component1 = new MyQComponent(); + Qt3DCore::QComponent *component2 = new MyQComponent(); + Qt3DCore::QComponent *component3 = new MyQComponent(); + entityWithComponents->addComponent(component1); + entityWithComponents->addComponent(component2); + entityWithComponents->addComponent(component3); + QTest::newRow("entityWithComponents") << entityWithComponents << QVector<QNodeId>() << 4; + } - Qt3DCore::QEntity *entityWithComponents = new MyEntity(); - Qt3DCore::QComponent *component1 = new MyQComponent(); - Qt3DCore::QComponent *component2 = new MyQComponent(); - Qt3DCore::QComponent *component3 = new MyQComponent(); - entityWithComponents->addComponent(component1); - entityWithComponents->addComponent(component2); - entityWithComponents->addComponent(component3); - QTest::newRow("entityWithComponents") << entityWithComponents; + { + Qt3DCore::QEntity *entityWithChildren = new MyEntity(); + Qt3DCore::QEntity *child1 = new MyEntity(entityWithChildren); + Qt3DCore::QEntity *child2 = new MyEntity(entityWithChildren); + QVector<QNodeId> childIds = {child1->id(), child2->id()}; + QTest::newRow("entityWithChildren") << entityWithChildren << childIds << 3; + } + + { + Qt3DCore::QEntity *entityWithNestedChildren = new MyEntity(); + Qt3DCore::QEntity *child = new MyEntity(entityWithNestedChildren); + Qt3DCore::QNode *dummy = new Qt3DCore::QNode(entityWithNestedChildren); + Qt3DCore::QEntity *grandChild = new MyEntity(entityWithNestedChildren); + QVector<QNodeId> childIds = {child->id(), grandChild->id()}; + QTest::newRow("entityWithNestedChildren") << entityWithNestedChildren << childIds << 4; + } } void tst_Entity::checkCloning() { // GIVEN QFETCH(Qt3DCore::QEntity *, entity); + QFETCH(QVector<QNodeId>, childEntityIds); + QFETCH(int, creationChangeCount); // WHEN Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(entity); QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); // THEN - QCOMPARE(creationChanges.size(), 1 + entity->components().size()); + QCOMPARE(creationChanges.size(), creationChangeCount); const Qt3DCore::QNodeCreatedChangePtr<Qt3DCore::QEntityData> creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DCore::QEntityData>>(creationChanges.first()); @@ -591,6 +616,7 @@ void tst_Entity::checkCloning() QCOMPARE(creationChangeData->metaObject(), entity->metaObject()); QCOMPARE(creationChangeData->parentId(), entity->parentNode() ? entity->parentNode()->id() : Qt3DCore::QNodeId()); QCOMPARE(cloneData.parentEntityId, entity->parentEntity() ? entity->parentEntity()->id() : Qt3DCore::QNodeId()); + QCOMPARE(cloneData.childEntityIds, childEntityIds); QCOMPARE(cloneData.componentIdsAndTypes.size(), entity->components().size()); const QVector<Qt3DCore::QComponent *> &components = entity->components(); diff --git a/tests/auto/global/aspects_startup_shutdown/aspects_startup_shutdown.pro b/tests/auto/global/aspects_startup_shutdown/aspects_startup_shutdown.pro new file mode 100644 index 000000000..0319ae1c3 --- /dev/null +++ b/tests/auto/global/aspects_startup_shutdown/aspects_startup_shutdown.pro @@ -0,0 +1,7 @@ +TARGET = tst_aspects_startup_shutdown +CONFIG += testcase +TEMPLATE = app + +SOURCES += tst_aspects_startup_shutdown.cpp + +QT += testlib 3dcore 3drender 3dinput 3dextras diff --git a/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp b/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp new file mode 100644 index 000000000..9eec010be --- /dev/null +++ b/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <Qt3DCore/QEntity> +#include <Qt3DCore/QTransform> +#include <Qt3DCore/QAspectEngine> + +#include <Qt3DInput/QInputAspect> +#include <Qt3DInput/QInputSettings> + +#include <Qt3DLogic/QLogicAspect> + +#include <Qt3DRender/QCamera> +#include <Qt3DRender/QCameraLens> +#include <Qt3DRender/QRenderAspect> +#include <Qt3DRender/QRenderSettings> + +#include <Qt3DExtras/QForwardRenderer> +#include <Qt3DExtras/Qt3DWindow> +#include <Qt3DExtras/QPhongMaterial> +#include <Qt3DExtras/QSphereMesh> +#include <Qt3DExtras/QTorusMesh> + +#include <QPropertyAnimation> + +namespace { + +Qt3DCore::QEntity *createScene(QWindow *w) +{ + // Root entity + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity; + + // Camera + Qt3DRender::QCamera *camera = new Qt3DRender::QCamera(rootEntity); + camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); + camera->setPosition(QVector3D(0, 0, 40.0f)); + camera->setViewCenter(QVector3D(0, 0, 0)); + + // FrameGraph + Qt3DRender::QRenderSettings *renderSettings = new Qt3DRender::QRenderSettings(); + Qt3DExtras::QForwardRenderer *forwardRenderer = new Qt3DExtras::QForwardRenderer(); + forwardRenderer->setSurface(w); + forwardRenderer->setCamera(camera); + forwardRenderer->setClearColor(QColor(Qt::blue)); + renderSettings->setActiveFrameGraph(forwardRenderer); + rootEntity->addComponent(renderSettings); + + // InputSettings + Qt3DInput::QInputSettings *inputSettigns = new Qt3DInput::QInputSettings(); + rootEntity->addComponent(inputSettigns); + + // Material + Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity); + + // Torus + Qt3DCore::QEntity *torusEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DExtras::QTorusMesh *torusMesh = new Qt3DExtras::QTorusMesh; + torusMesh->setRadius(5); + torusMesh->setMinorRadius(1); + torusMesh->setRings(100); + torusMesh->setSlices(20); + + Qt3DCore::QTransform *torusTransform = new Qt3DCore::QTransform; + torusTransform->setScale3D(QVector3D(1.5, 1, 0.5)); + torusTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f)); + + torusEntity->addComponent(torusMesh); + torusEntity->addComponent(torusTransform); + torusEntity->addComponent(material); + + // Sphere + Qt3DCore::QEntity *sphereEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DExtras::QSphereMesh *sphereMesh = new Qt3DExtras::QSphereMesh; + sphereMesh->setRadius(3); + + Qt3DCore::QTransform *sphereTransform = new Qt3DCore::QTransform; + + sphereEntity->addComponent(sphereMesh); + sphereEntity->addComponent(sphereTransform); + sphereEntity->addComponent(material); + + return rootEntity; +} + +} // anonymous + +class tst_AspectsStartupShutdown : public QObject +{ + Q_OBJECT + +public: + +private slots: + + void checkStartupAndShutdownImmediately() + { + // GIVEN + QWindow *win = new QWindow(); + win->setSurfaceType(QSurface::OpenGLSurface); + win->resize(1024, 768); + win->show(); + + // WHEN + Qt3DCore::QAspectEngine *engine = new Qt3DCore::QAspectEngine(); + engine->registerAspect(new Qt3DRender::QRenderAspect()); + engine->registerAspect(new Qt3DInput::QInputAspect()); + engine->registerAspect(new Qt3DLogic::QLogicAspect()); + QPointer<Qt3DCore::QEntity> scene = createScene(win); + engine->setRootEntity(Qt3DCore::QEntityPtr(scene.data())); + + // THEN + QCOMPARE(engine->rootEntity().data(), scene.data()); + + // WHEN + win->close(); + delete engine; + + // THEN -> shouldn't crash or deadlock + delete win; + } + + void checkStartupAndShutdownAfterAFewFrames() + { + // GIVEN + QWindow *win = new QWindow(); + win->setSurfaceType(QSurface::OpenGLSurface); + win->resize(1024, 768); + win->show(); + + // WHEN + Qt3DCore::QAspectEngine *engine = new Qt3DCore::QAspectEngine(); + engine->registerAspect(new Qt3DRender::QRenderAspect()); + engine->registerAspect(new Qt3DInput::QInputAspect()); + engine->registerAspect(new Qt3DLogic::QLogicAspect()); + QPointer<Qt3DCore::QEntity> scene = createScene(win); + engine->setRootEntity(Qt3DCore::QEntityPtr(scene.data())); + + // THEN + QCOMPARE(engine->rootEntity().data(), scene.data()); + + // Allow a few frames + for (int i = 0; i < 10; ++i) { + QCoreApplication::processEvents(); + QThread::msleep(16); + } + + // WHEN + // Right now we need to close the window before destroying + // the engine to prevent the render thread from trying to render + // while things are being destroyed + win->close(); + delete engine; + + // THEN -> shouldn't crash or deadlock + delete win; + } +}; + +QTEST_MAIN(tst_AspectsStartupShutdown) + +#include "tst_aspects_startup_shutdown.moc" diff --git a/tests/auto/global/global.pro b/tests/auto/global/global.pro new file mode 100644 index 000000000..7fca20c44 --- /dev/null +++ b/tests/auto/global/global.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs + +QT_FOR_CONFIG += 3dcore + +qtConfig(qt3d-render):qtConfig(qt3d-input):qtConfig(qt3d-extras):qtConfig(qt3d-render):qtConfig(qt3d-logic) { + SUBDIRS += \ + aspects_startup_shutdown +} diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp index 626f7811e..7a199e9e6 100644 --- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -190,6 +190,8 @@ private Q_SLOTS: // THEN QCOMPARE(backendFilterCompatibleTechniqueJob.manager(), &techniqueManager); QCOMPARE(backendFilterCompatibleTechniqueJob.renderer(), &renderer); + + renderer.shutdown(); } void checkRunRendererRunning() diff --git a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp index b06da033c..1e19d8609 100644 --- a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp +++ b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp @@ -35,6 +35,8 @@ #include <Qt3DRender/qframegraphnode.h> #include <Qt3DRender/private/qframegraphnode_p.h> #include <Qt3DRender/qframegraphnodecreatedchange.h> +#include <Qt3DRender/private/qframegraphnodecreatedchange_p.h> + #include "testpostmanarbiter.h" class MyFrameGraphNode : public Qt3DRender::QFrameGraphNode @@ -64,21 +66,48 @@ private Q_SLOTS: void checkCloning_data() { QTest::addColumn<Qt3DRender::QFrameGraphNode *>("frameGraphNode"); + QTest::addColumn<QVector<Qt3DCore::QNodeId>>("childFrameGraphNodeIds"); QTest::addColumn<bool>("enabled"); + QTest::addColumn<int>("creationChangeCount"); + + QVector<Qt3DCore::QNodeId> noChildIds; + + { + Qt3DRender::QFrameGraphNode *defaultConstructed = new MyFrameGraphNode(); + QTest::newRow("defaultConstructed") << defaultConstructed << noChildIds << true << 1; + } + + { + Qt3DRender::QFrameGraphNode *disabledFrameGraphNode = new MyFrameGraphNode(); + disabledFrameGraphNode->setEnabled(false); + QTest::newRow("allBuffers") << disabledFrameGraphNode << noChildIds << false << 1; + } - Qt3DRender::QFrameGraphNode *defaultConstructed = new MyFrameGraphNode(); - QTest::newRow("defaultConstructed") << defaultConstructed << true; + { + Qt3DRender::QFrameGraphNode *nodeWithChildren = new MyFrameGraphNode(); + Qt3DRender::QFrameGraphNode *child1 = new MyFrameGraphNode(nodeWithChildren); + Qt3DRender::QFrameGraphNode *child2 = new MyFrameGraphNode(nodeWithChildren); + QVector<Qt3DCore::QNodeId> childIds = {child1->id(), child2->id()}; + QTest::newRow("nodeWithChildren") << nodeWithChildren << childIds << true << 3; + } - Qt3DRender::QFrameGraphNode *disabledFrameGraphNode = new MyFrameGraphNode(); - disabledFrameGraphNode->setEnabled(false); - QTest::newRow("allBuffers") << disabledFrameGraphNode << false; + { + Qt3DRender::QFrameGraphNode *nodeWithNestedChildren = new MyFrameGraphNode(); + Qt3DRender::QFrameGraphNode *child = new MyFrameGraphNode(nodeWithNestedChildren); + Qt3DCore::QNode *dummy = new Qt3DCore::QNode(nodeWithNestedChildren); + Qt3DRender::QFrameGraphNode *grandChild = new MyFrameGraphNode(nodeWithNestedChildren); + QVector<Qt3DCore::QNodeId> childIds = {child->id(), grandChild->id()}; + QTest::newRow("nodeWithNestedChildren") << nodeWithNestedChildren << childIds << true << 4; + } } void checkCloning() { // GIVEN QFETCH(Qt3DRender::QFrameGraphNode *, frameGraphNode); + QFETCH(QVector<Qt3DCore::QNodeId>, childFrameGraphNodeIds); QFETCH(bool, enabled); + QFETCH(int, creationChangeCount); // THEN QCOMPARE(frameGraphNode->isEnabled(), enabled); @@ -88,7 +117,7 @@ private Q_SLOTS: QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); // THEN - QCOMPARE(creationChanges.size(), 1); + QCOMPARE(creationChanges.size(), creationChangeCount); const Qt3DCore::QNodeCreatedChangeBasePtr creationChangeData = creationChanges.first(); // THEN @@ -96,6 +125,12 @@ private Q_SLOTS: QCOMPARE(frameGraphNode->isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(frameGraphNode->metaObject(), creationChangeData->metaObject()); + // THEN + Qt3DRender::QFrameGraphNodeCreatedChangeBasePtr frameGraphNodeCreatedChange = qSharedPointerCast<Qt3DRender::QFrameGraphNodeCreatedChangeBase>(creationChangeData); + Qt3DRender::QFrameGraphNodeCreatedChangeBasePrivate *creationChangeDataPrivate = Qt3DRender::QFrameGraphNodeCreatedChangeBasePrivate::get(frameGraphNodeCreatedChange.get()); + QCOMPARE(creationChangeDataPrivate->m_parentFrameGraphNodeId, frameGraphNode->parentNode() ? frameGraphNode->parentNode()->id() : Qt3DCore::QNodeId()); + QCOMPARE(creationChangeDataPrivate->m_childFrameGraphNodeIds, childFrameGraphNodeIds); + delete frameGraphNode; } diff --git a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp index 9cd2054d6..53a646ccd 100644 --- a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp +++ b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp @@ -76,6 +76,7 @@ private Q_SLOTS: QCOMPARE(data.data()->image.format(), QImage::Format_ARGB32); // renderCapture will be deallocated by the nodeManagers destructor + renderer.shutdown(); } }; diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp index f1b72b33b..8bd4b355c 100644 --- a/tests/auto/render/textures/tst_textures.cpp +++ b/tests/auto/render/textures/tst_textures.cpp @@ -211,6 +211,8 @@ private Q_SLOTS: // THEN QCOMPARE(mgrs->glTextureManager()->lookupResource(bt1a->peerId()), mgrs->glTextureManager()->lookupResource(bt1b->peerId())); + + renderer.shutdown(); } void shouldCreateDifferentGLTexturess() @@ -264,6 +266,8 @@ private Q_SLOTS: QCOMPARE(glTextures[0]->properties(), glTextures[2]->properties()); QCOMPARE(glTextures[1]->properties(), glTextures[3]->properties()); QVERIFY(glTextures[0]->properties() != glTextures[1]->properties()); + + renderer.shutdown(); } void generatorsShouldCreateSameData() @@ -334,6 +338,8 @@ private Q_SLOTS: QCOMPARE(texDataMgr->getData(tg1a), texDataMgr->getData(tg1b)); QVERIFY(texDataMgr->getData(tg1a) != texDataMgr->getData(tg2)); + + renderer.shutdown(); } void checkTextureImageInitialState() @@ -538,6 +544,8 @@ private Q_SLOTS: renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); backendImage.unsetDirty(); } + + renderer.shutdown(); } void checkTextureImageProperlyReleaseGenerator() @@ -601,6 +609,8 @@ private Q_SLOTS: QCOMPARE(texImgDataMgr->pendingGenerators().size(), 0); QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull()); QVERIFY(texImgDataMgr->getData(backendGenerator).isNull()); + + renderer.shutdown(); } void checkTextureIsMarkedForDeletion() @@ -632,6 +642,8 @@ private Q_SLOTS: QCOMPARE(texMgr->textureIdsToCleanup().size(), 1); QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id()); QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr); + + renderer.shutdown(); } void checkTextureDestructionReconstructionWithinSameLoop() @@ -666,6 +678,8 @@ private Q_SLOTS: QVERIFY(backendTexture != nullptr); QCOMPARE(texMgr->textureIdsToCleanup().size(), 0); QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture); + + renderer.shutdown(); } void checkTextureImageDirtinessPropagatesToTextures() @@ -777,6 +791,8 @@ private Q_SLOTS: QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); QVERIFY(backendTexture2->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); + + renderer.shutdown(); } }; diff --git a/tests/manual/dynamic-model-loader-qml/main.qml b/tests/manual/dynamic-model-loader-qml/main.qml index 72d0529b8..dc6b929cf 100644 --- a/tests/manual/dynamic-model-loader-qml/main.qml +++ b/tests/manual/dynamic-model-loader-qml/main.qml @@ -49,7 +49,7 @@ ****************************************************************************/ import QtQuick 2.2 as QQ2 -import Qt3D.Core 2.0 +import Qt3D.Core 2.12 import Qt3D.Render 2.0 import Qt3D.Input 2.0 import Qt3D.Extras 2.0 @@ -81,44 +81,27 @@ Entity { InputSettings { } ] - - PhongMaterial { - id: material - diffuse: "yellow" - } - - TorusMesh { - id: torusMesh - radius: 5 - minorRadius: 1 - rings: 100 - slices: 20 - } - - Transform { - id: torusTransform - scale3D: Qt.vector3d(1.5, 1, 0.5) - rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) - } - - Entity { - id: torusEntity - components: [ torusMesh, material, torusTransform ] - } - QQ2.Timer { + id: timer interval: 1000 running: true repeat: true property bool addMore: true + property bool odd: false onTriggered: { if (instantiator.model > 10 || instantiator.model < 2) addMore = !addMore instantiator.model += (addMore ? 1 : -1) + odd = !odd } } + PhongMaterial { + id: material + diffuse: "yellow" + } + NodeInstantiator { id: instantiator model: 2 @@ -135,6 +118,46 @@ Entity { } source: model.index % 2 === 0 ? "qrc:/CuboidEntity.qml" : "qrc:/SphereEntity.qml" } + } + + + EntityLoader { + sourceComponent: timer.odd ? cylEntityCmp : torusEntityCmp + } + + QQ2.Component { + id: cylEntityCmp + Entity { + CylinderMesh { + id: cylMesh + } + PhongMaterial { + id: phong + } + components: [cylMesh, phong] + } } + + QQ2.Component { + id: torusEntityCmp + Entity { + TorusMesh { + id: torusMesh + radius: 5 + minorRadius: 1 + rings: 100 + slices: 20 + } + + Transform { + id: torusTransform + scale3D: Qt.vector3d(1.5, 1, 0.5) + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) + } + + components: [ torusMesh, material, torusTransform ] + } + } + } |