summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-08-26 14:53:20 +0100
committerSean Harmer <sean.harmer@kdab.com>2017-09-02 18:10:31 +0000
commitbbb9b6c25650fc17868c47d9c82501f9068dd158 (patch)
treee70e6658ad0efc1f654a1045caa5a39d3c6a31fa
parent9a14388cd5f3e509658e8ec1a1c582f9215f53ca (diff)
Extend buildRequiredChannelsAndTypes to handle indexed targets
Specifically, this is needed for animating joints of a skeleton. If we later find other such indexed targets we can rename the jointIndex member to something more generic. For now this naming helps with reasoning as there are many kinds of index in play within the animation system. Change-Id: I348f255ee622aa11f26e5a3c1055bf5c12071c17 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/animation/backend/animationutils.cpp42
-rw-r--r--src/animation/backend/animationutils_p.h19
-rw-r--r--src/animation/backend/channelmapping.cpp3
-rw-r--r--src/animation/backend/channelmapping_p.h11
-rw-r--r--src/animation/backend/skeleton_p.h7
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp42
6 files changed, 118 insertions, 6 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp
index e33a31b7b..8fe31bc24 100644
--- a/src/animation/backend/animationutils.cpp
+++ b/src/animation/backend/animationutils.cpp
@@ -458,12 +458,44 @@ QVector<ChannelNameAndType> buildRequiredChannelsAndTypes(Handler *handler,
ChannelMapping *mapping = mappingManager->lookupResource(mappingId);
Q_ASSERT(mapping);
- // Get the name and type
- const ChannelNameAndType nameAndType{ mapping->channelName(), mapping->type() };
+ switch (mapping->mappingType()) {
+ case ChannelMapping::ChannelMappingType:
+ case ChannelMapping::CallbackMappingType: {
+ // Get the name and type
+ const ChannelNameAndType nameAndType{ mapping->channelName(), mapping->type() };
- // Add if not already contained
- if (!namesAndTypes.contains(nameAndType))
- namesAndTypes.push_back(nameAndType);
+ // Add if not already contained
+ if (!namesAndTypes.contains(nameAndType))
+ namesAndTypes.push_back(nameAndType);
+
+ break;
+ }
+
+ case ChannelMapping::SkeletonMappingType: {
+ // Add an entry for each scale/rotation/translation property of each joint index
+ // of the target skeleton.
+ const QVector<ChannelNameAndType> jointProperties
+ = { { QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) },
+ { QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) },
+ { QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D) } };
+ Skeleton *skeleton = handler->skeletonManager()->lookupResource(mapping->skeletonId());
+ const int jointCount = skeleton->jointCount();
+ for (int jointIndex = 0; jointIndex < jointCount; ++jointIndex) {
+ const int propertyCount = jointProperties.size();
+ for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) {
+ // Get the name, type and index
+ ChannelNameAndType nameAndType = jointProperties[propertyIndex];
+ nameAndType.jointIndex = jointIndex;
+
+ // Add if not already contained
+ if (!namesAndTypes.contains(nameAndType))
+ namesAndTypes.push_back(nameAndType);
+ }
+ }
+
+ break;
+ }
+ }
}
return namesAndTypes;
diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h
index bcc50fce2..7fcd9ead5 100644
--- a/src/animation/backend/animationutils_p.h
+++ b/src/animation/backend/animationutils_p.h
@@ -100,10 +100,27 @@ struct ChannelNameAndType
{
QString name;
int type;
+ int jointIndex;
+
+ static const int invalidIndex = -1;
+
+ ChannelNameAndType()
+ : name()
+ , type(-1)
+ , jointIndex(-1)
+ {}
+
+ ChannelNameAndType(const QString &_name, int _type, int _jointIndex = invalidIndex)
+ : name(_name)
+ , type(_type)
+ , jointIndex(_jointIndex)
+ {}
bool operator==(const ChannelNameAndType &rhs) const
{
- return name == rhs.name && type == rhs.type;
+ return name == rhs.name
+ && type == rhs.type
+ && jointIndex == rhs.jointIndex;
}
};
diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp
index bf5be8383..417c10a1a 100644
--- a/src/animation/backend/channelmapping.cpp
+++ b/src/animation/backend/channelmapping.cpp
@@ -74,6 +74,7 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt
m_propertyName = data.propertyName;
m_callback = data.callback;
m_callbackFlags = data.callbackFlags;
+ m_mappingType = ChannelMappingType;
break;
}
@@ -81,11 +82,13 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt
const auto typedChange = qSharedPointerCast<QChannelMappingCreatedChange<QSkeletonMappingData>>(change);
const auto &data = typedChange->data;
m_skeletonId = data.skeletonId;
+ m_mappingType = SkeletonMappingType;
break;
}
case QChannelMappingCreatedChangeBase::CallbackMapping: {
// TODO: Refactor callback support out of QChannelMapping and into its own type
+ m_mappingType = CallbackMappingType;
break;
}
}
diff --git a/src/animation/backend/channelmapping_p.h b/src/animation/backend/channelmapping_p.h
index 1be89cc88..5cebbaf55 100644
--- a/src/animation/backend/channelmapping_p.h
+++ b/src/animation/backend/channelmapping_p.h
@@ -66,6 +66,12 @@ class Handler;
class Q_AUTOTEST_EXPORT ChannelMapping : public BackendNode
{
public:
+ enum MappingType {
+ ChannelMappingType = 0,
+ SkeletonMappingType,
+ CallbackMappingType
+ };
+
ChannelMapping();
void cleanup();
@@ -96,6 +102,9 @@ public:
void setSkeletonId(Qt3DCore::QNodeId skeletonId) { m_skeletonId = skeletonId; }
Qt3DCore::QNodeId skeletonId() const { return m_skeletonId; }
+ void setMappingType(MappingType mappingType) { m_mappingType = mappingType; }
+ MappingType mappingType() const { return m_mappingType; }
+
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
@@ -112,6 +121,8 @@ private:
// Properties from QSkeletonMapping
Qt3DCore::QNodeId m_skeletonId;
+
+ MappingType m_mappingType;
};
} // namespace Animation
diff --git a/src/animation/backend/skeleton_p.h b/src/animation/backend/skeleton_p.h
index 0674a28a1..19da98261 100644
--- a/src/animation/backend/skeleton_p.h
+++ b/src/animation/backend/skeleton_p.h
@@ -64,7 +64,14 @@ public:
void cleanup();
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ int jointCount() const { return m_jointLocalPoses.size(); }
+
#if defined(QT_BUILD_INTERNAL)
+ void setJointCount(int jointCount)
+ {
+ m_jointNames.resize(jointCount);
+ m_jointLocalPoses.resize(jointCount);
+ }
void setJointNames(const QVector<QString> &names) { m_jointNames = names; }
QVector<QString> jointNames() const { return m_jointNames; }
void setJointLocalPoses(const QVector<Qt3DCore::Sqt> &localPoses) { m_jointLocalPoses = localPoses; }
diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp
index 14181b893..ae68381f0 100644
--- a/tests/auto/animation/animationutils/tst_animationutils.cpp
+++ b/tests/auto/animation/animationutils/tst_animationutils.cpp
@@ -154,6 +154,18 @@ public:
channelMapping->setPropertyName(propertyName);
channelMapping->setChannelName(channelName);
channelMapping->setType(type);
+ channelMapping->setMappingType(ChannelMapping::ChannelMappingType);
+ return channelMapping;
+ }
+
+ ChannelMapping *createChannelMapping(Handler *handler,
+ const Qt3DCore::QNodeId skeletonId)
+ {
+ auto channelMappingId = Qt3DCore::QNodeId::createId();
+ ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId);
+ setPeerId(channelMapping, channelMappingId);
+ channelMapping->setSkeletonId(skeletonId);
+ channelMapping->setMappingType(ChannelMapping::SkeletonMappingType);
return channelMapping;
}
@@ -247,6 +259,15 @@ public:
return node;
}
+ Skeleton *createSkeleton(Handler *handler, int jointCount)
+ {
+ auto skeletonId = Qt3DCore::QNodeId::createId();
+ Skeleton *skeleton = handler->skeletonManager()->getOrCreateResource(skeletonId);
+ setPeerId(skeleton, skeletonId);
+ skeleton->setJointCount(jointCount);
+ return skeleton;
+ }
+
private Q_SLOTS:
void checkBuildPropertyMappings_data()
{
@@ -2509,6 +2530,27 @@ private Q_SLOTS:
QTest::addRow("Multiple channels with repeats") << handler << channelMapper << expectedResults;
}
+
+ {
+ auto handler = new Handler();
+ const int jointCount = 10;
+ auto skeleton = createSkeleton(handler, jointCount);
+ auto channelMapping = createChannelMapping(handler, skeleton->peerId());
+ QVector<ChannelMapping *> channelMappings;
+ channelMappings.push_back(channelMapping);
+
+ auto channelMapper = createChannelMapper(handler,
+ QVector<Qt3DCore::QNodeId>() << channelMapping->peerId());
+
+ QVector<ChannelNameAndType> expectedResults;
+ for (int i = 0; i < jointCount; ++i) {
+ expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i });
+ expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i });
+ expectedResults.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i });
+ }
+
+ QTest::addRow("Skeleton, 10 joints") << handler << channelMapper << expectedResults;
+ }
}
void checkBuildRequiredChannelsAndTypes()