diff options
Diffstat (limited to 'tests')
21 files changed, 1105 insertions, 140 deletions
diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index 1226f9498..c600da690 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -5,7 +5,6 @@ SUBDIRS += \ qanimationcliploader \ qclipanimator \ qblendedclipanimator \ - qchannelmapping \ qchannelmapper \ qclipblendvalue \ qanimationcontroller \ @@ -40,5 +39,6 @@ qtConfig(private_tests) { qabstractanimation \ clock \ skeleton \ - findrunningclipanimatorsjob + findrunningclipanimatorsjob \ + qchannelmapping } diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index ee393b366..7a7abb1b3 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -147,7 +147,8 @@ public: const Qt3DCore::QNodeId targetId, const QString &property, const char *propertyName, - int type) + int type, + int componentCount) { auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); @@ -159,6 +160,7 @@ public: channelMapping->setChannelName(channelName); channelMapping->setType(type); channelMapping->setMappingType(ChannelMapping::ChannelMappingType); + channelMapping->setComponentCount(componentCount); return channelMapping; } @@ -292,28 +294,43 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); QVector<ChannelMapping *> channelMappings = { channelMapping }; // Create a few channels in the format description ChannelNameAndType rotation = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), + 4, channelMapping->peerId() }; ChannelNameAndType location = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }; ChannelNameAndType baseColor = { QLatin1String("BaseColor"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }; ChannelNameAndType metalness = { QLatin1String("Metalness"), static_cast<int>(QVariant::Double), + 1, channelMapping->peerId() }; ChannelNameAndType roughness = { QLatin1String("Roughness"), static_cast<int>(QVariant::Double), + 1, channelMapping->peerId() }; + ChannelNameAndType morphTargetWeightsList = { QLatin1String("MorphTargetWeightsList"), + static_cast<int>(QVariant::List), + 5, + channelMapping->peerId() }; + ChannelNameAndType morphTargetWeightsVec = { QLatin1String("MorphTargetWeightsVec"), + qMetaTypeId<QVector<float>>(), + 6, + channelMapping->peerId() }; QVector<ChannelNameAndType> channelNamesAndTypes - = { rotation, location, baseColor, metalness, roughness }; + = { rotation, location, baseColor, metalness, roughness, + morphTargetWeightsList, morphTargetWeightsVec }; // And the matching indices ComponentIndices rotationIndices = { 0, 1, 2, 3 }; @@ -321,15 +338,20 @@ private Q_SLOTS: ComponentIndices baseColorIndices = { 7, 8, 9 }; ComponentIndices metalnessIndices = { 10 }; ComponentIndices roughnessIndices = { 11 }; + ComponentIndices morphTargetListIndices = { 12, 13, 14, 15, 16 }; + ComponentIndices morphTargetVecIndices = { 17, 18, 19, 20, 21, 22 }; QVector<ComponentIndices> channelComponentIndices = { rotationIndices, locationIndices, baseColorIndices, - metalnessIndices, roughnessIndices }; + metalnessIndices, roughnessIndices, morphTargetListIndices, + morphTargetVecIndices }; QVector<QBitArray> sourceClipMask = { QBitArray(4, true), QBitArray(3, true), QBitArray(3, true), QBitArray(1, true), - QBitArray(1, true) }; + QBitArray(1, true), + QBitArray(5, true), + QBitArray(6, true) }; MappingData expectedMapping; expectedMapping.targetId = channelMapping->targetId(); @@ -356,59 +378,83 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); auto metalnessMapping = createChannelMapping(handler, QLatin1String("Metalness"), Qt3DCore::QNodeId::createId(), QLatin1String("metalness"), "metalness", - static_cast<int>(QVariant::Double)); + static_cast<int>(QVariant::Double), + 1); auto baseColorMapping = createChannelMapping(handler, QLatin1String("BaseColor"), Qt3DCore::QNodeId::createId(), QLatin1String("baseColor"), "baseColor", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); auto roughnessMapping = createChannelMapping(handler, QLatin1String("Roughness"), Qt3DCore::QNodeId::createId(), QLatin1String("roughness"), "roughness", - static_cast<int>(QVariant::Double)); + static_cast<int>(QVariant::Double), + 1); auto rotationMapping = createChannelMapping(handler, QLatin1String("Rotation"), Qt3DCore::QNodeId::createId(), QLatin1String("rotation"), "rotation", - static_cast<int>(QVariant::Quaternion)); + static_cast<int>(QVariant::Quaternion), + 4); + + auto morphTargetMapping = createChannelMapping(handler, + QLatin1String("MorphTargetWeights"), + Qt3DCore::QNodeId::createId(), + QLatin1String("weights"), + "weights", + static_cast<int>(QVariant::List), + 5); + QVector<ChannelMapping *> channelMappings = { locationMapping, metalnessMapping, baseColorMapping, roughnessMapping, - rotationMapping }; + rotationMapping, morphTargetMapping }; // Create a few channels in the format description ChannelNameAndType rotation = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), + 4, rotationMapping->peerId() }; ChannelNameAndType location = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, locationMapping->peerId() }; ChannelNameAndType baseColor = { QLatin1String("BaseColor"), static_cast<int>(QVariant::Vector3D), + 3, baseColorMapping->peerId() }; ChannelNameAndType metalness = { QLatin1String("Metalness"), static_cast<int>(QVariant::Double), + 1, metalnessMapping->peerId() }; ChannelNameAndType roughness = { QLatin1String("Roughness"), static_cast<int>(QVariant::Double), + 1, roughnessMapping->peerId() }; + ChannelNameAndType morphTarget = { QLatin1String("MorphTargetWeights"), + static_cast<int>(QVariant::List), + 5, + morphTargetMapping->peerId() }; QVector<ChannelNameAndType> channelNamesAndTypes - = { rotation, location, baseColor, metalness, roughness }; + = { rotation, location, baseColor, metalness, roughness, + morphTarget }; // And the matching indices ComponentIndices rotationIndices = { 0, 1, 2, 3 }; @@ -416,15 +462,17 @@ private Q_SLOTS: ComponentIndices baseColorIndices = { 7, 8, 9 }; ComponentIndices metalnessIndices = { 10 }; ComponentIndices roughnessIndices = { 11 }; + ComponentIndices morphTargetIndices = { 12, 13, 14, 15, 16 }; QVector<ComponentIndices> channelComponentIndices = { rotationIndices, locationIndices, baseColorIndices, - metalnessIndices, roughnessIndices }; + metalnessIndices, roughnessIndices, morphTargetIndices }; QVector<QBitArray> sourceClipMask = { QBitArray(4, true), QBitArray(3, true), QBitArray(3, true), QBitArray(1, true), - QBitArray(1, true) }; + QBitArray(1, true), + QBitArray(5, true) }; MappingData expectedLocationMapping; expectedLocationMapping.targetId = locationMapping->targetId(); @@ -456,12 +504,19 @@ private Q_SLOTS: expectedRotationMapping.type = rotationMapping->type(); expectedRotationMapping.channelIndices = rotationIndices; + MappingData expectedMorphTargetMapping; + expectedMorphTargetMapping.targetId = morphTargetMapping->targetId(); + expectedMorphTargetMapping.propertyName = morphTargetMapping->propertyName(); + expectedMorphTargetMapping.type = morphTargetMapping->type(); + expectedMorphTargetMapping.channelIndices = morphTargetIndices; + QVector<MappingData> expectedResults = { expectedLocationMapping, expectedMetalnessMapping, expectedBaseColorMapping, expectedRoughnessMapping, - expectedRotationMapping }; + expectedRotationMapping, + expectedMorphTargetMapping }; QTest::newRow("multiple mappings") << handler @@ -486,6 +541,7 @@ private Q_SLOTS: for (int i = 0; i < jointCount; ++i) { ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }; locationDescription.jointIndex = i; locationDescription.jointTransformComponent = Translation; @@ -493,6 +549,7 @@ private Q_SLOTS: ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), + 4, channelMapping->peerId() }; rotationDescription.jointIndex = i; rotationDescription.jointTransformComponent = Rotation; @@ -500,6 +557,7 @@ private Q_SLOTS: ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }; scaleDescription.jointIndex = i; scaleDescription.jointTransformComponent = Scale; @@ -1004,6 +1062,35 @@ private Q_SLOTS: expectedChanges.clear(); } + // Single property, QVariantList + { + animatorId = Qt3DCore::QNodeId::createId(); + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "weights"; + mapping.type = static_cast<int>(QVariant::List); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 0.5f << 0.4f << 0.3f << 0.0f << 1.0f << 0.6f << 0.9f; + finalFrame = false; + normalizedTime = 1.1f; // Invalid + + auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId); + change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + change->setPropertyName(mapping.propertyName); + QVariantList expectedValue = QVariantList() << 0.5f << 0.4f << 0.3f << 0.0f << 1.0f << 0.6f << 0.9f; + change->setValue(QVariant::fromValue(expectedValue)); + expectedChanges.push_back(change); + + QTest::newRow("QVariantList weights") + << animatorId << mappingData << channelResults << normalizedTime + << finalFrame << expectedChanges; + + mappingData.clear(); + channelResults.clear(); + expectedChanges.clear(); + } + } void checkPreparePropertyChanges() @@ -1396,12 +1483,14 @@ private Q_SLOTS: { QTest::addColumn<Channel>("channel"); QTest::addColumn<int>("dataType"); + QTest::addColumn<int>("expectedChannelComponentCount"); QTest::addColumn<int>("offset"); QTest::addColumn<QVector<char>>("suffixes"); QTest::addColumn<QVector<int>>("expectedResults"); Channel channel; int dataType; + int expectedChannelComponentCount; int offset; QVector<char> suffixes; QVector<int> expectedResults; @@ -1414,20 +1503,22 @@ private Q_SLOTS: // leave 'name' empty dataType = static_cast<int>(QVariant::Vector3D); + expectedChannelComponentCount = 3; offset = 0; // suffixes expected to be ignored expectedResults = (QVector<int>() << 0 << 1 << 2); QTest::newRow("vec3 location, pre-sorted, no component names, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 4; expectedResults = (QVector<int>() << 4 << 5 << 6); QTest::newRow("vec3 location, pre-sorted, no component names, offset = 4") - << channel << dataType << offset << suffixes << expectedResults; - + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); } @@ -1441,19 +1532,22 @@ private Q_SLOTS: channel.channelComponents[2].name = QLatin1String("Location Z"); dataType = static_cast<int>(QVariant::Vector3D); + expectedChannelComponentCount = 3; offset = 0; suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector<int>() << 0 << 1 << 2); QTest::newRow("vec3 location, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 4; expectedResults = (QVector<int>() << 4 << 5 << 6); QTest::newRow("vec3 location, offset = 4") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); @@ -1468,19 +1562,22 @@ private Q_SLOTS: channel.channelComponents[1].name = QLatin1String("pos Y"); dataType = static_cast<int>(QVariant::Vector2D); + expectedChannelComponentCount = 2; offset = 0; suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector<int>() << 0 << 1); QTest::newRow("vec2 pos, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 2; expectedResults = (QVector<int>() << 2 << 3); QTest::newRow("vec2 pos, offset = 2") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); @@ -1497,19 +1594,22 @@ private Q_SLOTS: channel.channelComponents[3].name = QLatin1String("foo W"); dataType = static_cast<int>(QVariant::Vector4D); + expectedChannelComponentCount = 4; offset = 0; suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector<int>() << 0 << 1 << 2 << 3); QTest::newRow("vec4 foo, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector<int>() << 10 << 11 << 12 << 13); QTest::newRow("vec4 foo, offset = 10") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); @@ -1523,19 +1623,22 @@ private Q_SLOTS: channel.channelComponents[0].name = QLatin1String("Mass X"); dataType = static_cast<int>(QVariant::Double); + expectedChannelComponentCount = 1; offset = 0; suffixes = (QVector<char>() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector<int>() << 0); QTest::newRow("double Mass, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 5; expectedResults = (QVector<int>() << 5); QTest::newRow("double Mass, offset = 5") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); @@ -1552,19 +1655,22 @@ private Q_SLOTS: channel.channelComponents[3].name = QLatin1String("Rotation Z"); dataType = static_cast<int>(QVariant::Quaternion); + expectedChannelComponentCount = 4; offset = 0; suffixes = (QVector<char>() << 'W' << 'X' << 'Y' << 'Z'); expectedResults = (QVector<int>() << 0 << 1 << 2 << 3); QTest::newRow("quaternion Rotation, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector<int>() << 10 << 11 << 12 << 13); QTest::newRow("quaternion Rotation, offset = 10") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); @@ -1581,19 +1687,22 @@ private Q_SLOTS: channel.channelComponents[3].name = QLatin1String("Rotation Y"); dataType = static_cast<int>(QVariant::Quaternion); + expectedChannelComponentCount = 4; offset = 0; suffixes = (QVector<char>() << 'W' << 'X' << 'Y' << 'Z'); expectedResults = (QVector<int>() << 1 << 0 << 3 << 2); QTest::newRow("quaternion Rotation, offset = 0, randomized") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector<int>() << 11 << 10 << 13 << 12); QTest::newRow("quaternion Rotation, offset = 10, randomized") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); @@ -1609,37 +1718,95 @@ private Q_SLOTS: channel.channelComponents[2].name = QLatin1String("Color B"); dataType = static_cast<int>(QVariant::Color); + expectedChannelComponentCount = 3; offset = 0; suffixes = (QVector<char>() << 'R' << 'G' << 'B'); expectedResults = (QVector<int>() << 0 << 1 << 2); QTest::newRow("QColor Color, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector<int>() << 10 << 11 << 12); QTest::newRow("QColor Color, offset = 10") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; suffixes.clear(); expectedResults.clear(); } + + // weights as list with and without offset + { + channel = Channel(); + channel.name = QLatin1String("MorphWeights"); + channel.channelComponents.resize(6); + // leave channel component names empty + + dataType = static_cast<int>(QVariant::List); + expectedChannelComponentCount = 6; + offset = 0; + // suffixes expected to be ignored + expectedResults = (QVector<int>() << 0 << 1 << 2 << 3 << 4 << 5); + + QTest::newRow("MorphWeights List count = 6, offset = 0") + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; + expectedResults.clear(); + + offset = 10; + expectedResults = (QVector<int>() << 10 << 11 << 12 << 13 << 14 << 15); + QTest::newRow("MorphWeights List count = 6, offset = 10") + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; + suffixes.clear(); + expectedResults.clear(); + } + + // weights as vec of float with and without offset + { + channel = Channel(); + channel.name = QLatin1String("MorphWeights"); + channel.channelComponents.resize(6); + // leave channel component names empty + + dataType = qMetaTypeId<QVector<float>>(); + expectedChannelComponentCount = 6; + offset = 0; + // suffixes expected to be ignored + expectedResults = (QVector<int>() << 0 << 1 << 2 << 3 << 4 << 5); + + QTest::newRow("MorphWeights Vec count = 6, offset = 0") + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; + expectedResults.clear(); + + offset = 10; + expectedResults = (QVector<int>() << 10 << 11 << 12 << 13 << 14 << 15); + QTest::newRow("MorphWeights Vec count = 6, offset = 10") + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; + suffixes.clear(); + expectedResults.clear(); + } } void checkChannelComponentsToIndicesHelper() { // GIVEN QFETCH(Channel, channel); - QFETCH(int, dataType); QFETCH(int, offset); + QFETCH(int, expectedChannelComponentCount); QFETCH(QVector<char>, suffixes); QFETCH(QVector<int>, expectedResults); // WHEN QVector<int> actualResults - = channelComponentsToIndicesHelper(channel, dataType, offset, suffixes); + = channelComponentsToIndicesHelper(channel, expectedChannelComponentCount, + offset, suffixes); // THEN QCOMPARE(actualResults.size(), expectedResults.size()); @@ -1652,11 +1819,13 @@ private Q_SLOTS: { QTest::addColumn<Channel>("channel"); QTest::addColumn<int>("dataType"); + QTest::addColumn<int>("componentCount"); QTest::addColumn<int>("offset"); QTest::addColumn<QVector<int>>("expectedResults"); Channel channel; int dataType; + int componentCount; int offset; QVector<int> expectedResults; @@ -1671,18 +1840,19 @@ private Q_SLOTS: channel.channelComponents[3].name = QLatin1String("Rotation Z"); dataType = static_cast<int>(QVariant::Quaternion); + componentCount = 4; offset = 0; expectedResults = (QVector<int>() << 0 << 1 << 2 << 3); QTest::newRow("quaternion Rotation, offset = 0") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector<int>() << 10 << 11 << 12 << 13); QTest::newRow("quaternion Rotation, offset = 10") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); } @@ -1697,18 +1867,19 @@ private Q_SLOTS: channel.channelComponents[2].name = QLatin1String("Location Z"); dataType = static_cast<int>(QVariant::Vector3D); + componentCount = 3; offset = 0; expectedResults = (QVector<int>() << 0 << 1 << 2); QTest::newRow("vec3 location, offset = 0") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); offset = 4; expectedResults = (QVector<int>() << 4 << 5 << 6); QTest::newRow("vec3 location, offset = 4") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); } @@ -1723,18 +1894,19 @@ private Q_SLOTS: channel.channelComponents[2].name = QLatin1String("Color B"); dataType = static_cast<int>(QVariant::Color); + componentCount = 3; offset = 0; expectedResults = (QVector<int>() << 0 << 1 << 2); QTest::newRow("QColor Color, offset = 0") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector<int>() << 10 << 11 << 12); QTest::newRow("QColor Color, offset = 10") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); } @@ -1744,12 +1916,13 @@ private Q_SLOTS: { QFETCH(Channel, channel); QFETCH(int, dataType); + QFETCH(int, componentCount); QFETCH(int, offset); QFETCH(QVector<int>, expectedResults); // WHEN QVector<int> actualResults - = channelComponentsToIndices(channel, dataType, offset); + = channelComponentsToIndices(channel, dataType, componentCount, offset); // THEN QCOMPARE(actualResults.size(), expectedResults.size()); @@ -2387,7 +2560,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); QVector<ChannelMapping *> channelMappings; channelMappings.push_back(channelMapping); @@ -2397,6 +2571,7 @@ private Q_SLOTS: QVector<ChannelNameAndType> expectedResults; expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }); QTest::addRow("Location, vec3") << handler << channelMapper << expectedResults; @@ -2409,13 +2584,15 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); auto channelMapping2 = createChannelMapping(handler, QLatin1String("Rotation"), Qt3DCore::QNodeId::createId(), QLatin1String("rotatrion"), "rotation", - static_cast<int>(QVariant::Quaternion)); + static_cast<int>(QVariant::Quaternion), + 4); QVector<ChannelMapping *> channelMappings; channelMappings.push_back(channelMapping1); channelMappings.push_back(channelMapping2); @@ -2429,9 +2606,11 @@ private Q_SLOTS: QVector<ChannelNameAndType> expectedResults; expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping1->peerId() }); expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), + 4, channelMapping2->peerId() }); QTest::addRow("Multiple unique channels") << handler << channelMapper << expectedResults; @@ -2444,25 +2623,29 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); auto channelMapping2 = createChannelMapping(handler, QLatin1String("Rotation"), Qt3DCore::QNodeId::createId(), QLatin1String("rotation"), "rotation", - static_cast<int>(QVariant::Quaternion)); + static_cast<int>(QVariant::Quaternion), + 4); auto channelMapping3 = createChannelMapping(handler, QLatin1String("Location"), Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); auto channelMapping4 = createChannelMapping(handler, QLatin1String("Location"), Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); QVector<ChannelMapping *> channelMappings; channelMappings.push_back(channelMapping1); @@ -2481,15 +2664,19 @@ private Q_SLOTS: QVector<ChannelNameAndType> expectedResults; expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping1->peerId() }); expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), + 4, channelMapping2->peerId() }); expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping3->peerId() }); expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping4->peerId() }); QTest::addRow("Multiple channels with repeats") << handler << channelMapper << expectedResults; @@ -2510,6 +2697,7 @@ private Q_SLOTS: for (int i = 0; i < jointCount; ++i) { ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }; locationDescription.jointIndex = i; locationDescription.jointTransformComponent = Translation; @@ -2517,6 +2705,7 @@ private Q_SLOTS: ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), + 4, channelMapping->peerId() }; rotationDescription.jointIndex = i; rotationDescription.jointTransformComponent = Rotation; @@ -2524,6 +2713,7 @@ private Q_SLOTS: ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), + 3, channelMapping->peerId() }; scaleDescription.jointIndex = i; scaleDescription.jointTransformComponent = Scale; @@ -2560,7 +2750,7 @@ private Q_SLOTS: { QVector<ChannelNameAndType> allChannels; - allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); QVector<ComponentIndices> expectedResults; expectedResults.push_back({ 0, 1, 2 }); @@ -2570,8 +2760,8 @@ private Q_SLOTS: { QVector<ChannelNameAndType> allChannels; - allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); - allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }); QVector<ComponentIndices> expectedResults; expectedResults.push_back({ 0, 1, 2 }); @@ -2582,11 +2772,12 @@ private Q_SLOTS: { QVector<ChannelNameAndType> allChannels; - allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); - allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); - allChannels.push_back({ QLatin1String("BaseColor"), static_cast<int>(QVariant::Vector3D) }); - allChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); - allChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }); + allChannels.push_back({ QLatin1String("BaseColor"), static_cast<int>(QVariant::Vector3D), 3 }); + allChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double), 1 }); + allChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double), 1 }); + allChannels.push_back({ QLatin1String("MorphWeights"), static_cast<int>(QVariant::List), 6 }); QVector<ComponentIndices> expectedResults; expectedResults.push_back({ 0, 1, 2 }); @@ -2594,23 +2785,24 @@ private Q_SLOTS: expectedResults.push_back({ 7, 8, 9 }); expectedResults.push_back({ 10 }); expectedResults.push_back({ 11 }); + expectedResults.push_back({ 12, 13, 14, 15, 16, 17 }); - QTest::newRow("vec3 location, quaterion rotation, pbr metal-rough") << allChannels << expectedResults; + QTest::newRow("vec3 location, quaterion rotation, pbr metal-rough morphweights") << allChannels << expectedResults; } { QVector<ChannelNameAndType> allChannels; const int jointCount = 4; for (int i = 0; i < jointCount; ++i) { - ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }; locationDescription.jointIndex = i; allChannels.push_back(locationDescription); - ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }; + ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }; rotationDescription.jointIndex = i; allChannels.push_back(rotationDescription); - ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), 3 }; scaleDescription.jointIndex = i; allChannels.push_back(scaleDescription); } @@ -2665,11 +2857,11 @@ private Q_SLOTS: { QVector<ChannelNameAndType> targetChannels; - targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Base Color"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Base Color"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double), 1 }); QVector<ComponentIndices> targetIndices; targetIndices.push_back({ 0, 1, 2, 3 }); @@ -2703,11 +2895,11 @@ private Q_SLOTS: { QVector<ChannelNameAndType> targetChannels; - targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Base Color"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Base Color"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double), 1 }); QVector<ComponentIndices> targetIndices; targetIndices.push_back({ 0, 1, 2 }); @@ -2741,11 +2933,11 @@ private Q_SLOTS: { QVector<ChannelNameAndType> targetChannels; - targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Albedo"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Albedo"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double), 1 }); QVector<ComponentIndices> targetIndices; targetIndices.push_back({ 0, 1, 2, 3 }); @@ -2779,11 +2971,11 @@ private Q_SLOTS: { QVector<ChannelNameAndType> targetChannels; - targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Albedo"), static_cast<int>(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Albedo"), static_cast<int>(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast<int>(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast<int>(QVariant::Double), 1 }); QVector<ComponentIndices> targetIndices; targetIndices.push_back({ 0, 1, 2 }); @@ -2819,15 +3011,15 @@ private Q_SLOTS: QVector<ChannelNameAndType> targetChannels; const int jointCount = 4; for (int i = 0; i < jointCount; ++i) { - ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), 3 }; locationDescription.jointIndex = i; targetChannels.push_back(locationDescription); - ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) }; + ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), 4 }; rotationDescription.jointIndex = i; targetChannels.push_back(rotationDescription); - ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D) }; + ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), 3 }; scaleDescription.jointIndex = i; targetChannels.push_back(scaleDescription); } @@ -2934,7 +3126,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); ChannelNameAndType channelDescription; channelDescription.mappingId = channelMapping->peerId(); channelDescription.type = static_cast<int>(QVariant::Vector3D); @@ -2950,7 +3143,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("rotation"), "rotation", - static_cast<int>(QVariant::Quaternion)); + static_cast<int>(QVariant::Quaternion), + 4); ChannelNameAndType channelDescription; channelDescription.mappingId = channelMapping->peerId(); channelDescription.type = static_cast<int>(QVariant::Quaternion); @@ -2966,7 +3160,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("scale"), "scale", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); ChannelNameAndType channelDescription; channelDescription.mappingId = channelMapping->peerId(); channelDescription.type = static_cast<int>(QVariant::Vector3D); diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp index a947d4a2d..5c04c7f89 100644 --- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp +++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp @@ -41,6 +41,18 @@ #include <Qt3DCore/private/qbackendnode_p.h> #include "testpostmanarbiter.h" +class tst_TargetEntity : public Qt3DCore::QEntity +{ + Q_OBJECT + Q_PROPERTY(QVector2D foo MEMBER m_foo NOTIFY fooChanged) + +signals: + void fooChanged(); + +private: + QVector2D m_foo; +}; + class tst_ChannelMapping : public Qt3DCore::QBackendNodeTester { Q_OBJECT @@ -53,7 +65,7 @@ private Q_SLOTS: Qt3DAnimation::Animation::ChannelMapping backendMapping; backendMapping.setHandler(&handler); Qt3DAnimation::QChannelMapping mapping; - auto target = new Qt3DCore::QEntity; + auto target = new tst_TargetEntity; mapping.setChannelName(QLatin1String("Location")); mapping.setTarget(target); @@ -68,6 +80,9 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), mapping.channelName()); QCOMPARE(backendMapping.targetId(), mapping.target()->id()); QCOMPARE(backendMapping.property(), mapping.property()); + QVERIFY(qstrcmp(backendMapping.propertyName(), "foo") == 0); + QCOMPARE(backendMapping.componentCount(), 2); + QCOMPARE(backendMapping.type(), static_cast<int>(QVariant::Vector2D)); QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); // GIVEN @@ -100,12 +115,15 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), QString()); QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.property(), QString()); + QCOMPARE(backendMapping.propertyName(), nullptr); + QCOMPARE(backendMapping.componentCount(), 0); + QCOMPARE(backendMapping.type(), static_cast<int>(QVariant::Invalid)); QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); // GIVEN Qt3DAnimation::QChannelMapping mapping; - auto target = new Qt3DCore::QEntity; + auto target = new tst_TargetEntity; mapping.setChannelName(QLatin1String("Location")); mapping.setTarget(target); mapping.setProperty(QLatin1String("foo")); @@ -120,6 +138,9 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), QString()); QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.property(), QString()); + QCOMPARE(backendMapping.propertyName(), nullptr); + QCOMPARE(backendMapping.componentCount(), 0); + QCOMPARE(backendMapping.type(), static_cast<int>(QVariant::Invalid)); QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); } @@ -172,6 +193,34 @@ private Q_SLOTS: QCOMPARE(backendMapping.property(), property); // WHEN + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("type"); + updateChange->setValue(QVariant(static_cast<int>(QVariant::Vector3D))); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.type(), static_cast<int>(QVariant::Vector3D)); + + // WHEN + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("componentCount"); + updateChange->setValue(4); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.componentCount(), 4); + + // WHEN + const char *testName = "883"; + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("propertyName"); + updateChange->setValue(QVariant::fromValue(reinterpret_cast<void *>(const_cast<char *>(testName)))); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.propertyName(), testName); + + // WHEN const auto skeletonId = Qt3DCore::QNodeId::createId(); updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); updateChange->setPropertyName("skeleton"); diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp index 50c0eb524..cc09c7941 100644 --- a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp +++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp @@ -61,7 +61,8 @@ public: const Qt3DCore::QNodeId targetId, const QString &property, const char *propertyName, - int type) + int type, + int componentCount) { auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); @@ -72,6 +73,7 @@ public: channelMapping->setPropertyName(propertyName); channelMapping->setChannelName(channelName); channelMapping->setType(type); + channelMapping->setComponentCount(componentCount); channelMapping->setMappingType(ChannelMapping::ChannelMappingType); return channelMapping; } @@ -143,7 +145,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); QVector<ChannelMapping *> channelMappings; channelMappings.push_back(channelMapping); @@ -188,7 +191,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast<int>(QVariant::Vector3D)); + static_cast<int>(QVariant::Vector3D), + 3); QVector<ChannelMapping *> channelMappings; channelMappings.push_back(channelMapping); @@ -198,9 +202,9 @@ private Q_SLOTS: animator->setEnabled(false); // Has to be marked as enabled for the job to process it QTest::newRow("disabled animator") - << handler - << dirtyClipAnimators - << expectedResults; + << handler + << dirtyClipAnimators + << expectedResults; } } diff --git a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp index cab5fda6f..091876d09 100644 --- a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp +++ b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp @@ -28,6 +28,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/private/qabstractchannelmapping_p.h> #include <Qt3DAnimation/private/qchannelmapping_p.h> #include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -36,8 +37,49 @@ #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> #include <QObject> #include <QSignalSpy> +#include <QQuaternion> #include <testpostmanarbiter.h> +class tst_QTargetEntity : public Qt3DCore::QEntity +{ + Q_OBJECT + Q_PROPERTY(QQuaternion rotation MEMBER m_rotation NOTIFY rotationChanged) + Q_PROPERTY(QVector3D translation MEMBER m_translation NOTIFY translationChanged) + Q_PROPERTY(QVector3D scale MEMBER m_scale NOTIFY scaleChanged) + Q_PROPERTY(float floatProperty MEMBER m_floatProperty NOTIFY floatPropertyChanged) + Q_PROPERTY(QVector2D vec2Property MEMBER m_vec2Property NOTIFY vec2PropertyChanged) + Q_PROPERTY(QVector3D vec3Property MEMBER m_vec3Property NOTIFY vec3PropertyChanged) + Q_PROPERTY(QVector4D vec4Property MEMBER m_vec4Property NOTIFY vec4PropertyChanged) + Q_PROPERTY(QQuaternion quaternionProperty MEMBER m_quaternionProperty NOTIFY quaternionPropertyChanged) + Q_PROPERTY(QVariantList listProperty MEMBER m_listProperty NOTIFY listPropertyChanged) + Q_PROPERTY(QVector<float> vecProperty MEMBER m_vecProperty NOTIFY vecPropertyChanged) + +signals: + void rotationChanged(); + void translationChanged(); + void scaleChanged(); + void floatPropertyChanged(); + void vec2PropertyChanged(); + void vec3PropertyChanged(); + void vec4PropertyChanged(); + void quaternionPropertyChanged(); + void listPropertyChanged(); + void vecPropertyChanged(); + +private: + QQuaternion m_rotation; + QVector3D m_translation; + QVector3D m_scale; + float m_floatProperty; + QVector2D m_vec2Property; + QVector3D m_vec3Property; + QVector4D m_vec4Property; + QQuaternion m_quaternionProperty; + QVariantList m_listProperty; + QVector<float> m_vecProperty; +}; + + class tst_QChannelMapping : public QObject { Q_OBJECT @@ -52,6 +94,13 @@ private Q_SLOTS: QCOMPARE(mapping.channelName(), QString()); QCOMPARE(mapping.target(), static_cast<Qt3DCore::QNode *>(nullptr)); QCOMPARE(mapping.property(), QString()); + + const Qt3DAnimation::QChannelMappingPrivate *d = + static_cast<const Qt3DAnimation::QChannelMappingPrivate *>( + Qt3DAnimation::QChannelMappingPrivate::get(&mapping)); + + QCOMPARE(d->m_type, static_cast<int>(QVariant::Invalid)); + QCOMPARE(d->m_componentCount, 0); } void checkPropertyChanges() @@ -125,7 +174,7 @@ private Q_SLOTS: { // GIVEN Qt3DAnimation::QChannelMapping mapping; - auto target = new Qt3DCore::QEntity; + auto target = new tst_QTargetEntity; mapping.setChannelName(QStringLiteral("Location")); mapping.setTarget(target); @@ -154,6 +203,8 @@ private Q_SLOTS: QCOMPARE(mapping.channelName(), data.channelName); QCOMPARE(mapping.target()->id(), data.targetId); QCOMPARE(mapping.property(), data.property); + QCOMPARE(data.type, static_cast<int>(QVariant::Vector3D)); + QCOMPARE(data.componentCount, 3); } // WHEN @@ -179,6 +230,8 @@ private Q_SLOTS: QCOMPARE(mapping.channelName(), data.channelName); QCOMPARE(mapping.target()->id(), data.targetId); QCOMPARE(mapping.property(), data.property); + QCOMPARE(data.type, static_cast<int>(QVariant::Vector3D)); + QCOMPARE(data.componentCount, 3); } } @@ -187,6 +240,7 @@ private Q_SLOTS: // GIVEN TestArbiter arbiter; Qt3DAnimation::QChannelMapping mapping; + QScopedPointer<Qt3DCore::QEntity> target(new tst_QTargetEntity()); arbiter.setArbiterOnNode(&mapping); { @@ -213,8 +267,7 @@ private Q_SLOTS: { // WHEN - auto target = new Qt3DCore::QEntity(); - mapping.setTarget(target); + mapping.setTarget(target.data()); QCoreApplication::processEvents(); // THEN @@ -227,7 +280,7 @@ private Q_SLOTS: arbiter.events.clear(); // WHEN - mapping.setTarget(target); + mapping.setTarget(target.data()); QCoreApplication::processEvents(); // THEN @@ -236,16 +289,32 @@ private Q_SLOTS: { // WHEN + target->setProperty("scale", QVector3D(1.0f, 0.0f, 0.0f)); mapping.setProperty(QStringLiteral("scale")); QCoreApplication::processEvents(); // THEN - QCOMPARE(arbiter.events.size(), 1); - auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(arbiter.events.size(), 4); + auto change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); QCOMPARE(change->propertyName(), "property"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); QCOMPARE(change->value().toString(), mapping.property()); + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), static_cast<int>(QVariant::Vector3D)); + + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "componentCount"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), 3); + + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "propertyName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QVERIFY(qstrcmp(reinterpret_cast<const char *>(change->value().value<void *>()), "scale") == 0); + arbiter.events.clear(); // WHEN @@ -255,8 +324,88 @@ private Q_SLOTS: // THEN QCOMPARE(arbiter.events.size(), 0); } + } + void checkPropertyUpdateNameTypeAndComponentCount_data() + { + QTest::addColumn<QByteArray>("propertyName"); + QTest::addColumn<QVariant>("value"); + QTest::addColumn<int>("expectedType"); + QTest::addColumn<int>("expectedComponentCount"); + + QTest::newRow("float") << QByteArrayLiteral("floatProperty") << QVariant(1.0f) << static_cast<int>(QMetaType::Float) << 1; + QTest::newRow("vec2") << QByteArrayLiteral("vec2Property") << QVariant(QVector2D(1.0f, 1.0f)) << static_cast<int>(QVariant::Vector2D) << 2; + QTest::newRow("vec3") << QByteArrayLiteral("vec3Property") << QVariant(QVector3D(1.0f, 1.0f, 1.0f)) << static_cast<int>(QVariant::Vector3D) << 3; + QTest::newRow("vec4") << QByteArrayLiteral("vec4Property") << QVariant(QVector4D(1.0f, 1.0f, 1.0f, 1.0f)) << static_cast<int>(QVariant::Vector4D) << 4; + QTest::newRow("quaternion") << QByteArrayLiteral("quaternionProperty") << QVariant(QQuaternion(1.0f, 1.0f, 1.0f, 1.0f)) << static_cast<int>(QVariant::Quaternion) << 4; + + QVariantList list = QVariantList() << QVariant(1.0f) << QVariant(1.0) << QVariant(1.0f) << QVariant(1.0f) << QVariant(1.0f); + QTest::newRow("variantlist") << QByteArrayLiteral("listProperty") << QVariant::fromValue(list) << static_cast<int>(QVariant::List) << 5; + + QVector<float> vec(8); + QTest::newRow("vector") << QByteArrayLiteral("vecProperty") << QVariant::fromValue(vec) << qMetaTypeId<decltype(vec)>() << 8; } + + void checkPropertyUpdateNameTypeAndComponentCount() + { + // GIVEN + QFETCH(QByteArray, propertyName); + QFETCH(QVariant, value); + QFETCH(int, expectedType); + QFETCH(int, expectedComponentCount); + + TestArbiter arbiter; + Qt3DAnimation::QChannelMapping mapping; + QScopedPointer<Qt3DCore::QEntity> target(new tst_QTargetEntity()); + mapping.setTarget(target.data()); + arbiter.setArbiterOnNode(&mapping); + + { + // WHEN + target->setProperty(propertyName.constData(), value); + mapping.setProperty(QString::fromLatin1(propertyName)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 5); + + // Automatic notification change when property is updated + auto change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), propertyName.constData()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value(), value); + + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "property"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toString(), mapping.property()); + + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), expectedType); + + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "componentCount"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), expectedComponentCount); + + change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "propertyName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QVERIFY(qstrcmp(reinterpret_cast<const char *>(change->value().value<void *>()), propertyName.constData()) == 0); + + arbiter.events.clear(); + + // WHEN + mapping.setProperty(QString::fromLatin1(propertyName)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + }; QTEST_MAIN(tst_QChannelMapping) diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index 3f7fb4a75..dad66c5d5 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -73,6 +73,7 @@ private slots: void checkParentChangeToNull(); void checkParentChangeToOtherParent(); void checkParentChangeFromExistingBackendParentToNewlyCreatedParent(); + void checkBackendNodesCreatedFromTopDown(); //QTBUG-74106 void removingSingleChildNodeFromNode(); void removingMultipleChildNodesFromNode(); @@ -81,6 +82,7 @@ private slots: void removingChildEntitiesFromNode(); void checkConstructionSetParentMix(); // QTBUG-60612 + void checkParentingQEntityToQNode(); // QTBUG-73905 void checkConstructionWithParent(); void checkConstructionWithNonRootParent(); // QTBUG-73986 void checkConstructionAsListElement(); @@ -901,6 +903,85 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent() } } +//Test creation changes happen for an entire subtree at once, starting at the top +// so that parents are always created before their children. Even if the front-end +// nodes are constructed in a different order. +void tst_Nodes::checkBackendNodesCreatedFromTopDown() +{ + // GIVEN + Qt3DCore::QScene scene; + ObserverSpy spy; + QScopedPointer<MyQNode> root(new MyQNode()); + root->setArbiterAndScene(&spy, &scene); + QScopedPointer<Qt3DCore::QNode> parentWithBackend(new MyQNode(root.data())); + + // create parent backend node + QCoreApplication::processEvents(); + QVERIFY(Qt3DCore::QNodePrivate::get(parentWithBackend.get())->m_hasBackendNode); + + // WHEN -> creating 3 nodes and setting one as a property on the other + // child2 is set as property on child1, but is created AFTER child1 + spy.events.clear(); + MyQNode *dummyParent(new MyQNode(parentWithBackend.data())); + MyQNode *child1(new MyQNode(parentWithBackend.data())); + MyQNode *child2(new MyQNode(dummyParent)); + child2->setNodeProperty(child1); + + // THEN - we should have no events because the new nodes have no backend yet + QCOMPARE(spy.events.count(), 0); + + // WHEN - create the backend nodes + QCoreApplication::processEvents(); + + // THEN + QVERIFY(dummyParent->parent() == parentWithBackend.data()); + QVERIFY(child1->parent() == parentWithBackend.data()); + QVERIFY(child2->parent() == dummyParent); + + // THEN + QCOMPARE(spy.events.size(), 5); + // 2 node creation change for dummyParent subtree (dummyParent and child2) + // 1 node added to children change (dummyParent to parent) + // 1 node created change for child1 + // 1 node added to children change (child1 to parent) + + { + // 1st event: dummyParent creation + const auto event1 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!event1.isNull()); + QCOMPARE(event1->type(), Qt3DCore::NodeCreated); + QCOMPARE(event1->parentId(), parentWithBackend->id()); + QCOMPARE(event1->subjectId(), dummyParent->id()); + + // 2nd event: child2 creation (even though we constructed child1 first) + const auto event2 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!event2.isNull()); + QCOMPARE(event2->type(), Qt3DCore::NodeCreated); + QCOMPARE(event2->parentId(), dummyParent->id()); + QCOMPARE(event2->subjectId(), child2->id()); + + // 3rd event: dummyParent added to parent + const auto event3 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>(); + QCOMPARE(event3->type(), Qt3DCore::PropertyValueAdded); + QCOMPARE(event3->addedNodeId(), dummyParent->id()); + QCOMPARE(event3->subjectId(), parentWithBackend->id()); + + // 4th event: child1 creation + const auto event4 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!event4.isNull()); + QCOMPARE(event4->type(), Qt3DCore::NodeCreated); + QCOMPARE(event4->parentId(), parentWithBackend->id()); + QCOMPARE(event4->subjectId(), child1->id()); + + // 5th event: child 1 added to parent + const auto event5 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>(); + QCOMPARE(event5->type(), Qt3DCore::PropertyValueAdded); + QCOMPARE(event5->addedNodeId(), child1->id()); + QCOMPARE(event5->subjectId(), parentWithBackend->id()); + } +} + + void tst_Nodes::removingSingleChildNodeFromNode() { // GIVEN @@ -1079,6 +1160,72 @@ void tst_Nodes::checkConstructionSetParentMix() QCOMPARE(lastEvent->addedNodeId(), subTreeRoot->id()); } +void tst_Nodes::checkParentingQEntityToQNode() +{ + // GIVEN + ObserverSpy spy; + Qt3DCore::QScene scene; + QScopedPointer<MyQNode> root(new MyQNode()); + + // WHEN + root->setArbiterAndScene(&spy, &scene); + root->setSimulateBackendCreated(true); + + // THEN + QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr); + + // WHEN + auto subTreeRoot = new Qt3DCore::QEntity(root.data()); + auto childEntity = new Qt3DCore::QEntity(subTreeRoot); + auto childNode = new Qt3DCore::QNode(subTreeRoot); + + // THEN + QCoreApplication::processEvents(); + + // Ensure first event is subTreeRoot creation + const Qt3DCore::QNodeCreatedChangeBasePtr firstEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!firstEvent.isNull()); + QCOMPARE(firstEvent->subjectId(), subTreeRoot->id()); + QCOMPARE(firstEvent->parentId(), root->id()); + + // Ensure 2nd event is childEntity creation + const Qt3DCore::QNodeCreatedChangeBasePtr secondEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!secondEvent.isNull()); + QCOMPARE(secondEvent->subjectId(), childEntity->id()); + QCOMPARE(secondEvent->parentId(), subTreeRoot->id()); + + // Ensure 3rd event is childNode creation + const Qt3DCore::QNodeCreatedChangeBasePtr thirdEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>(); + QVERIFY(!thirdEvent.isNull()); + QCOMPARE(thirdEvent->subjectId(), childNode->id()); + QCOMPARE(thirdEvent->parentId(), subTreeRoot->id()); + + + // WHEN we reparent the childEntity to the childNode (QNode) + + spy.events.clear(); + childEntity->setParent(childNode); + // THEN we should get + // - one child removed change for childEntity->subTreeRoot, + // - one child added change for childEntity->childNode, + // - and one property updated event specifying the correct QEntity parent (subTreeRoot) + QCOMPARE(spy.events.size(), 3); + + const auto removedEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>(); + QVERIFY(!removedEvent.isNull()); + QCOMPARE(removedEvent->subjectId(), subTreeRoot->id()); + + const auto addedEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>(); + QVERIFY(!addedEvent.isNull()); + QCOMPARE(addedEvent->subjectId(), childNode->id()); + + const auto parentChangeEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>(); + QVERIFY(!parentChangeEvent.isNull()); + QCOMPARE(parentChangeEvent->subjectId(), childEntity->id()); + QCOMPARE(parentChangeEvent->propertyName(), "parentEntityUpdated"); + QCOMPARE(parentChangeEvent->value().value<Qt3DCore::QNodeId>(), subTreeRoot->id()); +} + void tst_Nodes::checkConstructionWithParent() { // GIVEN diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp index 992e643d2..b35c6d31a 100644 --- a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp +++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp @@ -55,6 +55,7 @@ #include <Qt3DRender/private/calcboundingvolumejob_p.h> #include <Qt3DRender/private/calcgeometrytrianglevolumes_p.h> #include <Qt3DRender/private/loadbufferjob_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/private/buffermanager_p.h> #include <Qt3DRender/private/geometryrenderermanager_p.h> #include <Qt3DRender/private/sphere_p.h> @@ -116,6 +117,10 @@ namespace { void runRequiredJobs(Qt3DRender::TestAspect *test) { + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(test->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; updateWorldTransform.setRoot(test->sceneRoot()); updateWorldTransform.run(); diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index 6ad958451..123a648d6 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -151,7 +151,7 @@ private slots: QVERIFY(!entity.componentsUuid<EnvironmentLight>().isEmpty()); QVERIFY(!entity.componentUuid<Armature>().isNull()); QVERIFY(entity.isBoundingVolumeDirty()); - QVERIFY(!entity.childrenHandles().isEmpty()); + QVERIFY(entity.childrenHandles().isEmpty()); QVERIFY(!entity.layerIds().isEmpty()); QVERIFY(renderer.dirtyBits() != 0); bool containsAll = entity.containsComponentsOfType<Transform, @@ -162,6 +162,7 @@ private slots: entity.cleanup(); // THEN + QVERIFY(entity.parentEntityId().isNull()); QVERIFY(entity.componentUuid<Transform>().isNull()); QVERIFY(entity.componentUuid<CameraLens>().isNull()); QVERIFY(entity.componentUuid<Material>().isNull()); @@ -180,6 +181,122 @@ private slots: QVERIFY(!containsAll); } + void checkRebuildingEntityHierarchy() + { + // GIVEN + TestRenderer renderer; + NodeManagers nodeManagers; + Qt3DCore::QEntity frontendEntityA, frontendEntityB, frontendEntityC; + + auto entityCreator = [&nodeManagers, &renderer](const Qt3DCore::QEntity &frontEndEntity) { + Entity *entity = nodeManagers.renderNodesManager()->getOrCreateResource(frontEndEntity.id()); + entity->setNodeManagers(&nodeManagers); + entity->setRenderer(&renderer); + return entity; + }; + + auto backendA = entityCreator(frontendEntityA); + auto backendB = entityCreator(frontendEntityB); + auto backendC = entityCreator(frontendEntityC); + + // THEN + QVERIFY(backendA->parentEntityId().isNull()); + QVERIFY(backendB->parentEntityId().isNull()); + QVERIFY(backendC->parentEntityId().isNull()); + + QVERIFY(backendA->parent() == nullptr); + QVERIFY(backendB->parent() == nullptr); + QVERIFY(backendC->parent() == nullptr); + + QVERIFY(backendA->childrenHandles().isEmpty()); + QVERIFY(backendB->childrenHandles().isEmpty()); + QVERIFY(backendC->childrenHandles().isEmpty()); + + // WHEN + renderer.clearDirtyBits(0); + QVERIFY(renderer.dirtyBits() == 0); + + auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) { + const auto parentChange = QPropertyUpdatedChangePtr::create(entity.id()); + parentChange->setPropertyName("parentEntityUpdated"); + auto parent = entity.parentEntity(); + parentChange->setValue(QVariant::fromValue(parent ? parent->id() : Qt3DCore::QNodeId())); + + Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id()); + backendEntity->sceneChangeEvent(parentChange); + }; + + // reparent B to A and C to B. + frontendEntityB.setParent(&frontendEntityA); + sendParentChange(frontendEntityB); + frontendEntityC.setParent(&frontendEntityB); + sendParentChange(frontendEntityC); + + // THEN + QVERIFY(renderer.dirtyBits() & AbstractRenderer::EntityHierarchyDirty); + + QVERIFY(backendA->parentEntityId().isNull()); + QVERIFY(backendB->parentEntityId() == frontendEntityA.id()); + QVERIFY(backendC->parentEntityId() == frontendEntityB.id()); + + QVERIFY(backendA->parent() == nullptr); + QVERIFY(backendB->parent() == nullptr); + QVERIFY(backendC->parent() == nullptr); + + QVERIFY(backendA->childrenHandles().isEmpty()); + QVERIFY(backendB->childrenHandles().isEmpty()); + QVERIFY(backendC->childrenHandles().isEmpty()); + + // WHEN + auto rebuildHierarchy = [](Entity *backend) { + backend->clearEntityHierarchy(); + backend->rebuildEntityHierarchy(); + }; + rebuildHierarchy(backendA); + rebuildHierarchy(backendB); + rebuildHierarchy(backendC); + + // THEN + QVERIFY(backendA->parent() == nullptr); + QVERIFY(backendB->parent() == backendA); + QVERIFY(backendC->parent() == backendB); + + QVERIFY(!backendA->childrenHandles().isEmpty()); + QVERIFY(!backendB->childrenHandles().isEmpty()); + QVERIFY(backendC->childrenHandles().isEmpty()); + + // WHEN - reparent B to null. + frontendEntityB.setParent(static_cast<Qt3DCore::QNode *>(nullptr)); + sendParentChange(frontendEntityB); + rebuildHierarchy(backendA); + rebuildHierarchy(backendB); + rebuildHierarchy(backendC); + + QVERIFY(backendA->parentEntityId().isNull()); + QVERIFY(backendB->parentEntityId().isNull()); + QVERIFY(backendC->parentEntityId() == frontendEntityB.id()); + + QVERIFY(backendA->parent() == nullptr); + QVERIFY(backendB->parent() == nullptr); + QVERIFY(backendC->parent() == backendB); + + QVERIFY(backendA->childrenHandles().isEmpty()); + QVERIFY(!backendB->childrenHandles().isEmpty()); + QVERIFY(backendC->childrenHandles().isEmpty()); + + // WHEN - cleanup + backendA->cleanup(); + backendB->cleanup(); + backendC->cleanup(); + + // THEN + QVERIFY(backendA->parentEntityId().isNull()); + QVERIFY(backendB->parentEntityId().isNull()); + QVERIFY(backendC->parentEntityId().isNull()); + + QVERIFY(renderer.dirtyBits() != 0); + } + void shouldHandleSingleComponentEvents_data() { QTest::addColumn<QComponent*>("component"); diff --git a/tests/auto/render/framegraphnode/tst_framegraphnode.cpp b/tests/auto/render/framegraphnode/tst_framegraphnode.cpp index 07ff4c0d9..22bd872dc 100644 --- a/tests/auto/render/framegraphnode/tst_framegraphnode.cpp +++ b/tests/auto/render/framegraphnode/tst_framegraphnode.cpp @@ -30,8 +30,7 @@ #include <QtTest/QTest> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> +#include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> #include "testrenderer.h" @@ -108,24 +107,9 @@ private Q_SLOTS: // WHEN n->setParentId(parentId); - // THEN - QCOMPARE(n->parentId(), parentId); - - // WHEN - const Qt3DCore::QNodeId childId = Qt3DCore::QNodeId::createId(); - QScopedPointer<Qt3DRender::Render::FrameGraphNode> c(new MyFrameGraphNode()); - setIdInternal(c.data(), childId); - manager->appendNode(childId, c.data()); - n->appendChildId(childId); - // THEN - QCOMPARE(n->childrenIds().count(), 1); - // WHEN - n->appendChildId(childId); // THEN - QCOMPARE(n->childrenIds().count(), 1); - - c.take(); + QCOMPARE(n->parentId(), parentId); } void checkParentChange() @@ -151,17 +135,8 @@ private Q_SLOTS: QVERIFY(child->parentId().isNull()); // WHEN - parent1->appendChildId(childId); - // THEN - QCOMPARE(child->parentId(), parentId); - QCOMPARE(child->parent(), parent1); - QCOMPARE(parent1->childrenIds().count(), 1); - QCOMPARE(parent1->childrenIds().first(), childId); - QCOMPARE(parent1->children().count(), parent1->childrenIds().count()); - QCOMPARE(parent1->children().first(), child); + child->setParentId(parentId); - // WHEN - parent1->appendChildId(childId); // THEN QCOMPARE(child->parentId(), parentId); QCOMPARE(child->parent(), parent1); @@ -171,7 +146,8 @@ private Q_SLOTS: QCOMPARE(parent1->children().first(), child); // WHEN - parent1->removeChildId(childId); + child->setParentId(Qt3DCore::QNodeId()); + // THEN QVERIFY(child->parentId().isNull()); QVERIFY(child->parent() == nullptr); @@ -251,6 +227,7 @@ private Q_SLOTS: TestRenderer renderer; backendFGNode->setRenderer(&renderer); + backendFGChild->setRenderer(&renderer); setIdInternal(backendFGNode, fgNode1Id); setIdInternal(backendFGChild, frontendFGChild->id()); @@ -269,20 +246,27 @@ private Q_SLOTS: { // WHEN - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), frontendFGChild); - backendFGNode->sceneChangeEvent(change); + renderer.clearDirtyBits(0); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(frontendFGChild->id()); + change->setPropertyName("parentFrameGraphUpdated"); + change->setValue(QVariant::fromValue(fgNode1Id)); + backendFGChild->sceneChangeEvent(change); // THEN QCOMPARE(backendFGNode->childrenIds().size(), 1); - QCOMPARE(backendFGNode->childrenIds().first(), frontendFGChild->id()); + QCOMPARE(backendFGChild->parentId(), fgNode1Id); } { // WHEN - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), frontendFGChild); - backendFGNode->sceneChangeEvent(change); + renderer.clearDirtyBits(0); + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(frontendFGChild->id()); + change->setPropertyName("parentFrameGraphUpdated"); + change->setValue(QVariant::fromValue(Qt3DCore::QNodeId())); + backendFGChild->sceneChangeEvent(change); // THEN QCOMPARE(backendFGNode->childrenIds().size(), 0); + QVERIFY(backendFGChild->parentId().isNull()); } } diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp index eeffc69b2..9b8636f49 100644 --- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp +++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp @@ -33,6 +33,7 @@ #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/filterlayerentityjob_p.h> #include <Qt3DRender/private/updatetreeenabledjob_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/qlayer.h> #include <Qt3DRender/qlayerfilter.h> #include "testaspect.h" @@ -632,6 +633,11 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id()); + + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(aspect->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateTreeEnabledJob updateTreeEnabledJob; updateTreeEnabledJob.setRoot(backendRoot); updateTreeEnabledJob.run(); diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index e2acff16c..cd82d69d8 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -48,6 +48,7 @@ #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/pickboundingvolumejob_p.h> #include <Qt3DRender/private/pickboundingvolumeutils_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/private/updatemeshtrianglelistjob_p.h> #include <Qt3DRender/private/updateworldboundingvolumejob_p.h> #include <Qt3DRender/private/updateworldtransformjob_p.h> @@ -110,6 +111,10 @@ namespace { void runRequiredJobs(Qt3DRender::TestAspect *test) { + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(test->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; updateWorldTransform.setRoot(test->sceneRoot()); updateWorldTransform.run(); diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp index 7a5648271..7bb3c16a7 100644 --- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -246,6 +246,11 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id()); + + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(aspect->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateTreeEnabledJob updateTreeEnabledJob; updateTreeEnabledJob.setRoot(backendRoot); updateTreeEnabledJob.run(); diff --git a/tests/auto/render/qcamera/tst_qcamera.cpp b/tests/auto/render/qcamera/tst_qcamera.cpp index b630c447a..7aef2af7d 100644 --- a/tests/auto/render/qcamera/tst_qcamera.cpp +++ b/tests/auto/render/qcamera/tst_qcamera.cpp @@ -35,6 +35,7 @@ #include <Qt3DCore/QEntity> #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DCore/private/qaspectjobmanager_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qnodecreatedchange.h> @@ -99,6 +100,10 @@ namespace { void runRequiredJobs(Qt3DRender::TestAspect *test) { + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(test->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; updateWorldTransform.setRoot(test->sceneRoot()); updateWorldTransform.run(); diff --git a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp index 4980bfc30..411bb9160 100644 --- a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp +++ b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp @@ -51,6 +51,7 @@ #include <Qt3DRender/private/updateworldtransformjob_p.h> #include <Qt3DRender/private/expandboundingvolumejob_p.h> #include <Qt3DRender/private/calcboundingvolumejob_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/private/calcgeometrytrianglevolumes_p.h> #include <Qt3DRender/private/loadbufferjob_p.h> #include <Qt3DRender/private/buffermanager_p.h> @@ -106,6 +107,10 @@ namespace { void runRequiredJobs(Qt3DRender::TestAspect *test) { + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(test->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; updateWorldTransform.setRoot(test->sceneRoot()); updateWorldTransform.run(); diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index 012cdb1b1..a823c233a 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -254,8 +254,8 @@ private Q_SLOTS: 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // ExpandBoundingVolumeJob - 1 + // RenderableEntityFilterJob - 1 + // CacheRenderableEntitiesJob + 1 + // RenderableEntityFilterPtr + 1 + // SyncRenderableEntities singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -315,6 +315,30 @@ private Q_SLOTS: renderQueue->reset(); // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityHierarchyDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN + QCOMPARE(jobs.size(), + 1 + // EntityEnabledDirty + 1 + // EntityHierarchyJob + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // ExpandBoundingVolumeJob + 1 + // UpdateEntityLayersJob + 1 + // updateLevelOfDetailJob + 1 + // syncLoadingJobs + 1 + // updateSkinningPaletteJob + 1 + // cleanupJob + 1 + // sendBufferCaptureJob + singleRenderViewJobCount + + layerCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); jobs = renderer.renderBinJobs(); @@ -322,6 +346,7 @@ private Q_SLOTS: // and ShaderGathererJob are not added here) QCOMPARE(jobs.size(), 1 + // EntityEnabledDirty + 1 + // EntityHierarchyDirty 1 + // WorldTransformJob 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform @@ -335,13 +360,13 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // BufferGathererJob 1 + // TexturesGathererJob + 1 + // UpdateEntityLayersJob 1 + // LightGathererJob 1 + // CacheLightJob 1 + // RenderableEntityFilterJob 1 + // CacheRenderableEntitiesJob 1 + // ComputableEntityFilterJob 1 + // CacheComputableEntitiesJob - 1 + // UpdateEntityLayersJob singleRenderViewJobCount + layerCacheJobCount + renderViewBuilderMaterialCacheJobCount); diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp index 007bfac7c..a7c81ca20 100644 --- a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp +++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp @@ -474,6 +474,7 @@ private slots: void shouldHandleShaderCodeGeneration() { + QSKIP("Disabled for Qt Base QShaderGenerator Integration"); // GIVEN Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json"); QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); @@ -562,6 +563,8 @@ private slots: void checkCodeUpdatedNotification() { // GIVEN + QSKIP("Disabled for Qt Base QShaderGenerator Integration"); + Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json"); QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type); diff --git a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp index 67ddccd9b..4bab46423 100644 --- a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp +++ b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp @@ -29,6 +29,7 @@ #include <QtTest/QTest> #include <Qt3DRender/private/updateshaderdatatransformjob_p.h> #include <Qt3DRender/private/updateworldtransformjob_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/qrenderaspect.h> @@ -88,6 +89,10 @@ namespace { void runRequiredJobs(Qt3DRender::TestAspect *test) { + Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob; + updateEntitiesJob.setManager(test->nodeManagers()); + updateEntitiesJob.run(); + Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform; updateWorldTransform.setRoot(test->sceneRoot()); updateWorldTransform.run(); diff --git a/tests/manual/cylinder-parent-test/cylinder-parent-test.pro b/tests/manual/cylinder-parent-test/cylinder-parent-test.pro new file mode 100644 index 000000000..d3db3bc76 --- /dev/null +++ b/tests/manual/cylinder-parent-test/cylinder-parent-test.pro @@ -0,0 +1,9 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dinput 3dextras + +SOURCES += main.cpp + + diff --git a/tests/manual/cylinder-parent-test/main.cpp b/tests/manual/cylinder-parent-test/main.cpp new file mode 100644 index 000000000..823461a28 --- /dev/null +++ b/tests/manual/cylinder-parent-test/main.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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:GPL-EXCEPT$ +** 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QTimer> + +#include <Qt3DInput/QInputAspect> + +#include <Qt3DRender/qcamera.h> +#include <Qt3DRender/qcameralens.h> +#include <Qt3DExtras/qcylindermesh.h> +#include <Qt3DRender/qmesh.h> +#include <Qt3DRender/qtechnique.h> +#include <Qt3DExtras/qphongmaterial.h> +#include <Qt3DRender/qeffect.h> +#include <Qt3DRender/qtexture.h> +#include <Qt3DRender/qrenderpass.h> +#include <Qt3DRender/qrenderaspect.h> +#include <Qt3DExtras/qforwardrenderer.h> + +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qtransform.h> +#include <Qt3DCore/qaspectengine.h> + +#include <Qt3DExtras/qt3dwindow.h> +#include <Qt3DExtras/qorbitcameracontroller.h> +#include <QThread> +#include <QLoggingCategory> + +#include <type_traits> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + Qt3DExtras::Qt3DWindow view; + + QLoggingCategory::setFilterRules("Qt3D.Renderer.RenderNodes=true"); + + // Root entity + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + view.setRootEntity(rootEntity); + rootEntity->setObjectName("Root Entity"); + + // Set root object of the scene + view.show(); + + // Camera + Qt3DRender::QCamera *camera = view.camera(); + camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 1000.0f); + camera->setPosition(QVector3D(0, 0, 20.0f)); + camera->setUpVector(QVector3D(0, 1, 0)); + camera->setViewCenter(QVector3D(0, 0, 0)); + + // For camera controls + Qt3DExtras::QOrbitCameraController *cameraController = new Qt3DExtras::QOrbitCameraController(rootEntity); + cameraController->setCamera(camera); + + // Cylinder shape data + Qt3DExtras::QCylinderMesh *mesh = new Qt3DExtras::QCylinderMesh(); + + qDebug() << "Setup complete. Creating cylinders\n"; + + // simple setParent from nullptr (OK for QTBUG-73905) + // green cylinder, bottom left + { + Qt3DCore::QTransform *leftTransform = new Qt3DCore::QTransform; + leftTransform->setTranslation(QVector3D(-5, -2, 0)); + leftTransform->setObjectName("Green transform"); + + Qt3DExtras::QPhongMaterial *greenMaterial = new Qt3DExtras::QPhongMaterial(rootEntity); + greenMaterial->setObjectName("Green Material"); + greenMaterial->setDiffuse(Qt::green); + + Qt3DCore::QEntity *grandParentNode = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *parentNode = new Qt3DCore::QEntity(); + Qt3DCore::QEntity *leafNode = new Qt3DCore::QEntity(); + grandParentNode->setObjectName("Green Grandparent"); + parentNode->setObjectName("Green Parent"); + leafNode->setObjectName("Green Leaf"); + + leafNode->addComponent(mesh); + leafNode->addComponent(greenMaterial); + parentNode->addComponent(leftTransform); + + grandParentNode->setParent(rootEntity); + parentNode->setParent(grandParentNode); + leafNode->setParent(parentNode); + } + + // simple setParent from rootEntity (doesn't work QTBUG-73905) + // yellow cylinder, top left + { + Qt3DCore::QTransform *leftTransform = new Qt3DCore::QTransform; + leftTransform->setTranslation(QVector3D(-5, 2, 0)); + leftTransform->setObjectName("Yellow Transform"); + + Qt3DExtras::QPhongMaterial *yellowMaterial = new Qt3DExtras::QPhongMaterial(rootEntity); + yellowMaterial->setObjectName("Yellow Material"); + yellowMaterial->setDiffuse(Qt::yellow); + + Qt3DCore::QEntity *grandParentNode = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *parentNode = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *leafNode = new Qt3DCore::QEntity(rootEntity); + leafNode->setObjectName("Yellow Leaf"); + grandParentNode->setObjectName("Yellow Grandparent"); + parentNode->setObjectName("Yellow Parent"); + + leafNode->addComponent(mesh); + leafNode->addComponent(yellowMaterial); + parentNode->addComponent(leftTransform); + + // sometimes this can change things + //QCoreApplication::processEvents(); + + grandParentNode->setParent(rootEntity); + parentNode->setParent(grandParentNode); + leafNode->setParent(parentNode); + } + + // complex setParent from nullptr (OK QTBUG-73905?) + // red cylinder, Bottom-right + { + Qt3DCore::QNode *tree1node1 = new Qt3DCore::QNode(); + Qt3DCore::QEntity *tree1node2 = new Qt3DCore::QEntity(); + Qt3DCore::QNode *tree1node3 = new Qt3DCore::QNode(); + tree1node1->setObjectName("Red Tree1-Node1"); + tree1node2->setObjectName("Red Tree1-Node2"); + tree1node3->setObjectName("Red Tree1-Node3"); + + Qt3DCore::QNode *tree2node1 = new Qt3DCore::QNode(); + Qt3DCore::QEntity *tree2node2 = new Qt3DCore::QEntity(); + Qt3DCore::QNode *tree2node3 = new Qt3DCore::QNode(); + tree2node1->setObjectName("Red Tree2-Node1"); + tree2node2->setObjectName("Red Tree2-Node2"); + tree2node3->setObjectName("Red Tree2-Node3"); + + Qt3DCore::QTransform *wrongRedTransform = new Qt3DCore::QTransform; + wrongRedTransform->setTranslation(QVector3D(1, -1, 0)); + Qt3DCore::QTransform *bottomRightTransform = new Qt3DCore::QTransform; + bottomRightTransform->setTranslation(QVector3D(5, -2, 0)); + bottomRightTransform->setObjectName("Red BR Transform"); + wrongRedTransform->setObjectName("Red Wrong Transform"); + + Qt3DExtras::QPhongMaterial *redMaterial = new Qt3DExtras::QPhongMaterial(rootEntity); + redMaterial->setDiffuse(Qt::red); + redMaterial->setObjectName("Red Material"); + Qt3DCore::QEntity *leafNode = new Qt3DCore::QEntity(); + leafNode->setObjectName("Red Leaf"); + leafNode->addComponent(mesh); + leafNode->addComponent(redMaterial); + + tree1node2->addComponent(wrongRedTransform); + tree2node2->addComponent(bottomRightTransform); + + tree1node1->setParent(rootEntity); + tree1node2->setParent(tree1node1); + tree1node3->setParent(tree1node2); + + tree2node1->setParent(rootEntity); + tree2node2->setParent(tree2node1); + tree2node3->setParent(tree2node2); + + leafNode->setParent(tree1node3); + leafNode->setParent(tree2node3); + } + + // complex setParent from rootEntity (doesn't work QTBUG-73905) + // blue cylinder, top right + { + Qt3DCore::QNode *tree1node1 = new Qt3DCore::QNode(rootEntity); + Qt3DCore::QEntity *tree1node2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QNode *tree1node3 = new Qt3DCore::QNode(rootEntity); + tree1node1->setObjectName("Blue Tree1-Node1"); + tree1node2->setObjectName("Blue Tree1-Node2"); + tree1node3->setObjectName("Blue Tree1-Node3"); + + Qt3DCore::QNode *tree2node1 = new Qt3DCore::QNode(rootEntity); + Qt3DCore::QEntity *tree2node2 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QNode *tree2node3 = new Qt3DCore::QNode(rootEntity); + tree2node1->setObjectName("Blue Tree2-Node1"); + tree2node2->setObjectName("Blue Tree2-Node2"); + tree2node3->setObjectName("Blue Tree2-Node3"); + + Qt3DCore::QTransform *wrongBlueTransform = new Qt3DCore::QTransform; + wrongBlueTransform->setTranslation(QVector3D(1, 1, 0)); + Qt3DCore::QTransform *topRightTransform = new Qt3DCore::QTransform; + topRightTransform->setTranslation(QVector3D(5, 2, 0)); + wrongBlueTransform->setObjectName("Blue Wrong Transform"); + topRightTransform->setObjectName("Blue TR Transform"); + + Qt3DExtras::QPhongMaterial *blueMaterial = new Qt3DExtras::QPhongMaterial(rootEntity); + blueMaterial->setObjectName("Blue Material"); + blueMaterial->setDiffuse(Qt::blue); + Qt3DCore::QEntity *leafNode = new Qt3DCore::QEntity(rootEntity); + leafNode->addComponent(mesh); + leafNode->addComponent(blueMaterial); + leafNode->setObjectName("Blue Leaf"); + + // sometimes this can change things + //QCoreApplication::processEvents(); + + tree1node2->addComponent(wrongBlueTransform); + tree2node2->addComponent(topRightTransform); + + tree1node1->setParent(rootEntity); + tree1node2->setParent(tree1node1); + tree1node3->setParent(tree1node2); + + tree2node1->setParent(rootEntity); + tree2node2->setParent(tree2node1); + tree2node3->setParent(tree2node2); + + leafNode->setParent(tree1node3); + leafNode->setParent(tree2node3); + } + + return app.exec(); +} diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index f5a51907a..93890007c 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -13,6 +13,7 @@ SUBDIRS += \ custom-mesh-update-data-cpp \ custom-mesh-update-data-qml \ cylinder-cpp \ + cylinder-parent-test \ cylinder-qml \ deferred-renderer-cpp \ deferred-renderer-qml \ diff --git a/tests/tests.pro b/tests/tests.pro index 157bdcea5..17c91cb1f 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -1,5 +1,8 @@ TEMPLATE = subdirs +!qtHaveModule(3dcore): \ + return() + QT_FOR_CONFIG += 3dcore !package { |