summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2017-03-20 13:42:53 +0000
committerSean Harmer <sean.harmer@kdab.com>2017-03-25 14:23:28 +0000
commit1929b3e48c0a327e7a741275d6d4847b72ddf704 (patch)
tree703782cb36b3979929b0d440550bfe337bb925a7
parentb18d39153453e6e2cab9e6c75bd2991aa25d0397 (diff)
Add a function to build list of unique channel names and types
This will be needed to construct the data layout for blend trees. Change-Id: I0b11076f5ecd55cfad094d864f3f8270841fc62a Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/animation/backend/animationutils.cpp31
-rw-r--r--src/animation/backend/animationutils_p.h15
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp126
3 files changed, 172 insertions, 0 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp
index 8b2ba6821..d79b412fd 100644
--- a/src/animation/backend/animationutils.cpp
+++ b/src/animation/backend/animationutils.cpp
@@ -335,6 +335,37 @@ QVector<MappingData> buildPropertyMappings(Handler *handler,
return mappingDataVec;
}
+QVector<ChannelNameAndType> buildRequiredChannelsAndTypes(Handler *handler,
+ const ChannelMapper *mapper)
+{
+ ChannelMappingManager *mappingManager = handler->channelMappingManager();
+ const QVector<Qt3DCore::QNodeId> mappingIds = mapper->mappingIds();
+
+ // Reserve enough storage assuming each mapping is for a different channel.
+ // May be overkill but avoids potential for multiple allocations
+ QVector<ChannelNameAndType> namesAndTypes;
+ namesAndTypes.reserve(mappingIds.size());
+
+ // Iterate through the mappings and add ones not already used by an earlier mapping.
+ // We could add them all then sort and remove duplicates. However, our approach has the
+ // advantage of keeping the blend tree format more consistent with the mapping
+ // orderings which will have better cache locality when generating events.
+ for (const Qt3DCore::QNodeId mappingId : mappingIds) {
+ // Get the mapping object
+ ChannelMapping *mapping = mappingManager->lookupResource(mappingId);
+ Q_ASSERT(mapping);
+
+ // 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);
+ }
+
+ return namesAndTypes;
+}
+
QVector<Qt3DCore::QNodeId> gatherValueNodesToEvaluate(Handler *handler,
Qt3DCore::QNodeId blendTreeRootId)
{
diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h
index 705e37c34..dd600c207 100644
--- a/src/animation/backend/animationutils_p.h
+++ b/src/animation/backend/animationutils_p.h
@@ -102,6 +102,17 @@ struct ClipEvaluationData
typedef QVector<float> ClipResults;
+struct ChannelNameAndType
+{
+ QString name;
+ int type;
+
+ bool operator==(const ChannelNameAndType &rhs) const
+ {
+ return name == rhs.name && type == rhs.type;
+ }
+};
+
template<typename Animator>
AnimatorEvaluationData evaluationDataForAnimator(Animator animator, qint64 globalTime)
{
@@ -159,6 +170,10 @@ QVector<MappingData> buildPropertyMappings(Handler *handler,
const ChannelMapper *mapper);
Q_AUTOTEST_EXPORT
+QVector<ChannelNameAndType> buildRequiredChannelsAndTypes(Handler *handler,
+ const ChannelMapper *mapper);
+
+Q_AUTOTEST_EXPORT
double localTimeFromGlobalTime(double t_global, double t_start_global,
double playbackRate, double duration,
int loopCount, int &currentLoop);
diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp
index 6f0c998e6..a96f7d2d2 100644
--- a/tests/auto/animation/animationutils/tst_animationutils.cpp
+++ b/tests/auto/animation/animationutils/tst_animationutils.cpp
@@ -59,6 +59,7 @@ Q_DECLARE_METATYPE(AnimatorEvaluationData)
Q_DECLARE_METATYPE(ClipEvaluationData)
Q_DECLARE_METATYPE(ClipAnimator *)
Q_DECLARE_METATYPE(BlendedClipAnimator *)
+Q_DECLARE_METATYPE(QVector<ChannelNameAndType>)
namespace {
@@ -1953,6 +1954,131 @@ private Q_SLOTS:
for (int i = 0; i < actualResults.size(); ++i)
QCOMPARE(actualResults[i], expectedResults[i]);
}
+
+ void checkBuildRequiredChannelsAndTypes_data()
+ {
+ QTest::addColumn<Handler *>("handler");
+ QTest::addColumn<ChannelMapper *>("mapper");
+ QTest::addColumn<QVector<ChannelNameAndType>>("expectedResults");
+
+ {
+ 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);
+
+ auto channelMapper = createChannelMapper(handler,
+ QVector<Qt3DCore::QNodeId>() << channelMapping->peerId());
+
+ QVector<ChannelNameAndType> expectedResults;
+ expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) });
+
+ QTest::addRow("Location, vec3") << handler << channelMapper << expectedResults;
+ }
+
+ {
+ auto handler = new Handler();
+ auto channelMapping1 = createChannelMapping(handler,
+ QLatin1String("Location"),
+ Qt3DCore::QNodeId::createId(),
+ QLatin1String("translation"),
+ "translation",
+ static_cast<int>(QVariant::Vector3D));
+ auto channelMapping2 = createChannelMapping(handler,
+ QLatin1String("Rotation"),
+ Qt3DCore::QNodeId::createId(),
+ QLatin1String("rotatrion"),
+ "rotation",
+ static_cast<int>(QVariant::Quaternion));
+ QVector<ChannelMapping *> channelMappings;
+ channelMappings.push_back(channelMapping1);
+ channelMappings.push_back(channelMapping2);
+
+ QVector<Qt3DCore::QNodeId> channelMappingIds
+ = (QVector<Qt3DCore::QNodeId>()
+ << channelMapping1->peerId()
+ << channelMapping2->peerId());
+ auto channelMapper = createChannelMapper(handler, channelMappingIds);
+
+ QVector<ChannelNameAndType> expectedResults;
+ expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) });
+ expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) });
+
+ QTest::addRow("Multiple unique channels") << handler << channelMapper << expectedResults;
+ }
+
+ {
+ auto handler = new Handler();
+ auto channelMapping1 = createChannelMapping(handler,
+ QLatin1String("Location"),
+ Qt3DCore::QNodeId::createId(),
+ QLatin1String("translation"),
+ "translation",
+ static_cast<int>(QVariant::Vector3D));
+ auto channelMapping2 = createChannelMapping(handler,
+ QLatin1String("Rotation"),
+ Qt3DCore::QNodeId::createId(),
+ QLatin1String("rotation"),
+ "rotation",
+ static_cast<int>(QVariant::Quaternion));
+ auto channelMapping3 = createChannelMapping(handler,
+ QLatin1String("Location"),
+ Qt3DCore::QNodeId::createId(),
+ QLatin1String("translation"),
+ "translation",
+ static_cast<int>(QVariant::Vector3D));
+ auto channelMapping4 = createChannelMapping(handler,
+ QLatin1String("Location"),
+ Qt3DCore::QNodeId::createId(),
+ QLatin1String("translation"),
+ "translation",
+ static_cast<int>(QVariant::Vector3D));
+
+ QVector<ChannelMapping *> channelMappings;
+ channelMappings.push_back(channelMapping1);
+ channelMappings.push_back(channelMapping2);
+ channelMappings.push_back(channelMapping3);
+ channelMappings.push_back(channelMapping4);
+
+ QVector<Qt3DCore::QNodeId> channelMappingIds
+ = (QVector<Qt3DCore::QNodeId>()
+ << channelMapping1->peerId()
+ << channelMapping2->peerId()
+ << channelMapping3->peerId()
+ << channelMapping4->peerId());
+ auto channelMapper = createChannelMapper(handler, channelMappingIds);
+
+ QVector<ChannelNameAndType> expectedResults;
+ expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D) });
+ expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion) });
+
+ QTest::addRow("Multiple channels with repeats") << handler << channelMapper << expectedResults;
+ }
+ }
+
+ void checkBuildRequiredChannelsAndTypes()
+ {
+ // GIVEN
+ QFETCH(Handler *, handler);
+ QFETCH(ChannelMapper *, mapper);
+ QFETCH(QVector<ChannelNameAndType>, expectedResults);
+
+ // WHEN
+ const QVector<ChannelNameAndType> actualResults = buildRequiredChannelsAndTypes(handler, mapper);
+
+ // THEN
+ QCOMPARE(actualResults.size(), expectedResults.size());
+ for (int i = 0; i < actualResults.size(); ++i)
+ QCOMPARE(actualResults[i], expectedResults[i]);
+
+ // Cleanup
+ delete handler;
+ }
};
QTEST_MAIN(tst_AnimationUtils)