summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/animation/backend/animationutils.cpp49
-rw-r--r--src/animation/backend/animationutils_p.h9
-rw-r--r--src/animation/backend/skeleton.cpp9
-rw-r--r--src/animation/backend/skeleton_p.h17
-rw-r--r--src/animation/frontend/qanimationaspect.cpp1
-rw-r--r--src/core/transforms/sqt_p.h1
6 files changed, 85 insertions, 1 deletions
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp
index 83a9a8426..a1224f69a 100644
--- a/src/animation/backend/animationutils.cpp
+++ b/src/animation/backend/animationutils.cpp
@@ -48,6 +48,7 @@
#include <QtGui/qquaternion.h>
#include <QtGui/qcolor.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qvarlengtharray.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <numeric>
@@ -292,13 +293,45 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim
bool finalFrame)
{
QVector<Qt3DCore::QSceneChangePtr> changes;
+ QVarLengthArray<Skeleton *, 4> dirtySkeletons;
+
// Iterate over the mappings
for (const MappingData &mappingData : mappingDataVec) {
if (!mappingData.propertyName)
continue;
+
// Build the new value from the channel/fcurve evaluation results
const QVariant v = buildPropertyValue(mappingData, channelResults);
- if (v.isValid()) {
+ if (!v.isValid())
+ continue;
+
+ // TODO: Avoid wrapping joint transform components up in a variant, just
+ // to immediately unwrap them again. Refactor buildPropertyValue() to call
+ // helper functions that we can call directly here for joints.
+ if (mappingData.skeleton && mappingData.jointIndex != -1) {
+ // Remember that this skeleton is dirty. We will ask each dirty skeleton
+ // to send its set of local poses to observers below.
+ if (!dirtySkeletons.contains(mappingData.skeleton))
+ dirtySkeletons.push_back(mappingData.skeleton);
+
+ switch (mappingData.jointTransformComponent) {
+ case MappingData::Scale:
+ mappingData.skeleton->setJointScale(mappingData.jointIndex, v.value<QVector3D>());
+ break;
+
+ case MappingData::Rotation:
+ mappingData.skeleton->setJointRotation(mappingData.jointIndex, v.value<QQuaternion>());
+ break;
+
+ case MappingData::Translation:
+ mappingData.skeleton->setJointTranslation(mappingData.jointIndex, v.value<QVector3D>());
+ break;
+
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else {
// Construct a property update change, set target, property and delivery options
auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(mappingData.targetId);
e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
@@ -311,6 +344,8 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim
}
}
+ for (const auto skeleton : dirtySkeletons)
+ skeleton->sendLocalPoses();
// If it's the final frame, notify the frontend that we've stopped
if (finalFrame) {
@@ -415,6 +450,7 @@ QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &chann
// Populate the data we need, easy stuff first
MappingData mappingData;
mappingData.targetId = mapping->skeletonId();
+ mappingData.skeleton = mapping->skeleton();
const int propertyCount = jointProperties.size();
for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) {
@@ -430,6 +466,17 @@ QVector<MappingData> buildPropertyMappings(const QVector<ChannelMapping*> &chann
mappingData.type = nameAndType.type;
mappingData.channelIndices = channelComponentIndices[index];
mappingData.jointIndex = jointIndex;
+
+ // Convert property name for joint transform components to
+ // an enumerated type so we can avoid the string comparisons
+ // when sending the change events after evaluation.
+ if (qstrcmp(mappingData.propertyName, "scale") == 0)
+ mappingData.jointTransformComponent = MappingData::Scale;
+ else if (qstrcmp(mappingData.propertyName, "rotation") == 0)
+ mappingData.jointTransformComponent = MappingData::Rotation;
+ else if (qstrcmp(mappingData.propertyName, "translation") == 0)
+ mappingData.jointTransformComponent = MappingData::Translation;
+
mappingDataVec.push_back(mappingData);
}
}
diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h
index 5d84f54b0..a225e9311 100644
--- a/src/animation/backend/animationutils_p.h
+++ b/src/animation/backend/animationutils_p.h
@@ -71,8 +71,17 @@ typedef QVector<int> ComponentIndices;
struct MappingData
{
+ enum JointTransformComponent {
+ NoTransformComponent = 0,
+ Scale,
+ Rotation,
+ Translation
+ };
+
Qt3DCore::QNodeId targetId;
+ Skeleton *skeleton = nullptr;
int jointIndex = -1;
+ JointTransformComponent jointTransformComponent = NoTransformComponent;
const char *propertyName;
QAnimationCallback *callback;
QAnimationCallback::Flags callbackFlags;
diff --git a/src/animation/backend/skeleton.cpp b/src/animation/backend/skeleton.cpp
index a920e2473..dcfaf55e7 100644
--- a/src/animation/backend/skeleton.cpp
+++ b/src/animation/backend/skeleton.cpp
@@ -96,6 +96,15 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
BackendNode::sceneChangeEvent(e);
}
+void Skeleton::sendLocalPoses()
+{
+ auto e = QPropertyUpdatedChangePtr::create(peerId());
+ e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes);
+ e->setPropertyName("localPoses");
+ e->setValue(QVariant::fromValue(m_jointLocalPoses));
+ notifyObservers(e);
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/skeleton_p.h b/src/animation/backend/skeleton_p.h
index 19da98261..e26e276d9 100644
--- a/src/animation/backend/skeleton_p.h
+++ b/src/animation/backend/skeleton_p.h
@@ -66,6 +66,23 @@ public:
int jointCount() const { return m_jointLocalPoses.size(); }
+ void setJointScale(int jointIndex, const QVector3D &scale)
+ {
+ m_jointLocalPoses[jointIndex].scale = scale;
+ }
+
+ void setJointRotation(int jointIndex, const QQuaternion &rotation)
+ {
+ m_jointLocalPoses[jointIndex].rotation = rotation;
+ }
+
+ void setJointTranslation(int jointIndex, const QVector3D &translation)
+ {
+ m_jointLocalPoses[jointIndex].translation = translation;
+ }
+
+ void sendLocalPoses();
+
#if defined(QT_BUILD_INTERNAL)
void setJointCount(int jointCount)
{
diff --git a/src/animation/frontend/qanimationaspect.cpp b/src/animation/frontend/qanimationaspect.cpp
index 14a0c4f8c..9b23a7b1d 100644
--- a/src/animation/frontend/qanimationaspect.cpp
+++ b/src/animation/frontend/qanimationaspect.cpp
@@ -95,6 +95,7 @@ QAnimationAspect::QAnimationAspect(QAnimationAspectPrivate &dd, QObject *parent)
Q_D(QAnimationAspect);
qRegisterMetaType<Qt3DAnimation::QAnimationClipLoader*>();
qRegisterMetaType<Qt3DAnimation::QChannelMapper*>();
+ qRegisterMetaType<QVector<Qt3DCore::Sqt>>();
registerBackendType<QAbstractAnimationClip>(
QSharedPointer<Animation::NodeFunctor<Animation::AnimationClip, Animation::AnimationClipLoaderManager>>::create(d->m_handler.data(),
diff --git a/src/core/transforms/sqt_p.h b/src/core/transforms/sqt_p.h
index 262e3a645..5fdefccc8 100644
--- a/src/core/transforms/sqt_p.h
+++ b/src/core/transforms/sqt_p.h
@@ -101,6 +101,7 @@ struct JointNamesAndLocalPoses
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QVector<Qt3DCore::Sqt>)
Q_DECLARE_METATYPE(Qt3DCore::JointNamesAndLocalPoses)
#endif // QT3DCORE_SQT_P_H