From f0f5a2de1da2e05e3587d2a6486687ebbe649339 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 28 Mar 2019 08:31:42 +0100 Subject: Animations: handle variable length properties For that we know determine the expected number of channel components for a given property in the frontend where we have access to both the type and the value rather than in the backend using the type only. Change-Id: I75aca20d43dd1b3db316c303af041acd557c07e4 Reviewed-by: Sean Harmer --- src/animation/backend/animationutils.cpp | 110 +++--- src/animation/backend/animationutils_p.h | 37 ++- src/animation/backend/channelmapping.cpp | 5 + src/animation/backend/channelmapping_p.h | 4 + src/animation/frontend/qabstractchannelmapping_p.h | 2 +- src/animation/frontend/qchannelmapping.cpp | 78 ++++- src/animation/frontend/qchannelmapping_p.h | 10 +- tests/auto/animation/animation.pro | 4 +- .../animationutils/tst_animationutils.cpp | 367 ++++++++++++++++----- .../channelmapping/tst_channelmapping.cpp | 53 ++- .../tst_findrunningclipanimatorsjob.cpp | 16 +- .../qchannelmapping/tst_qchannelmapping.cpp | 161 ++++++++- 12 files changed, 671 insertions(+), 176 deletions(-) diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp index c876fcb87..30db10e3b 100644 --- a/src/animation/backend/animationutils.cpp +++ b/src/animation/backend/animationutils.cpp @@ -58,36 +58,6 @@ QT_BEGIN_NAMESPACE namespace Qt3DAnimation { namespace Animation { -int componentsForType(int type) -{ - int componentCount = 1; - switch (type) { - case QMetaType::Float: - case QVariant::Double: - componentCount = 1; - break; - - case QVariant::Vector2D: - componentCount = 2; - break; - - case QVariant::Vector3D: - case QVariant::Color: - componentCount = 3; - break; - - case QVariant::Vector4D: - case QVariant::Quaternion: - componentCount = 4; - break; - - default: - qWarning() << "Unhandled animation type"; - } - - return componentCount; -} - inline QVector valueToVector(const QVector3D &value) { return { value.x(), value.y(), value.z() }; @@ -178,7 +148,10 @@ double phaseFromElapsedTime(double t_current_local, later be used as part of the format vector in the formatClipResults() function to remap the channels into the standard W, X, Y, Z order required by QQuaternion. */ -ComponentIndices channelComponentsToIndices(const Channel &channel, int dataType, int offset) +ComponentIndices channelComponentsToIndices(const Channel &channel, + int dataType, + int expectedComponentCount, + int offset) { #if defined Q_COMPILER_UNIFORM_INIT static const QVector standardSuffixes = { 'X', 'Y', 'Z', 'W' }; @@ -192,20 +165,22 @@ ComponentIndices channelComponentsToIndices(const Channel &channel, int dataType switch (dataType) { case QVariant::Quaternion: - return channelComponentsToIndicesHelper(channel, dataType, offset, quaternionSuffixes); + return channelComponentsToIndicesHelper(channel, expectedComponentCount, + offset, quaternionSuffixes); case QVariant::Color: - return channelComponentsToIndicesHelper(channel, dataType, offset, colorSuffixes); + return channelComponentsToIndicesHelper(channel, expectedComponentCount, + offset, colorSuffixes); default: - return channelComponentsToIndicesHelper(channel, dataType, offset, standardSuffixes); + return channelComponentsToIndicesHelper(channel, expectedComponentCount, + offset, standardSuffixes); } } ComponentIndices channelComponentsToIndicesHelper(const Channel &channel, - int dataType, + int expectedComponentCount, int offset, const QVector &suffixes) { - const int expectedComponentCount = componentsForType(dataType); const int actualComponentCount = channel.channelComponents.size(); if (actualComponentCount != expectedComponentCount) { qWarning() << "Data type expects" << expectedComponentCount @@ -329,30 +304,44 @@ ClipResults evaluateClipAtPhase(AnimationClip *clip, float phase) return evaluateClipAtLocalTime(clip, localTime); } +template +Container mapChannelResultsToContainer(const MappingData &mappingData, + const QVector &channelResults) +{ + Container r; + r.reserve(channelResults.size()); + + const ComponentIndices channelIndices = mappingData.channelIndices; + for (const int channelIndex : channelIndices) + r.push_back(channelResults.at(channelIndex)); + + return r; +} + QVariant buildPropertyValue(const MappingData &mappingData, const QVector &channelResults) { - QVariant v; + const int vectorOfFloatType = qMetaTypeId>(); + + if (mappingData.type == vectorOfFloatType) + return QVariant::fromValue(channelResults); switch (mappingData.type) { case QMetaType::Float: case QVariant::Double: { - v = QVariant::fromValue(channelResults[mappingData.channelIndices[0]]); - break; + return QVariant::fromValue(channelResults[mappingData.channelIndices[0]]); } case QVariant::Vector2D: { const QVector2D vector(channelResults[mappingData.channelIndices[0]], channelResults[mappingData.channelIndices[1]]); - v = QVariant::fromValue(vector); - break; + return QVariant::fromValue(vector); } case QVariant::Vector3D: { const QVector3D vector(channelResults[mappingData.channelIndices[0]], channelResults[mappingData.channelIndices[1]], channelResults[mappingData.channelIndices[2]]); - v = QVariant::fromValue(vector); - break; + return QVariant::fromValue(vector); } case QVariant::Vector4D: { @@ -360,8 +349,7 @@ QVariant buildPropertyValue(const MappingData &mappingData, const QVector channelResults[mappingData.channelIndices[1]], channelResults[mappingData.channelIndices[2]], channelResults[mappingData.channelIndices[3]]); - v = QVariant::fromValue(vector); - break; + return QVariant::fromValue(vector); } case QVariant::Quaternion: { @@ -370,24 +358,28 @@ QVariant buildPropertyValue(const MappingData &mappingData, const QVector channelResults[mappingData.channelIndices[2]], channelResults[mappingData.channelIndices[3]]); q.normalize(); - v = QVariant::fromValue(q); - break; + return QVariant::fromValue(q); } case QVariant::Color: { - const QColor color = QColor::fromRgbF(channelResults[mappingData.channelIndices[0]], + const QColor color = + QColor::fromRgbF(channelResults[mappingData.channelIndices[0]], channelResults[mappingData.channelIndices[1]], channelResults[mappingData.channelIndices[2]]); - v = QVariant::fromValue(color); - break; + return QVariant::fromValue(color); } + case QVariant::List: { + const QVariantList results = mapChannelResultsToContainer( + mappingData, channelResults); + return QVariant::fromValue(results); + } default: qWarning() << "Unhandled animation type" << mappingData.type; break; } - return v; + return QVariant(); } QVector preparePropertyChanges(Qt3DCore::QNodeId animatorId, @@ -540,7 +532,11 @@ QVector buildPropertyMappings(const QVector &chann } // Try to find matching channel name and type - const ChannelNameAndType nameAndType = { mapping->channelName(), mapping->type(), mapping->peerId() }; + const ChannelNameAndType nameAndType = { mapping->channelName(), + mapping->type(), + mapping->componentCount(), + mapping->peerId() + }; const int index = channelNamesAndTypes.indexOf(nameAndType); if (index != -1) { // Do we have any animation data for this channel? If not, don't bother @@ -645,7 +641,10 @@ QVector buildRequiredChannelsAndTypes(Handler *handler, case ChannelMapping::ChannelMappingType: case ChannelMapping::CallbackMappingType: { // Get the name and type - const ChannelNameAndType nameAndType{ mapping->channelName(), mapping->type(), mappingId }; + const ChannelNameAndType nameAndType{ mapping->channelName(), + mapping->type(), + mapping->componentCount(), + mappingId }; // Add if not already contained if (!namesAndTypes.contains(nameAndType)) @@ -694,7 +693,7 @@ QVector assignChannelComponentIndices(const QVector &targetCh const int baseIndex = clip->channelComponentBaseIndex(clipChannelIndex); const auto channelIndices = channelComponentsToIndices(clip->channels()[clipChannelIndex], targetChannel.type, + targetChannel.componentCount, baseIndex); std::copy(channelIndices.begin(), channelIndices.end(), formatIt); @@ -909,7 +909,7 @@ QVector defaultValueForChannel(Handler *handler, } // Everything else gets all zeros - const int componentCount = componentsForType(channelDescription.type); + const int componentCount = mapping->componentCount(); result = QVector(componentCount, 0.0f); break; } diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h index 42402c5ec..bded12bd2 100644 --- a/src/animation/backend/animationutils_p.h +++ b/src/animation/backend/animationutils_p.h @@ -134,7 +134,7 @@ struct ChannelNameAndType int jointIndex; Qt3DCore::QNodeId mappingId; JointTransformComponent jointTransformComponent; - float pad; // Unused + int componentCount; static const int invalidIndex = -1; @@ -145,11 +145,12 @@ struct ChannelNameAndType , jointIndex(-1) , mappingId() , jointTransformComponent(NoTransformComponent) - , pad(0) + , componentCount(-1) {} ChannelNameAndType(const QString &_name, int _type, + int componentCount, Qt3DCore::QNodeId _mappingId = Qt3DCore::QNodeId(), int _jointIndex = invalidIndex) : jointName() @@ -158,7 +159,7 @@ struct ChannelNameAndType , jointIndex(_jointIndex) , mappingId(_mappingId) , jointTransformComponent(NoTransformComponent) - , pad(0) + , componentCount(componentCount) {} ChannelNameAndType(const QString &_name, @@ -170,8 +171,20 @@ struct ChannelNameAndType , jointIndex(invalidIndex) , mappingId() , jointTransformComponent(_jointTransformComponent) - , pad(0) - {} + , componentCount(-1) + { + switch (_jointTransformComponent) { + case NoTransformComponent: + break; + case Scale: + case Translation: + componentCount = 3; + break; + case Rotation: + componentCount = 4; + break; + }; + } bool operator==(const ChannelNameAndType &rhs) const { @@ -179,7 +192,8 @@ struct ChannelNameAndType && type == rhs.type && jointIndex == rhs.jointIndex && mappingId == rhs.mappingId - && jointTransformComponent == rhs.jointTransformComponent; + && jointTransformComponent == rhs.jointTransformComponent + && componentCount == rhs.componentCount; } }; @@ -192,7 +206,8 @@ inline QDebug operator<<(QDebug dbg, const ChannelNameAndType &nameAndType) << "mappingId =" << nameAndType.mappingId << "jointIndex =" << nameAndType.jointIndex << "jointName =" << nameAndType.jointName - << "jointTransformComponent =" << nameAndType.jointTransformComponent; + << "jointTransformComponent =" << nameAndType.jointTransformComponent + << "componentCount =" << nameAndType.componentCount; return dbg; } #endif @@ -288,9 +303,6 @@ inline bool isValidNormalizedTime(float t) return !(t < 0.0f) && !(t > 1.0f); } -Q_AUTOTEST_EXPORT -int componentsForType(int type); - Q_AUTOTEST_EXPORT ClipEvaluationData evaluationDataForClip(AnimationClip *clip, const AnimatorEvaluationData &animatorData); @@ -298,11 +310,12 @@ ClipEvaluationData evaluationDataForClip(AnimationClip *clip, Q_AUTOTEST_EXPORT ComponentIndices channelComponentsToIndices(const Channel &channel, int dataType, - int offset = 0); + int expectedComponentCount, + int offset); Q_AUTOTEST_EXPORT ComponentIndices channelComponentsToIndicesHelper(const Channel &channelGroup, - int dataType, + int expectedComponentCount, int offset, const QVector &suffixes); diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp index ecae8bbae..d8572a074 100644 --- a/src/animation/backend/channelmapping.cpp +++ b/src/animation/backend/channelmapping.cpp @@ -55,6 +55,7 @@ ChannelMapping::ChannelMapping() , m_targetId() , m_property() , m_type(static_cast(QVariant::Invalid)) + , m_componentCount(0) , m_propertyName(nullptr) , m_callback(nullptr) , m_callbackFlags(0) @@ -74,6 +75,7 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt m_targetId = data.targetId; m_property = data.property; m_type = data.type; + m_componentCount = data.componentCount; m_propertyName = data.propertyName; m_mappingType = ChannelMappingType; break; @@ -108,6 +110,7 @@ void ChannelMapping::cleanup() m_property.clear(); m_type = static_cast(QVariant::Invalid); m_propertyName = nullptr; + m_componentCount = 0; m_callback = nullptr; m_callbackFlags = 0; m_skeletonId = Qt3DCore::QNodeId(); @@ -128,6 +131,8 @@ void ChannelMapping::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) m_type = change->value().toInt(); else if (change->propertyName() == QByteArrayLiteral("propertyName")) m_propertyName = static_cast(const_cast(change->value().value())); + else if (change->propertyName() == QByteArrayLiteral("componentCount")) + m_componentCount = change->value().toInt(); else if (change->propertyName() == QByteArrayLiteral("callback")) m_callback = static_cast(change->value().value()); else if (change->propertyName() == QByteArrayLiteral("callbackFlags")) diff --git a/src/animation/backend/channelmapping_p.h b/src/animation/backend/channelmapping_p.h index 82de5c7b4..5159adae2 100644 --- a/src/animation/backend/channelmapping_p.h +++ b/src/animation/backend/channelmapping_p.h @@ -93,6 +93,9 @@ public: void setPropertyName(const char *propertyName) { m_propertyName = propertyName; } const char *propertyName() const { return m_propertyName; } + void setComponentCount(int componentCount) { m_componentCount = componentCount; } + int componentCount() const { return m_componentCount; } + void setCallback(QAnimationCallback *callback) { m_callback = callback; } QAnimationCallback *callback() const { return m_callback; } @@ -114,6 +117,7 @@ private: Qt3DCore::QNodeId m_targetId; QString m_property; int m_type; + int m_componentCount; const char *m_propertyName; // TODO: Properties from QCallbackMapping diff --git a/src/animation/frontend/qabstractchannelmapping_p.h b/src/animation/frontend/qabstractchannelmapping_p.h index 1a1de4ba9..2d77ee265 100644 --- a/src/animation/frontend/qabstractchannelmapping_p.h +++ b/src/animation/frontend/qabstractchannelmapping_p.h @@ -60,7 +60,7 @@ namespace Qt3DAnimation { class QAbstractChannelMapping; -class QAbstractChannelMappingPrivate : public Qt3DCore::QNodePrivate +class Q_AUTOTEST_EXPORT QAbstractChannelMappingPrivate : public Qt3DCore::QNodePrivate { public: QAbstractChannelMappingPrivate(); diff --git a/src/animation/frontend/qchannelmapping.cpp b/src/animation/frontend/qchannelmapping.cpp index 0d9150c50..0dbe68c8c 100644 --- a/src/animation/frontend/qchannelmapping.cpp +++ b/src/animation/frontend/qchannelmapping.cpp @@ -47,6 +47,61 @@ QT_BEGIN_NAMESPACE namespace Qt3DAnimation { +namespace { + +template +int componentCountForValue(const T &) +{ + return 0; +} + +template<> +int componentCountForValue>(const QVector &v) +{ + return v.size(); +} + +template<> +int componentCountForValue(const QVariantList &v) +{ + return v.size(); +} + + +int componentCountForType(int type, const QVariant &value) +{ + const int vectorOfFloatTypeId = qMetaTypeId>(); + + if (type == vectorOfFloatTypeId) + return componentCountForValue>(value.value>()); + + switch (type) { + case QMetaType::Float: + case QVariant::Double: + return 1; + + case QVariant::Vector2D: + return 2; + + case QVariant::Vector3D: + case QVariant::Color: + return 3; + + case QVariant::Vector4D: + case QVariant::Quaternion: + return 4; + + case QVariant::List: + return componentCountForValue(value.toList()); + + default: + qWarning() << "Unhandled animation type"; + return 0; + } +} + +} // anonymous + QChannelMappingPrivate::QChannelMappingPrivate() : QAbstractChannelMappingPrivate() , m_channelName() @@ -54,6 +109,7 @@ QChannelMappingPrivate::QChannelMappingPrivate() , m_property() , m_propertyName(nullptr) , m_type(static_cast(QVariant::Invalid)) + , m_componentCount(0) { m_mappingType = QChannelMappingCreatedChangeBase::ChannelMapping; } @@ -63,9 +119,10 @@ QChannelMappingPrivate::QChannelMappingPrivate() Find the type of the property specified on the target node */ -void QChannelMappingPrivate::updatePropertyNameAndType() +void QChannelMappingPrivate::updatePropertyNameTypeAndComponentCount() { int type; + int componentCount = 0; const char *propertyName = nullptr; if (!m_target || m_property.isNull()) { @@ -76,8 +133,8 @@ void QChannelMappingPrivate::updatePropertyNameAndType() QMetaProperty mp = mo->property(propertyIndex); propertyName = mp.name(); type = mp.userType(); + const QVariant currentValue = m_target->property(mp.name()); if (type == QMetaType::QVariant) { - QVariant currentValue = m_target->property(mp.name()); if (currentValue.isValid()) { type = currentValue.userType(); } else { @@ -85,6 +142,7 @@ void QChannelMappingPrivate::updatePropertyNameAndType() "Set a value first in order to be able to determine the type."); } } + componentCount = componentCountForType(type, currentValue); } if (m_type != type) { @@ -98,6 +156,17 @@ void QChannelMappingPrivate::updatePropertyNameAndType() notifyObservers(e); } + if (m_componentCount != componentCount) { + m_componentCount = componentCount; + + // Send update to the backend + Q_Q(QChannelMapping); + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id()); + e->setPropertyName("componentCount"); + e->setValue(QVariant(m_componentCount)); + notifyObservers(e); + } + if (qstrcmp(m_propertyName, propertyName) != 0) { m_propertyName = propertyName; @@ -178,7 +247,7 @@ void QChannelMapping::setTarget(Qt3DCore::QNode *target) d->registerDestructionHelper(d->m_target, &QChannelMapping::setTarget, d->m_target); emit targetChanged(target); - d->updatePropertyNameAndType(); + d->updatePropertyNameTypeAndComponentCount(); } void QChannelMapping::setProperty(const QString &property) @@ -189,7 +258,7 @@ void QChannelMapping::setProperty(const QString &property) d->m_property = property; emit propertyChanged(property); - d->updatePropertyNameAndType(); + d->updatePropertyNameTypeAndComponentCount(); } Qt3DCore::QNodeCreatedChangeBasePtr QChannelMapping::createNodeCreationChange() const @@ -201,6 +270,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QChannelMapping::createNodeCreationChange() data.targetId = Qt3DCore::qIdForNode(d->m_target); data.property = d->m_property; data.type = d->m_type; + data.componentCount = d->m_componentCount; data.propertyName = d->m_propertyName; return creationChange; } diff --git a/src/animation/frontend/qchannelmapping_p.h b/src/animation/frontend/qchannelmapping_p.h index b7de3b821..6a3f1afc5 100644 --- a/src/animation/frontend/qchannelmapping_p.h +++ b/src/animation/frontend/qchannelmapping_p.h @@ -50,25 +50,27 @@ #include #include +#include QT_BEGIN_NAMESPACE namespace Qt3DAnimation { -class QChannelMappingPrivate : public QAbstractChannelMappingPrivate +class Q_AUTOTEST_EXPORT QChannelMappingPrivate : public QAbstractChannelMappingPrivate { public: QChannelMappingPrivate(); Q_DECLARE_PUBLIC(QChannelMapping) - void updatePropertyNameAndType(); + void updatePropertyNameTypeAndComponentCount(); QString m_channelName; Qt3DCore::QNode *m_target; QString m_property; const char *m_propertyName; int m_type; + int m_componentCount; }; struct QChannelMappingData @@ -77,6 +79,7 @@ struct QChannelMappingData Qt3DCore::QNodeId targetId; QString property; int type; + int componentCount; const char *propertyName; }; @@ -85,4 +88,7 @@ struct QChannelMappingData QT_END_NAMESPACE +// Used to define the meta type id +Q_DECLARE_METATYPE(QVector) // LCOV_EXCL_LINE + #endif // QT3DANIMATION_QCHANNELMAPPING_P_H 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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); QVector channelMappings = { channelMapping }; // Create a few channels in the format description ChannelNameAndType rotation = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion), + 4, channelMapping->peerId() }; ChannelNameAndType location = { QLatin1String("Location"), static_cast(QVariant::Vector3D), + 3, channelMapping->peerId() }; ChannelNameAndType baseColor = { QLatin1String("BaseColor"), static_cast(QVariant::Vector3D), + 3, channelMapping->peerId() }; ChannelNameAndType metalness = { QLatin1String("Metalness"), static_cast(QVariant::Double), + 1, channelMapping->peerId() }; ChannelNameAndType roughness = { QLatin1String("Roughness"), static_cast(QVariant::Double), + 1, channelMapping->peerId() }; + ChannelNameAndType morphTargetWeightsList = { QLatin1String("MorphTargetWeightsList"), + static_cast(QVariant::List), + 5, + channelMapping->peerId() }; + ChannelNameAndType morphTargetWeightsVec = { QLatin1String("MorphTargetWeightsVec"), + qMetaTypeId>(), + 6, + channelMapping->peerId() }; QVector 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 channelComponentIndices = { rotationIndices, locationIndices, baseColorIndices, - metalnessIndices, roughnessIndices }; + metalnessIndices, roughnessIndices, morphTargetListIndices, + morphTargetVecIndices }; QVector 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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); auto metalnessMapping = createChannelMapping(handler, QLatin1String("Metalness"), Qt3DCore::QNodeId::createId(), QLatin1String("metalness"), "metalness", - static_cast(QVariant::Double)); + static_cast(QVariant::Double), + 1); auto baseColorMapping = createChannelMapping(handler, QLatin1String("BaseColor"), Qt3DCore::QNodeId::createId(), QLatin1String("baseColor"), "baseColor", - static_cast(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); auto roughnessMapping = createChannelMapping(handler, QLatin1String("Roughness"), Qt3DCore::QNodeId::createId(), QLatin1String("roughness"), "roughness", - static_cast(QVariant::Double)); + static_cast(QVariant::Double), + 1); auto rotationMapping = createChannelMapping(handler, QLatin1String("Rotation"), Qt3DCore::QNodeId::createId(), QLatin1String("rotation"), "rotation", - static_cast(QVariant::Quaternion)); + static_cast(QVariant::Quaternion), + 4); + + auto morphTargetMapping = createChannelMapping(handler, + QLatin1String("MorphTargetWeights"), + Qt3DCore::QNodeId::createId(), + QLatin1String("weights"), + "weights", + static_cast(QVariant::List), + 5); + QVector channelMappings = { locationMapping, metalnessMapping, baseColorMapping, roughnessMapping, - rotationMapping }; + rotationMapping, morphTargetMapping }; // Create a few channels in the format description ChannelNameAndType rotation = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion), + 4, rotationMapping->peerId() }; ChannelNameAndType location = { QLatin1String("Location"), static_cast(QVariant::Vector3D), + 3, locationMapping->peerId() }; ChannelNameAndType baseColor = { QLatin1String("BaseColor"), static_cast(QVariant::Vector3D), + 3, baseColorMapping->peerId() }; ChannelNameAndType metalness = { QLatin1String("Metalness"), static_cast(QVariant::Double), + 1, metalnessMapping->peerId() }; ChannelNameAndType roughness = { QLatin1String("Roughness"), static_cast(QVariant::Double), + 1, roughnessMapping->peerId() }; + ChannelNameAndType morphTarget = { QLatin1String("MorphTargetWeights"), + static_cast(QVariant::List), + 5, + morphTargetMapping->peerId() }; QVector 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 channelComponentIndices = { rotationIndices, locationIndices, baseColorIndices, - metalnessIndices, roughnessIndices }; + metalnessIndices, roughnessIndices, morphTargetIndices }; QVector 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 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(QVariant::Vector3D), + 3, channelMapping->peerId() }; locationDescription.jointIndex = i; locationDescription.jointTransformComponent = Translation; @@ -493,6 +549,7 @@ private Q_SLOTS: ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion), + 4, channelMapping->peerId() }; rotationDescription.jointIndex = i; rotationDescription.jointTransformComponent = Rotation; @@ -500,6 +557,7 @@ private Q_SLOTS: ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast(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(QVariant::List); + mapping.channelIndices = QVector() << 0 << 1 << 2 << 3 << 4 << 5 << 6; + mappingData.push_back(mapping); + channelResults = QVector() << 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"); QTest::addColumn("dataType"); + QTest::addColumn("expectedChannelComponentCount"); QTest::addColumn("offset"); QTest::addColumn>("suffixes"); QTest::addColumn>("expectedResults"); Channel channel; int dataType; + int expectedChannelComponentCount; int offset; QVector suffixes; QVector expectedResults; @@ -1414,20 +1503,22 @@ private Q_SLOTS: // leave 'name' empty dataType = static_cast(QVariant::Vector3D); + expectedChannelComponentCount = 3; offset = 0; // suffixes expected to be ignored expectedResults = (QVector() << 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() << 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(QVariant::Vector3D); + expectedChannelComponentCount = 3; offset = 0; suffixes = (QVector() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector() << 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() << 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(QVariant::Vector2D); + expectedChannelComponentCount = 2; offset = 0; suffixes = (QVector() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector() << 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() << 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(QVariant::Vector4D); + expectedChannelComponentCount = 4; offset = 0; suffixes = (QVector() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector() << 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() << 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(QVariant::Double); + expectedChannelComponentCount = 1; offset = 0; suffixes = (QVector() << 'X' << 'Y' << 'Z' << 'W'); expectedResults = (QVector() << 0); QTest::newRow("double Mass, offset = 0") - << channel << dataType << offset << suffixes << expectedResults; + << channel << dataType << expectedChannelComponentCount + << offset << suffixes << expectedResults; expectedResults.clear(); offset = 5; expectedResults = (QVector() << 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(QVariant::Quaternion); + expectedChannelComponentCount = 4; offset = 0; suffixes = (QVector() << 'W' << 'X' << 'Y' << 'Z'); expectedResults = (QVector() << 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() << 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(QVariant::Quaternion); + expectedChannelComponentCount = 4; offset = 0; suffixes = (QVector() << 'W' << 'X' << 'Y' << 'Z'); expectedResults = (QVector() << 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() << 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(QVariant::Color); + expectedChannelComponentCount = 3; offset = 0; suffixes = (QVector() << 'R' << 'G' << 'B'); expectedResults = (QVector() << 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() << 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(QVariant::List); + expectedChannelComponentCount = 6; + offset = 0; + // suffixes expected to be ignored + expectedResults = (QVector() << 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() << 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>(); + expectedChannelComponentCount = 6; + offset = 0; + // suffixes expected to be ignored + expectedResults = (QVector() << 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() << 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, suffixes); QFETCH(QVector, expectedResults); // WHEN QVector 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"); QTest::addColumn("dataType"); + QTest::addColumn("componentCount"); QTest::addColumn("offset"); QTest::addColumn>("expectedResults"); Channel channel; int dataType; + int componentCount; int offset; QVector expectedResults; @@ -1671,18 +1840,19 @@ private Q_SLOTS: channel.channelComponents[3].name = QLatin1String("Rotation Z"); dataType = static_cast(QVariant::Quaternion); + componentCount = 4; offset = 0; expectedResults = (QVector() << 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() << 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(QVariant::Vector3D); + componentCount = 3; offset = 0; expectedResults = (QVector() << 0 << 1 << 2); QTest::newRow("vec3 location, offset = 0") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); offset = 4; expectedResults = (QVector() << 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(QVariant::Color); + componentCount = 3; offset = 0; expectedResults = (QVector() << 0 << 1 << 2); QTest::newRow("QColor Color, offset = 0") - << channel << dataType << offset << expectedResults; + << channel << dataType << componentCount << offset << expectedResults; expectedResults.clear(); offset = 10; expectedResults = (QVector() << 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, expectedResults); // WHEN QVector 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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); QVector channelMappings; channelMappings.push_back(channelMapping); @@ -2397,6 +2571,7 @@ private Q_SLOTS: QVector expectedResults; expectedResults.push_back({ QLatin1String("Location"), static_cast(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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); auto channelMapping2 = createChannelMapping(handler, QLatin1String("Rotation"), Qt3DCore::QNodeId::createId(), QLatin1String("rotatrion"), "rotation", - static_cast(QVariant::Quaternion)); + static_cast(QVariant::Quaternion), + 4); QVector channelMappings; channelMappings.push_back(channelMapping1); channelMappings.push_back(channelMapping2); @@ -2429,9 +2606,11 @@ private Q_SLOTS: QVector expectedResults; expectedResults.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), + 3, channelMapping1->peerId() }); expectedResults.push_back({ QLatin1String("Rotation"), static_cast(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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); auto channelMapping2 = createChannelMapping(handler, QLatin1String("Rotation"), Qt3DCore::QNodeId::createId(), QLatin1String("rotation"), "rotation", - static_cast(QVariant::Quaternion)); + static_cast(QVariant::Quaternion), + 4); auto channelMapping3 = createChannelMapping(handler, QLatin1String("Location"), Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); auto channelMapping4 = createChannelMapping(handler, QLatin1String("Location"), Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); QVector channelMappings; channelMappings.push_back(channelMapping1); @@ -2481,15 +2664,19 @@ private Q_SLOTS: QVector expectedResults; expectedResults.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), + 3, channelMapping1->peerId() }); expectedResults.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), + 4, channelMapping2->peerId() }); expectedResults.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), + 3, channelMapping3->peerId() }); expectedResults.push_back({ QLatin1String("Location"), static_cast(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(QVariant::Vector3D), + 3, channelMapping->peerId() }; locationDescription.jointIndex = i; locationDescription.jointTransformComponent = Translation; @@ -2517,6 +2705,7 @@ private Q_SLOTS: ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion), + 4, channelMapping->peerId() }; rotationDescription.jointIndex = i; rotationDescription.jointTransformComponent = Rotation; @@ -2524,6 +2713,7 @@ private Q_SLOTS: ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast(QVariant::Vector3D), + 3, channelMapping->peerId() }; scaleDescription.jointIndex = i; scaleDescription.jointTransformComponent = Scale; @@ -2560,7 +2750,7 @@ private Q_SLOTS: { QVector allChannels; - allChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); + allChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); QVector expectedResults; expectedResults.push_back({ 0, 1, 2 }); @@ -2570,8 +2760,8 @@ private Q_SLOTS: { QVector allChannels; - allChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); - allChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }); + allChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }); QVector expectedResults; expectedResults.push_back({ 0, 1, 2 }); @@ -2582,11 +2772,12 @@ private Q_SLOTS: { QVector allChannels; - allChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); - allChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }); - allChannels.push_back({ QLatin1String("BaseColor"), static_cast(QVariant::Vector3D) }); - allChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double) }); - allChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double) }); + allChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }); + allChannels.push_back({ QLatin1String("BaseColor"), static_cast(QVariant::Vector3D), 3 }); + allChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double), 1 }); + allChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double), 1 }); + allChannels.push_back({ QLatin1String("MorphWeights"), static_cast(QVariant::List), 6 }); QVector 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 allChannels; const int jointCount = 4; for (int i = 0; i < jointCount; ++i) { - ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast(QVariant::Vector3D) }; + ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }; locationDescription.jointIndex = i; allChannels.push_back(locationDescription); - ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }; + ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }; rotationDescription.jointIndex = i; allChannels.push_back(rotationDescription); - ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast(QVariant::Vector3D) }; + ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast(QVariant::Vector3D), 3 }; scaleDescription.jointIndex = i; allChannels.push_back(scaleDescription); } @@ -2665,11 +2857,11 @@ private Q_SLOTS: { QVector targetChannels; - targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Base Color"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Base Color"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double), 1 }); QVector targetIndices; targetIndices.push_back({ 0, 1, 2, 3 }); @@ -2703,11 +2895,11 @@ private Q_SLOTS: { QVector targetChannels; - targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Base Color"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Base Color"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double), 1 }); QVector targetIndices; targetIndices.push_back({ 0, 1, 2 }); @@ -2741,11 +2933,11 @@ private Q_SLOTS: { QVector targetChannels; - targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Albedo"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Albedo"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double), 1 }); QVector targetIndices; targetIndices.push_back({ 0, 1, 2, 3 }); @@ -2779,11 +2971,11 @@ private Q_SLOTS: { QVector targetChannels; - targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }); - targetChannels.push_back({ QLatin1String("Albedo"), static_cast(QVariant::Vector3D) }); - targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double) }); - targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double) }); + targetChannels.push_back({ QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }); + targetChannels.push_back({ QLatin1String("Albedo"), static_cast(QVariant::Vector3D), 3 }); + targetChannels.push_back({ QLatin1String("Metalness"), static_cast(QVariant::Double), 1 }); + targetChannels.push_back({ QLatin1String("Roughness"), static_cast(QVariant::Double), 1 }); QVector targetIndices; targetIndices.push_back({ 0, 1, 2 }); @@ -2819,15 +3011,15 @@ private Q_SLOTS: QVector targetChannels; const int jointCount = 4; for (int i = 0; i < jointCount; ++i) { - ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast(QVariant::Vector3D) }; + ChannelNameAndType locationDescription = { QLatin1String("Location"), static_cast(QVariant::Vector3D), 3 }; locationDescription.jointIndex = i; targetChannels.push_back(locationDescription); - ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion) }; + ChannelNameAndType rotationDescription = { QLatin1String("Rotation"), static_cast(QVariant::Quaternion), 4 }; rotationDescription.jointIndex = i; targetChannels.push_back(rotationDescription); - ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast(QVariant::Vector3D) }; + ChannelNameAndType scaleDescription = { QLatin1String("Scale"), static_cast(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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); ChannelNameAndType channelDescription; channelDescription.mappingId = channelMapping->peerId(); channelDescription.type = static_cast(QVariant::Vector3D); @@ -2950,7 +3143,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("rotation"), "rotation", - static_cast(QVariant::Quaternion)); + static_cast(QVariant::Quaternion), + 4); ChannelNameAndType channelDescription; channelDescription.mappingId = channelMapping->peerId(); channelDescription.type = static_cast(QVariant::Quaternion); @@ -2966,7 +3160,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("scale"), "scale", - static_cast(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); ChannelNameAndType channelDescription; channelDescription.mappingId = channelMapping->peerId(); channelDescription.type = static_cast(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 #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(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(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(QVariant::Invalid)); QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); } @@ -171,6 +192,34 @@ private Q_SLOTS: // THEN QCOMPARE(backendMapping.property(), property); + // WHEN + updateChange = QSharedPointer::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("type"); + updateChange->setValue(QVariant(static_cast(QVariant::Vector3D))); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.type(), static_cast(QVariant::Vector3D)); + + // WHEN + updateChange = QSharedPointer::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("componentCount"); + updateChange->setValue(4); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.componentCount(), 4); + + // WHEN + const char *testName = "883"; + updateChange = QSharedPointer::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("propertyName"); + updateChange->setValue(QVariant::fromValue(reinterpret_cast(const_cast(testName)))); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.propertyName(), testName); + // WHEN const auto skeletonId = Qt3DCore::QNodeId::createId(); updateChange = QSharedPointer::create(Qt3DCore::QNodeId()); 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(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); QVector channelMappings; channelMappings.push_back(channelMapping); @@ -188,7 +191,8 @@ private Q_SLOTS: Qt3DCore::QNodeId::createId(), QLatin1String("translation"), "translation", - static_cast(QVariant::Vector3D)); + static_cast(QVariant::Vector3D), + 3); QVector 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 #include +#include #include #include #include @@ -36,8 +37,49 @@ #include #include #include +#include #include +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 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 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(nullptr)); QCOMPARE(mapping.property(), QString()); + + const Qt3DAnimation::QChannelMappingPrivate *d = + static_cast( + Qt3DAnimation::QChannelMappingPrivate::get(&mapping)); + + QCOMPARE(d->m_type, static_cast(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(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(QVariant::Vector3D)); + QCOMPARE(data.componentCount, 3); } } @@ -187,6 +240,7 @@ private Q_SLOTS: // GIVEN TestArbiter arbiter; Qt3DAnimation::QChannelMapping mapping; + QScopedPointer 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(); + QCOMPARE(arbiter.events.size(), 4); + auto change = arbiter.events.takeFirst().staticCast(); QCOMPARE(change->propertyName(), "property"); QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); QCOMPARE(change->value().toString(), mapping.property()); + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), static_cast(QVariant::Vector3D)); + + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "componentCount"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), 3); + + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "propertyName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QVERIFY(qstrcmp(reinterpret_cast(change->value().value()), "scale") == 0); + arbiter.events.clear(); // WHEN @@ -255,8 +324,88 @@ private Q_SLOTS: // THEN QCOMPARE(arbiter.events.size(), 0); } + } + void checkPropertyUpdateNameTypeAndComponentCount_data() + { + QTest::addColumn("propertyName"); + QTest::addColumn("value"); + QTest::addColumn("expectedType"); + QTest::addColumn("expectedComponentCount"); + + QTest::newRow("float") << QByteArrayLiteral("floatProperty") << QVariant(1.0f) << static_cast(QMetaType::Float) << 1; + QTest::newRow("vec2") << QByteArrayLiteral("vec2Property") << QVariant(QVector2D(1.0f, 1.0f)) << static_cast(QVariant::Vector2D) << 2; + QTest::newRow("vec3") << QByteArrayLiteral("vec3Property") << QVariant(QVector3D(1.0f, 1.0f, 1.0f)) << static_cast(QVariant::Vector3D) << 3; + QTest::newRow("vec4") << QByteArrayLiteral("vec4Property") << QVariant(QVector4D(1.0f, 1.0f, 1.0f, 1.0f)) << static_cast(QVariant::Vector4D) << 4; + QTest::newRow("quaternion") << QByteArrayLiteral("quaternionProperty") << QVariant(QQuaternion(1.0f, 1.0f, 1.0f, 1.0f)) << static_cast(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(QVariant::List) << 5; + + QVector vec(8); + QTest::newRow("vector") << QByteArrayLiteral("vecProperty") << QVariant::fromValue(vec) << qMetaTypeId() << 8; } + + void checkPropertyUpdateNameTypeAndComponentCount() + { + // GIVEN + QFETCH(QByteArray, propertyName); + QFETCH(QVariant, value); + QFETCH(int, expectedType); + QFETCH(int, expectedComponentCount); + + TestArbiter arbiter; + Qt3DAnimation::QChannelMapping mapping; + QScopedPointer 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(); + QCOMPARE(change->propertyName(), propertyName.constData()); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value(), value); + + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "property"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toString(), mapping.property()); + + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), expectedType); + + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "componentCount"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), expectedComponentCount); + + change = arbiter.events.takeFirst().staticCast(); + QCOMPARE(change->propertyName(), "propertyName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QVERIFY(qstrcmp(reinterpret_cast(change->value().value()), propertyName.constData()) == 0); + + arbiter.events.clear(); + + // WHEN + mapping.setProperty(QString::fromLatin1(propertyName)); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } + }; QTEST_MAIN(tst_QChannelMapping) -- cgit v1.2.3