diff options
22 files changed, 548 insertions, 188 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index f421a8025..4e90d3c1d 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -342,65 +342,6 @@ QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> & return callbacks; } -//TODO: Remove this and use new implementation below for both the unblended -// and blended animation cases. -QVector<MappingData> buildPropertyMappings(Handler *handler, - const AnimationClip *clip, - const ChannelMapper *mapper) -{ - QVector<MappingData> mappingDataVec; - ChannelMappingManager *mappingManager = handler->channelMappingManager(); - const QVector<Channel> &channels = clip->channels(); - - // Iterate over the mappings in the mapper object - const auto mappingIds = mapper->mappingIds(); - for (const Qt3DCore::QNodeId mappingId : mappingIds) { - // Get the mapping object - ChannelMapping *mapping = mappingManager->lookupResource(mappingId); - Q_ASSERT(mapping); - - // Populate the data we need, easy stuff first - MappingData mappingData; - mappingData.targetId = mapping->targetId(); - mappingData.propertyName = mapping->propertyName(); - mappingData.type = mapping->type(); - mappingData.callback = mapping->callback(); - mappingData.callbackFlags = mapping->callbackFlags(); - - if (mappingData.type == static_cast<int>(QVariant::Invalid)) { - qWarning() << "Unknown type for node id =" << mappingData.targetId - << "and property =" << mapping->property() - << "and callback =" << mapping->callback(); - continue; - } - - // Now the tricky part. Mapping the channel indices onto the property type. - // Try to find a ChannelGroup with matching name - const QString channelName = mapping->channelName(); - int channelGroupIndex = 0; - bool foundMatch = false; - for (const Channel &channel : channels) { - if (channel.name == channelName) { - foundMatch = true; - const int channelBaseIndex = clip->channelComponentBaseIndex(channelGroupIndex); - - // Within this group, match channel names with index ordering - mappingData.channelIndices = channelComponentsToIndices(channel, mappingData.type, channelBaseIndex); - - // Store the mapping data - mappingDataVec.push_back(mappingData); - - if (foundMatch) - break; - } - - ++channelGroupIndex; - } - } - - return mappingDataVec; -} - QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &channelMappings, const QVector<ChannelNameAndType> &channelNamesAndTypes, const QVector<ComponentIndices> &channelComponentIndices) @@ -539,6 +480,10 @@ QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler, ClipBlendNodeVisitor::VisitOnlyDependencies); auto func = [&clipIds, nodeManager] (ClipBlendNode *blendNode) { + // Check if this is a value node itself + if (blendNode->blendType() == ClipBlendNode::ValueType) + clipIds.append(blendNode->peerId()); + const auto dependencyIds = blendNode->currentDependencyIds(); for (const auto dependencyId : dependencyIds) { // Look up the blend node and if it's a value type (clip), @@ -565,12 +510,11 @@ ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &ta // Reserve enough storage for all the format indices int indexCount = 0; - for (const auto targetIndexVec : qAsConst(targetIndices)) + for (const auto &targetIndexVec : qAsConst(targetIndices)) indexCount += targetIndexVec.size(); ComponentIndices format; format.resize(indexCount); - // Iterate through the target channels const int channelCount = targetChannels.size(); auto formatIt = format.begin(); @@ -579,18 +523,18 @@ ComponentIndices generateClipFormatIndices(const QVector<ChannelNameAndType> &ta const ChannelNameAndType &targetChannel = targetChannels[i]; const int clipChannelIndex = clip->channelIndex(targetChannel.name, targetChannel.jointIndex); - - // TODO: Ensure channel in the clip has enough components to map to the type. - // Requires some improvements to the clip data structure first. - // TODO: I don't think we need the targetIndices, only the number of components - // for each target channel. Check once blend tree is complete. const int componentCount = targetIndices[i].size(); if (clipChannelIndex != -1) { // Found a matching channel in the clip. Get the base channel // component index and populate the format indices for this channel. const int baseIndex = clip->channelComponentBaseIndex(clipChannelIndex); - std::iota(formatIt, formatIt + componentCount, baseIndex); + + // Within this group, match channel names with index ordering + const auto channelIndices = channelComponentsToIndices(clip->channels()[clipChannelIndex], + targetChannel.type, + baseIndex); + std::copy(channelIndices.begin(), channelIndices.end(), formatIt); } else { // No such channel in this clip. We'll use default values when diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index 7fcd9ead5..cf21c448d 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -190,11 +190,6 @@ QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> & const QVector<float> &channelResults); Q_AUTOTEST_EXPORT -QVector<MappingData> buildPropertyMappings(Handler *handler, - const AnimationClip *clip, - const ChannelMapper *mapper); - -Q_AUTOTEST_EXPORT QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping *> &channelMappings, const QVector<ChannelNameAndType> &channelNamesAndTypes, const QVector<ComponentIndices> &channelComponentIndices); diff --git a/src/animation/backend/channelmapper.cpp b/src/animation/backend/channelmapper.cpp index 0e5555096..48a1335fa 100644 --- a/src/animation/backend/channelmapper.cpp +++ b/src/animation/backend/channelmapper.cpp @@ -38,6 +38,7 @@ #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/private/qchannelmapper_p.h> #include <Qt3DAnimation/private/animationlogging_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qpropertynodeaddedchange.h> #include <Qt3DCore/qpropertynoderemovedchange.h> @@ -50,6 +51,7 @@ namespace Animation { ChannelMapper::ChannelMapper() : BackendNode(ReadOnly) , m_mappingIds() + , m_isDirty(true) { } @@ -58,12 +60,15 @@ void ChannelMapper::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QChannelMapperData>>(change); const auto &data = typedChange->data; m_mappingIds = data.mappingIds; + m_isDirty = true; } void ChannelMapper::cleanup() { setEnabled(false); m_mappingIds.clear(); + m_mappings.clear(); + m_isDirty = true; } void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) @@ -74,6 +79,7 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->propertyName() == QByteArrayLiteral("mappings")) { m_mappingIds.push_back(change->addedNodeId()); setDirty(Handler::ChannelMappingsDirty); + m_isDirty = true; } break; } @@ -83,6 +89,7 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) if (change->propertyName() == QByteArrayLiteral("mappings")) { m_mappingIds.removeOne(change->removedNodeId()); setDirty(Handler::ChannelMappingsDirty); + m_isDirty = true; } break; } @@ -93,6 +100,19 @@ void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) QBackendNode::sceneChangeEvent(e); } +void ChannelMapper::updateMappings() const +{ + m_mappings.clear(); + m_mappings.reserve(m_mappingIds.size()); + const auto mappingManager = m_handler->channelMappingManager(); + for (const auto &mappingId : m_mappingIds) { + const auto mapping = mappingManager->lookupResource(mappingId); + Q_ASSERT(mapping); + m_mappings.push_back(mapping); + } + m_isDirty = false; +} + } // namespace Animation } // namespace Qt3DAnimation diff --git a/src/animation/backend/channelmapper_p.h b/src/animation/backend/channelmapper_p.h index 710de01ab..8d8f03511 100644 --- a/src/animation/backend/channelmapper_p.h +++ b/src/animation/backend/channelmapper_p.h @@ -74,10 +74,22 @@ public: void setMappingIds(const QVector<Qt3DCore::QNodeId> &mappingIds) { m_mappingIds = mappingIds; } QVector<Qt3DCore::QNodeId> mappingIds() const { return m_mappingIds; } + QVector<ChannelMapping*> mappings() const + { + if (m_isDirty) + updateMappings(); + return m_mappings; + } + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; + void updateMappings() const; QVector<Qt3DCore::QNodeId> m_mappingIds; + + // Cached data + mutable QVector<ChannelMapping*> m_mappings; + mutable bool m_isDirty; }; } // namespace Animation diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp index 2f4dca63f..568e2dbb0 100644 --- a/src/animation/backend/clipanimator.cpp +++ b/src/animation/backend/clipanimator.cpp @@ -114,6 +114,7 @@ void ClipAnimator::cleanup() m_clockId = Qt3DCore::QNodeId(); m_running = false; m_loops = 1; + m_formatIndices.clear(); } void ClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h index b3389f8da..8a08969ba 100644 --- a/src/animation/backend/clipanimator_p.h +++ b/src/animation/backend/clipanimator_p.h @@ -97,6 +97,9 @@ public: void animationClipMarkedDirty() { setDirty(Handler::ClipAnimatorDirty); } + void setFormatIndices(const ComponentIndices &formatIndices) { m_formatIndices = formatIndices; } + ComponentIndices formatIndices() const { return m_formatIndices; } + private: void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; @@ -111,6 +114,7 @@ private: QVector<MappingData> m_mappingData; int m_currentLoop; + ComponentIndices m_formatIndices; }; } // namespace Animation diff --git a/src/animation/backend/clipblendvalue_p.h b/src/animation/backend/clipblendvalue_p.h index 6da800f98..5ff8d2b0f 100644 --- a/src/animation/backend/clipblendvalue_p.h +++ b/src/animation/backend/clipblendvalue_p.h @@ -73,7 +73,7 @@ public: inline QVector<Qt3DCore::QNodeId> currentDependencyIds() const Q_DECL_OVERRIDE { - return { m_clipId }; + return {}; } double duration() const Q_DECL_OVERRIDE; diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp index 6dab51d63..d9600c375 100644 --- a/src/animation/backend/evaluateclipanimatorjob.cpp +++ b/src/animation/backend/evaluateclipanimatorjob.cpp @@ -70,7 +70,11 @@ void EvaluateClipAnimatorJob::run() // Prepare for evaluation (convert global time to local time ....) const AnimatorEvaluationData animatorEvaluationData = evaluationDataForAnimator(clipAnimator, clock, globalTime); const ClipEvaluationData preEvaluationDataForClip = evaluationDataForClip(clip, animatorEvaluationData); - const ClipResults channelResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); + const ClipResults rawClipResults = evaluateClipAtLocalTime(clip, preEvaluationDataForClip.localTime); + + // Reformat the clip results into the layout used by this animator/blend tree + ComponentIndices format = clipAnimator->formatIndices(); + ClipResults formattedClipResults = formatClipResults(rawClipResults, format); if (preEvaluationDataForClip.isFinalFrame) clipAnimator->setRunning(false); @@ -80,14 +84,15 @@ void EvaluateClipAnimatorJob::run() // Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend) const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(), clipAnimator->mappingData(), - channelResults, + formattedClipResults, preEvaluationDataForClip.isFinalFrame); // Send the property changes clipAnimator->sendPropertyChanges(changes); // Trigger callbacks either on this thread or by notifying the gui thread. - const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(clipAnimator->mappingData(), channelResults); + const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(clipAnimator->mappingData(), + formattedClipResults); clipAnimator->sendCallbacks(callbacks); } diff --git a/src/animation/backend/findrunningclipanimatorsjob.cpp b/src/animation/backend/findrunningclipanimatorsjob.cpp index a8349eb91..41454004d 100644 --- a/src/animation/backend/findrunningclipanimatorsjob.cpp +++ b/src/animation/backend/findrunningclipanimatorsjob.cpp @@ -62,24 +62,39 @@ void FindRunningClipAnimatorsJob::run() Q_ASSERT(m_handler); ClipAnimatorManager *clipAnimatorManager = m_handler->clipAnimatorManager(); - for (const auto clipAnimatorHandle : qAsConst(m_clipAnimatorHandles)) { + for (const auto &clipAnimatorHandle : qAsConst(m_clipAnimatorHandles)) { ClipAnimator *clipAnimator = clipAnimatorManager->data(clipAnimatorHandle); Q_ASSERT(clipAnimator); const bool canRun = clipAnimator->canRun(); m_handler->setClipAnimatorRunning(clipAnimatorHandle, canRun); - // The clip animator needs to know how to map fcurve values through to - // properties on QNodes. Now we know this animator can run, build the mapping - // table. - // TODO: Should be possible to parallelise this with the fcurve evaluation as - // sending the property change events doesn't happen until after evaluation - if (canRun) { - const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); - const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId()); - Q_ASSERT(clip && mapper); - const QVector<MappingData> mappingData = buildPropertyMappings(m_handler, clip, mapper); - clipAnimator->setMappingData(mappingData); - } + if (!canRun) + continue; + + // The clip animator needs to know how to map fcurve values through to properties on QNodes. + // Now we know this animator can run, build the mapping table. Even though this could be + // done a little simpler in the non-blended case, we follow the same code path as the + // blended clip animator for consistency and ease of maintenance. + const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(clipAnimator->mapperId()); + Q_ASSERT(mapper); + const QVector<ChannelMapping *> channelMappings = mapper->mappings(); + + const QVector<ChannelNameAndType> channelNamesAndTypes + = buildRequiredChannelsAndTypes(m_handler, mapper); + const QVector<ComponentIndices> channelComponentIndices + = assignChannelComponentIndices(channelNamesAndTypes); + + const AnimationClip *clip = m_handler->animationClipLoaderManager()->lookupResource(clipAnimator->clipId()); + Q_ASSERT(clip); + const ComponentIndices formatIndices = generateClipFormatIndices(channelNamesAndTypes, + channelComponentIndices, + clip); + clipAnimator->setFormatIndices(formatIndices); + + const QVector<MappingData> mappingData = buildPropertyMappings(channelMappings, + channelNamesAndTypes, + channelComponentIndices); + clipAnimator->setMappingData(mappingData); } qCDebug(Jobs) << "Running clip animators =" << m_handler->runningClipAnimators(); diff --git a/src/animation/backend/findrunningclipanimatorsjob_p.h b/src/animation/backend/findrunningclipanimatorsjob_p.h index 023f46303..f8b09939f 100644 --- a/src/animation/backend/findrunningclipanimatorsjob_p.h +++ b/src/animation/backend/findrunningclipanimatorsjob_p.h @@ -52,6 +52,10 @@ #include <Qt3DAnimation/private/handle_types_p.h> #include <QtCore/qvector.h> +#if defined(QT_BUILD_INTERNAL) +class tst_FindRunningClipAnimatorsJob; +#endif + QT_BEGIN_NAMESPACE namespace Qt3DAnimation { @@ -59,7 +63,7 @@ namespace Animation { class Handler; -class FindRunningClipAnimatorsJob : public Qt3DCore::QAspectJob +class Q_AUTOTEST_EXPORT FindRunningClipAnimatorsJob : public Qt3DCore::QAspectJob { public: FindRunningClipAnimatorsJob(); @@ -75,6 +79,10 @@ protected: private: QVector<HClipAnimator> m_clipAnimatorHandles; Handler *m_handler; + +#if defined(QT_BUILD_INTERNAL) + friend class ::tst_FindRunningClipAnimatorsJob; +#endif }; } // namespace Animation diff --git a/src/plugins/geometryloaders/default/objgeometryloader.cpp b/src/plugins/geometryloaders/default/objgeometryloader.cpp index b1fb1f931..7184e2f69 100644 --- a/src/plugins/geometryloaders/default/objgeometryloader.cpp +++ b/src/plugins/geometryloaders/default/objgeometryloader.cpp @@ -144,7 +144,7 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh) ++normalsOffset; } } - } else if (!skipping && qstrncmp(tokens.charPtrAt(0), "f ", 2) == 0) { + } else if (!skipping && tokens.size() >= 4 && qstrncmp(tokens.charPtrAt(0), "f ", 2) == 0) { // Process face ++faceCount; diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp index 4212897ab..23f88eb10 100644 --- a/src/render/frontend/qrendersettings.cpp +++ b/src/render/frontend/qrendersettings.cpp @@ -217,8 +217,11 @@ void QRenderSettings::setActiveFrameGraph(QFrameGraphNode *activeFrameGraph) if (d->m_activeFrameGraph && activeFrameGraph) { Qt3DRender::QRenderSurfaceSelector *oldSurfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(d->m_activeFrameGraph); Qt3DRender::QRenderSurfaceSelector *newSurfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(activeFrameGraph); - if (oldSurfaceSelector && newSurfaceSelector && oldSurfaceSelector->surface()) + if (oldSurfaceSelector && newSurfaceSelector && oldSurfaceSelector->surface()) { + newSurfaceSelector->setExternalRenderTargetSize(oldSurfaceSelector->externalRenderTargetSize()); + newSurfaceSelector->setSurfacePixelRatio(oldSurfaceSelector->surfacePixelRatio()); newSurfaceSelector->setSurface(oldSurfaceSelector->surface()); + } } if (d->m_activeFrameGraph) diff --git a/src/render/texture/gltexture.cpp b/src/render/texture/gltexture.cpp index 2a35a6f7e..11cc1544f 100644 --- a/src/render/texture/gltexture.cpp +++ b/src/render/texture/gltexture.cpp @@ -208,6 +208,7 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture() // need to (re-)upload texture data? if (needUpload && !texturedDataInvalid) { uploadGLTextureData(); + setDirtyFlag(TextureData, false); } // need to set texture parameters? diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index eff1a4779..c97b07923 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -38,5 +38,6 @@ qtConfig(private_tests) { animationutils \ qabstractanimation \ clock \ - skeleton + skeleton \ + findrunningclipanimatorsjob } diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 9bc7a8c47..177dbd19a 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -271,77 +271,6 @@ public: private Q_SLOTS: void checkBuildPropertyMappings_data() { - QTest::addColumn<Handler *>("handler"); - QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); - QTest::addColumn<ChannelMapper *>("channelMapper"); - QTest::addColumn<AnimationClip *>("clip"); - QTest::addColumn<QVector<MappingData>>("expectedMappingData"); - - auto handler = new Handler; - auto channelMapping = createChannelMapping(handler, - QLatin1String("Location"), - Qt3DCore::QNodeId::createId(), - QLatin1String("translation"), - "translation", - static_cast<int>(QVariant::Vector3D)); - QVector<ChannelMapping *> channelMappings; - channelMappings.push_back(channelMapping); - - // ... a channel mapper... - auto channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); - - // ...and an animation clip - auto clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); - - QVector<MappingData> mappingData; - MappingData mapping; - mapping.targetId = channelMapping->targetId(); - mapping.propertyName = channelMapping->propertyName(); // Location - mapping.type = channelMapping->type(); - mapping.channelIndices = QVector<int>() << 0 << 1 << 2; // Location X, Y, Z - mappingData.push_back(mapping); - - QTest::newRow("clip1.json") << handler - << channelMappings - << channelMapper - << clip - << mappingData; - } - - void checkBuildPropertyMappings() - { - // GIVEN - QFETCH(Handler *, handler); - QFETCH(QVector<ChannelMapping *>, channelMappings); - QFETCH(ChannelMapper *, channelMapper); - QFETCH(AnimationClip *, clip); - QFETCH(QVector<MappingData>, expectedMappingData); - - // WHEN - // Build the mapping data for the above configuration - QVector<MappingData> mappingData = buildPropertyMappings(handler, clip, channelMapper); - - // THEN - QCOMPARE(mappingData.size(), expectedMappingData.size()); - for (int i = 0; i < mappingData.size(); ++i) { - const auto mapping = mappingData[i]; - const auto expectedMapping = expectedMappingData[i]; - - QCOMPARE(mapping.targetId, expectedMapping.targetId); - QCOMPARE(mapping.propertyName, expectedMapping.propertyName); - QCOMPARE(mapping.type, expectedMapping.type); - QCOMPARE(mapping.channelIndices.size(), expectedMapping.channelIndices.size()); - for (int j = 0; j < mapping.channelIndices.size(); ++j) { - QCOMPARE(mapping.channelIndices[j], expectedMapping.channelIndices[j]); - } - } - - // Cleanup - delete handler; - } - - void checkBuildPropertyMappings2_data() - { QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); @@ -507,7 +436,7 @@ private Q_SLOTS: } } - void checkBuildPropertyMappings2() + void checkBuildPropertyMappings() { // GIVEN QFETCH(QVector<ChannelMapping *>, channelMappings); @@ -2088,6 +2017,18 @@ private Q_SLOTS: QTest::newRow("simple lerp") << handler << lerp->peerId() << expectedIds; } + + { + Handler *handler = new Handler; + + const auto value1 = createClipBlendValue(handler); + const auto clip1Id = Qt3DCore::QNodeId::createId(); + value1->setClipId(clip1Id); + + QVector<Qt3DCore::QNodeId> expectedIds = { value1->peerId() }; + + QTest::newRow("value only") << handler << value1->peerId() << expectedIds; + } } void checkGatherValueNodesToEvaluate() @@ -2694,8 +2635,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation - 4, 5, 6, // Location + ComponentIndices expectedResults = { 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) + 4, 6, 5, // Location (y/z swapped in clip3.json) 7, 8, 9, // Base Color 10, // Metalness 11 }; // Roughness @@ -2724,8 +2665,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location - 0, 1, 2, 3, // Rotation + ComponentIndices expectedResults = { 4, 6, 5, // Location (y/z swapped in clip3.json) + 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) 7, 8, 9, // Base Color 10, // Metalness 11 }; // Roughness @@ -2754,8 +2695,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 0, 1, 2, 3, // Rotation - 4, 5, 6, // Location + ComponentIndices expectedResults = { 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) + 4, 6, 5, // Location (y/z swapped in clip3.json) -1, -1, -1, // Albedo (missing from clip) 10, // Metalness 11 }; // Roughness @@ -2784,8 +2725,8 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip3.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location - 0, 1, 2, 3, // Rotation + ComponentIndices expectedResults = { 4, 6, 5, // Location (y/z swapped in clip3.json) + 0, 1, 3, 2, // Rotation (y/z swapped in clip3.json) -1, -1, -1, // Albedo (missing from clip) 10, // Metalness 11 }; // Roughness @@ -2825,17 +2766,17 @@ private Q_SLOTS: clip->setSource(QUrl("qrc:/clip5.json")); clip->loadAnimation(); - ComponentIndices expectedResults = { 4, 5, 6, // Location, joint 0 - 0, 1, 2, 3, // Rotation, joint 0 + ComponentIndices expectedResults = { 4, 6, 5, // Location, joint 0 (y/z swapped in clip5.json) + 0, 1, 3, 2, // Rotation, joint 0 (y/z swapped in clip5.json) 7, 8, 9, // Scale, joint 0 - 14, 15, 16, // Location, joint 1 - 10, 11, 12, 13, // Rotation, joint 1 + 14, 16, 15, // Location, joint 1 (y/z swapped in clip5.json) + 10, 11, 13, 12, // Rotation, joint 1 (y/z swapped in clip5.json) 17, 18, 19, // Scale, joint 1 - 24, 25, 26, // Location, joint 2 - 20, 21, 22, 23, // Rotation, joint 2 + 24, 26, 25, // Location, joint 2 (y/z swapped in clip5.json) + 20, 21, 23, 22, // Rotation, joint 2 (y/z swapped in clip5.json) 27, 28, 29, // Scale, joint 2 - 34, 35, 36, // Location, joint 3 - 30, 31, 32, 33, // Rotation, joint 3 + 34, 36, 35, // Location, joint 3 (y/z swapped in clip5.json) + 30, 31, 33, 32, // Rotation, joint 3 (y/z swapped in clip5.json) 37, 38, 39 }; // Scale, joint 3 QTest::newRow("skeleton (SQT), 4 joints") diff --git a/tests/auto/animation/channelmapper/tst_channelmapper.cpp b/tests/auto/animation/channelmapper/tst_channelmapper.cpp index 4dcb52aef..446e1a0c5 100644 --- a/tests/auto/animation/channelmapper/tst_channelmapper.cpp +++ b/tests/auto/animation/channelmapper/tst_channelmapper.cpp @@ -30,6 +30,8 @@ #include <qbackendnodetester.h> #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/managers_p.h> #include <Qt3DAnimation/qchannelmapper.h> #include <Qt3DAnimation/qchannelmapping.h> #include <Qt3DAnimation/private/qchannelmapper_p.h> @@ -116,13 +118,40 @@ private Q_SLOTS: // WHEN Qt3DAnimation::QChannelMapping mapping; const Qt3DCore::QNodeId mappingId = mapping.id(); - const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping); + Qt3DAnimation::Animation::ChannelMapping *backendMapping + = handler.channelMappingManager()->getOrCreateResource(mappingId); + backendMapping->setHandler(&handler); + simulateInitialization(&mapping, backendMapping); + + auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping); nodeAddedChange->setPropertyName("mappings"); backendMapper.sceneChangeEvent(nodeAddedChange); // THEN QCOMPARE(backendMapper.mappingIds().size(), 1); QCOMPARE(backendMapper.mappingIds().first(), mappingId); + QCOMPARE(backendMapper.mappings().size(), 1); + QCOMPARE(backendMapper.mappings().first(), backendMapping); + + // WHEN + Qt3DAnimation::QChannelMapping mapping2; + const Qt3DCore::QNodeId mappingId2 = mapping2.id(); + Qt3DAnimation::Animation::ChannelMapping *backendMapping2 + = handler.channelMappingManager()->getOrCreateResource(mappingId2); + backendMapping2->setHandler(&handler); + simulateInitialization(&mapping2, backendMapping2); + + nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping2); + nodeAddedChange->setPropertyName("mappings"); + backendMapper.sceneChangeEvent(nodeAddedChange); + + // THEN + QCOMPARE(backendMapper.mappingIds().size(), 2); + QCOMPARE(backendMapper.mappingIds().first(), mappingId); + QCOMPARE(backendMapper.mappingIds().last(), mappingId2); + QCOMPARE(backendMapper.mappings().size(), 2); + QCOMPARE(backendMapper.mappings().first(), backendMapping); + QCOMPARE(backendMapper.mappings().last(), backendMapping2); // WHEN const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &mapping); @@ -130,7 +159,10 @@ private Q_SLOTS: backendMapper.sceneChangeEvent(nodeRemovedChange); // THEN - QCOMPARE(backendMapper.mappingIds().size(), 0); + QCOMPARE(backendMapper.mappingIds().size(), 1); + QCOMPARE(backendMapper.mappingIds().first(), mappingId2); + QCOMPARE(backendMapper.mappings().size(), 1); + QCOMPARE(backendMapper.mappings().first(), backendMapping2); } }; diff --git a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp index 6fe2846b8..fcbc167ca 100644 --- a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp +++ b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp @@ -137,8 +137,7 @@ private Q_SLOTS: QVector<Qt3DCore::QNodeId> actualIds = clipNode.currentDependencyIds(); // THEN - QCOMPARE(actualIds.size(), 1); - QCOMPARE(actualIds[0], clipId); + QCOMPARE(actualIds.size(), 0); // WHEN auto anotherClipId = Qt3DCore::QNodeId::createId(); @@ -146,8 +145,7 @@ private Q_SLOTS: actualIds = clipNode.currentDependencyIds(); // THEN - QCOMPARE(actualIds.size(), 1); - QCOMPARE(actualIds[0], anotherClipId); + QCOMPARE(actualIds.size(), 0); } void checkDuration() diff --git a/tests/auto/animation/findrunningclipanimatorsjob/clip1.json b/tests/auto/animation/findrunningclipanimatorsjob/clip1.json new file mode 100644 index 000000000..a2ad365a8 --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/clip1.json @@ -0,0 +1,114 @@ +{ + "animations": [ + { + "animationName": "CubeAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location" + } + ] + } + ] +} + diff --git a/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro new file mode 100644 index 000000000..f81b95dcd --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_findrunningclipanimatorsjob + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_findrunningclipanimatorsjob.cpp + +include(../../core/common/common.pri) + +RESOURCES += \ + findrunningclipanimatorsjob.qrc diff --git a/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc new file mode 100644 index 000000000..72234ec64 --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/findrunningclipanimatorsjob.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>clip1.json</file> + </qresource> +</RCC> diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp new file mode 100644 index 000000000..79d18b7cf --- /dev/null +++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 <QtTest/QTest> +#include <Qt3DAnimation/qanimationcliploader.h> +#include <Qt3DAnimation/qclipanimator.h> +#include <Qt3DAnimation/qchannelmapper.h> +#include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/private/clipanimator_p.h> +#include <Qt3DAnimation/private/channelmapper_p.h> +#include <Qt3DAnimation/private/channelmapping_p.h> +#include <Qt3DAnimation/private/findrunningclipanimatorsjob_p.h> +#include <Qt3DAnimation/private/handler_p.h> +#include <Qt3DAnimation/private/managers_p.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DAnimation::Animation; + +Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) +Q_DECLARE_METATYPE(QVector<Qt3DAnimation::Animation::HClipAnimator>) + +typedef QHash<ClipAnimator*, QVector<Qt3DAnimation::Animation::MappingData>> MappingDataResults; +Q_DECLARE_METATYPE(MappingDataResults) + +class tst_FindRunningClipAnimatorsJob: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +public: + ChannelMapping *createChannelMapping(Handler *handler, + const QString &channelName, + const Qt3DCore::QNodeId targetId, + const QString &property, + const char *propertyName, + int type) + { + auto channelMappingId = Qt3DCore::QNodeId::createId(); + ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); + setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); + channelMapping->setTargetId(targetId); + channelMapping->setProperty(property); + channelMapping->setPropertyName(propertyName); + channelMapping->setChannelName(channelName); + channelMapping->setType(type); + return channelMapping; + } + + ChannelMapper *createChannelMapper(Handler *handler, + const QVector<Qt3DCore::QNodeId> &mappingIds) + { + auto channelMapperId = Qt3DCore::QNodeId::createId(); + ChannelMapper *channelMapper = handler->channelMapperManager()->getOrCreateResource(channelMapperId); + setPeerId(channelMapper, channelMapperId); + channelMapper->setHandler(handler); + channelMapper->setMappingIds(mappingIds); + return channelMapper; + } + + AnimationClip *createAnimationClipLoader(Handler *handler, + const QUrl &source) + { + auto clipId = Qt3DCore::QNodeId::createId(); + AnimationClip *clip = handler->animationClipLoaderManager()->getOrCreateResource(clipId); + setPeerId(clip, clipId); + clip->setHandler(handler); + clip->setDataType(AnimationClip::File); + clip->setSource(source); + clip->loadAnimation(); + return clip; + } + + ClipAnimator *createClipAnimator(Handler *handler, + qint64 globalStartTimeNS, + int loops) + { + auto animatorId = Qt3DCore::QNodeId::createId(); + ClipAnimator *animator = handler->clipAnimatorManager()->getOrCreateResource(animatorId); + setPeerId(animator, animatorId); + animator->setHandler(handler); + animator->setStartTime(globalStartTimeNS); + animator->setLoops(loops); + return animator; + } + +private Q_SLOTS: + void checkJob_data() + { + QTest::addColumn<Handler *>("handler"); + QTest::addColumn<QVector<HClipAnimator>>("dirtyClipAnimators"); + QTest::addColumn<MappingDataResults>("expectedResults"); + + Handler *handler; + AnimationClip *clip; + ClipAnimator *animator; + QVector<HClipAnimator> dirtyClipAnimators; + ChannelMapper *channelMapper; + MappingDataResults expectedResults; + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + + const qint64 globalStartTimeNS = 0; + const int loops = 1; + animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setClipId(clip->peerId()); + dirtyClipAnimators = (QVector<HClipAnimator>() + << handler->clipAnimatorManager()->getOrAcquireHandle(animator->peerId())); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + channelMapper = createChannelMapper(handler, QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + animator->setMapperId(channelMapper->peerId()); + animator->setRunning(true); // Has to be marked as running for the job to process it + + const ComponentIndices locationIndices = { 0, 1, 2 }; + MappingData expectedMapping; + expectedMapping.targetId = channelMapping->targetId(); + expectedMapping.propertyName = channelMapping->propertyName(); + expectedMapping.type = channelMapping->type(); + expectedMapping.channelIndices = locationIndices; + expectedResults.insert(animator, QVector<MappingData>() << expectedMapping); + + QTest::newRow("single mapping") + << handler + << dirtyClipAnimators + << expectedResults; + } + } + + void checkJob() + { + // GIVEN + QFETCH(Handler *, handler); + QFETCH(QVector<HClipAnimator>, dirtyClipAnimators); + QFETCH(MappingDataResults, expectedResults); + FindRunningClipAnimatorsJob job; + + // WHEN + job.setHandler(handler); + job.setDirtyClipAnimators(dirtyClipAnimators); + job.run(); + + // THEN - check the resulting MappingData on the animator matches the expected results + for (const auto &dirtyClipAnimator : dirtyClipAnimators) { + const auto animator = handler->clipAnimatorManager()->data(dirtyClipAnimator); + const QVector<MappingData> actualMappingData = animator->mappingData(); + const QVector<MappingData> expectedMappingData = expectedResults[animator]; + + QCOMPARE(expectedMappingData.size(), actualMappingData.size()); + for (int i = 0; i < actualMappingData.size(); ++i) { + QCOMPARE(expectedMappingData[i].targetId, actualMappingData[i].targetId); + QCOMPARE(expectedMappingData[i].type, actualMappingData[i].type); + QVERIFY(qstrcmp(expectedMappingData[i].propertyName, actualMappingData[i].propertyName) == 0); + QCOMPARE(expectedMappingData[i].channelIndices.size(), actualMappingData[i].channelIndices.size()); + + for (int j = 0; j < actualMappingData[i].channelIndices.size(); ++j) { + QCOMPARE(expectedMappingData[i].channelIndices[j], actualMappingData[i].channelIndices[j]); + } + } + } + } +}; + +QTEST_APPLESS_MAIN(tst_FindRunningClipAnimatorsJob) + +#include "tst_findrunningclipanimatorsjob.moc" diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index bf5f0d55f..fd430c5d8 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -27,8 +27,12 @@ ****************************************************************************/ #include <QtTest/QtTest> +#include <Qt3DCore/qcomponent.h> #include <Qt3DRender/qgeometryfactory.h> #include <Qt3DRender/qgeometry.h> +#include <Qt3DRender/qmesh.h> +#include <Qt3DRender/private/qmesh_p.h> +#include <Qt3DCore/qaspectengine.h> class MeshFunctorA : public Qt3DRender::QGeometryFactory { @@ -117,8 +121,46 @@ private Q_SLOTS: QVERIFY(*functorB == *functorB); QVERIFY(*functorASub == *functorASub); } + + void checkMeshFunctorEquality() + { + // GIVEN + Qt3DCore::QAspectEngine engine; + auto meshA = new Qt3DRender::QMesh(); + meshA->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshA->setMeshName(QLatin1String("bar")); + + auto meshB = new Qt3DRender::QMesh(); + meshB->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshB->setMeshName(QLatin1String("baz")); + + auto meshC = new Qt3DRender::QMesh(); + meshC->setSource(QUrl::fromLocalFile(QLatin1String("/baz"))); + meshC->setMeshName(QLatin1String("bar")); + + auto meshD = new Qt3DRender::QMesh(); + meshD->setSource(QUrl::fromLocalFile(QLatin1String("/foo"))); + meshD->setMeshName(QLatin1String("bar")); + + const Qt3DRender::MeshLoaderFunctor functorA(meshA, &engine); + const Qt3DRender::MeshLoaderFunctor functorB(meshB, &engine); + const Qt3DRender::MeshLoaderFunctor functorC(meshC, &engine); + const Qt3DRender::MeshLoaderFunctor functorD(meshD, &engine); + + // WHEN + const bool selfEquality = (functorA == functorA); + const bool sameSource = (functorA == functorB); + const bool sameMeshName = (functorA == functorC); + const bool perfectMatch = (functorA == functorD); + + // THEN + QCOMPARE(selfEquality, true); + QCOMPARE(sameSource, false); + QCOMPARE(sameMeshName, false); + QCOMPARE(perfectMatch, true); + } }; -QTEST_APPLESS_MAIN(tst_MeshFunctors) +QTEST_MAIN(tst_MeshFunctors) #include "tst_meshfunctors.moc" |