summaryrefslogtreecommitdiffstats
path: root/src/runtime/q3dsanimationmanager.cpp
diff options
context:
space:
mode:
authorChristian Strømme <christian.stromme@qt.io>2018-02-21 15:36:52 +0100
committerChristian Stromme <christian.stromme@qt.io>2018-02-27 10:38:22 +0000
commit4166e5e2e052313eb44d5d1c88aad340c1e0137f (patch)
tree26af58fff9d4dad15bba0639d849ea3af06627f2 /src/runtime/q3dsanimationmanager.cpp
parent714e67009f63ade540ed7ca7389feca1d6a72c2f (diff)
Add support for keyframes with easing values
Change-Id: I9765912d02b128c8c90419f355894c8031cd53d3 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/runtime/q3dsanimationmanager.cpp')
-rw-r--r--src/runtime/q3dsanimationmanager.cpp110
1 files changed, 81 insertions, 29 deletions
diff --git a/src/runtime/q3dsanimationmanager.cpp b/src/runtime/q3dsanimationmanager.cpp
index 08fe8ab..0e32e6f 100644
--- a/src/runtime/q3dsanimationmanager.cpp
+++ b/src/runtime/q3dsanimationmanager.cpp
@@ -307,49 +307,101 @@ void Q3DSAnimationManager::updateAnimationHelper(const AnimationTrackListMap<T *
};
QHash<QString, ChannelComponents> channelData;
- for (const Q3DSAnimationTrack *animTrack : it.value()) {
- const QStringList prop = animTrack->property().split('.');
- if (prop.count() < 1)
- continue;
- const QString &propertyName = prop[0];
- if (!animatables->contains(propertyName))
- continue;
-
- Animatable *animMeta = &(*animatables)[propertyName];
- ChannelComponents &c(channelData[animMeta->name]);
- c.meta = *animMeta;
-
- for (const Q3DSAnimationTrack::KeyFrame &kf : animTrack->keyFrames()) {
- Qt3DAnimation::QKeyFrame qkf;
-#if 0 // ### not supported yet, fix Qt3D first
- switch (animTrack->type()) {
+ static const auto buildKeyFrames = [](const Q3DSAnimationTrack::KeyFrameList &keyFrames,
+ Q3DSAnimationTrack::AnimationType type,
+ ChannelComponents &channelComponent,
+ const QStringList &prop) {
+
+ const auto end = keyFrames.constEnd();
+ const auto begin = keyFrames.constBegin();
+ auto it = begin;
+ Qt3DAnimation::QKeyFrame qkf;
+ while (it != end) {
+ switch (type) {
case Q3DSAnimationTrack::EaseInOut:
- qkf = Qt3DAnimation::QKeyFrame(QVector2D(kf.time, kf.value), kf.easeIn / 100.0f, kf.easeOut / 100.0f);
+ {
+ // c1 (t, v) -> first/right control point (ease in).
+ // Easing value (for t) is between 0 and 1, where 0 is the current keyframe's start time
+ // and 1 is the next keyframe's start time.
+ // c1's value is always the same as the current keyframe's value, as that's the
+ // only option we support at the moment.
+
+ // c2 (t, v) -> second/left control point (ease out).
+ // Easing value (for t) is between 0 and 1, where 0 is the next keyframe's start time
+ // and 1 is the current keyframe's start time.
+ // c2's value is always the same as the next keyframe's value, as that's the only
+ // option we support at the moment.
+
+ // Get normalized value [0..1]
+ const float easeIn = qBound(0.0f, (it->easeIn / 100.0f) / 2.0f, 1.0f);
+ const float easeOut = qBound(0.0f, (it->easeOut / 100.0f) / 2.0f, 1.0f);
+
+ // Next and previous keyframes, if any.
+ const auto next = ((it + 1) != end) ? (it + 1) : it;
+ const auto previous = (it != begin) ? (it - 1) : it;
+
+ // p0
+ const QVector2D coordinates(it->time, it->value);
+
+ // c1
+ float dt = (next->time - it->time);
+ const float p1t = qBound(it->time, it->time + (dt * easeIn), next->time);
+ const float p1v = it->value;
+ const QVector2D rightControlPoint(p1t, p1v);
+
+ // c2
+ dt = (it->time - previous->time);
+ const float p2t = qBound(previous->time, it->time - (dt * easeOut), it->time);
+ const float p2v = it->value;
+ const QVector2D leftControlPoint(p2t, p2v);
+
+ qkf = Qt3DAnimation::QKeyFrame(coordinates, leftControlPoint, rightControlPoint);
+ }
break;
case Q3DSAnimationTrack::Bezier:
- qkf = Qt3DAnimation::QKeyFrame(QVector2D(kf.time, kf.value),
- QVector2D(kf.c1time, kf.c1value / 100.0f),
- QVector2D(kf.c2time, kf.c2value / 100.0f));
+ qkf = Qt3DAnimation::QKeyFrame(QVector2D(it->time, it->value),
+ QVector2D(it->c1time, it->c1value / 100.0f),
+ QVector2D(it->c2time, it->c2value / 100.0f));
break;
-
- default: // linear interpolation
- qkf = Qt3DAnimation::QKeyFrame(QVector2D(kf.time, kf.value));
+ default:
+ qkf = Qt3DAnimation::QKeyFrame(QVector2D(it->time, it->value));
break;
}
-#else
- qkf = Qt3DAnimation::QKeyFrame(QVector2D(kf.time, kf.value));
-#endif
+
if (prop.count() == 1) {
- c.comps[0].appendKeyFrame(qkf);
+ channelComponent.comps[0].appendKeyFrame(qkf);
} else {
int idx = componentSuffixToIndex(prop[1]);
if (idx < 0) {
- qWarning("Unknown component suffix %s for animated property %s", qPrintable(prop[1]), qPrintable(propertyName));
+ qWarning("Unknown component suffix %s for animated property %s", qPrintable(prop[1]), qPrintable(prop[0]));
continue;
}
- c.comps[idx].appendKeyFrame(qkf);
+ channelComponent.comps[idx].appendKeyFrame(qkf);
}
+ ++it;
}
+ };
+
+ const auto &animatonTracks = it.value();
+ for (const Q3DSAnimationTrack *animationTrack : animatonTracks) {
+ const QStringList prop = animationTrack->property().split('.');
+ if (prop.count() < 1)
+ continue;
+
+ const QString &propertyName = prop[0];
+ if (!animatables->contains(propertyName))
+ continue;
+
+ const auto &keyFrames = animationTrack->keyFrames();
+ if (keyFrames.isEmpty())
+ continue;
+
+ Animatable *animMeta = &(*animatables)[propertyName];
+ ChannelComponents &channelComponent(channelData[animMeta->name]);
+ channelComponent.meta = *animMeta;
+
+ const auto type = animationTrack->type();
+ buildKeyFrames(keyFrames, type, channelComponent, prop);
}
static const bool animSetupDebug = qEnvironmentVariableIntValue("Q3DS_DEBUG") >= 2;