summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Strømme <christian.stromme@qt.io>2018-12-12 17:02:25 +0100
committerChristian Stromme <christian.stromme@qt.io>2019-01-08 15:42:25 +0000
commit7ffe0aff86fc78cb6c673f1b6041bfacd4e481b6 (patch)
tree979912c9acc59ecd138a200a19bad849c588c82e /src
parent5de34146f23df4aad5c3d6ffcc01b1915b3b34f8 (diff)
Some improvments to the new animation code
- The animation tracks for a slide are now stored in one continuous block of memory. - The master slide has its own animator, which means it can technically be run on its own. - Building the animation tracks are now much more simple and clean, but it does now assume that the tracks in the UIP are grouped correctly. - +++ Change-Id: Ib3a87975e6014170fefecdc909d50b6ea81929cd Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/runtime/animator/q3dsanimator.cpp103
-rw-r--r--src/runtime/animator/q3dsanimator_p.h92
-rw-r--r--src/runtime/slideplayerng/q3dsanimationmanagerng.cpp216
-rw-r--r--src/runtime/slideplayerng/q3dsslideplayerng.cpp29
-rw-r--r--src/runtime/slideplayerng/q3dsslideplayerng_p.h2
5 files changed, 207 insertions, 235 deletions
diff --git a/src/runtime/animator/q3dsanimator.cpp b/src/runtime/animator/q3dsanimator.cpp
index b5d53f6..fed5985 100644
--- a/src/runtime/animator/q3dsanimator.cpp
+++ b/src/runtime/animator/q3dsanimator.cpp
@@ -35,8 +35,8 @@
QT_BEGIN_NAMESPACE
-bool evaluateAnimation(const Q3DSNodeAnimation::KeyFrameList::const_iterator &cbegin,
- const Q3DSNodeAnimation::KeyFrameList::const_iterator &cend,
+bool evaluateAnimation(const Q3DSAnimator::AnimationDataList::const_iterator &cbegin,
+ const Q3DSAnimator::AnimationDataList::const_iterator &cend,
float time,
float *value)
{
@@ -46,40 +46,40 @@ bool evaluateAnimation(const Q3DSNodeAnimation::KeyFrameList::const_iterator &cb
if (size < 2) {
if (size == 0)
return false;
- *value = cbegin->value;
+ *value = cbegin->keyFrameData.value;
} else {
- if (time >= cend->time) {
- *value = cend->value;
- } else if (time <= cbegin->time) {
- *value = cbegin->value;
+ if (time >= cend->keyFrameData.time) {
+ *value = cend->keyFrameData.value;
+ } else if (time <= cbegin->keyFrameData.time) {
+ *value = cbegin->keyFrameData.value;
} else {
- const auto foundIt = std::find_if(cbegin, cend, [time](const Q3DSAnimationUtils::KeyFrame &kf) { return (kf.time >= time); });
+ const auto foundIt = std::find_if(cbegin, cend, [time](const Q3DSAnimationData &data) { return (data.keyFrameData.time >= time); });
const auto previous = (foundIt != cbegin) ? (foundIt - 1) : foundIt;
- *value = Q3DSAnimationUtils::evaluateBezierKeyframe(time, (*previous), (*foundIt));
+ Q_ASSERT(foundIt->type == Q3DSAnimationData::DataType::KeyFrame && previous->type == Q3DSAnimationData::DataType::KeyFrame);
+ *value = Q3DSAnimationUtils::evaluateBezierKeyframe(time, (*previous).keyFrameData, (*foundIt).keyFrameData);
}
}
return !qFuzzyCompare(*value, oldValue);
}
-void syncDirtyProperties(const QVector<Q3DSNodeAnimation::DirtyProperty> &dirtyProperties)
+void syncDirtyProperties(const Q3DSAnimator::DirtyPropertyList &dirtyProperties)
{
Q3DSGraphObject *target;
qint8 changeFlags;
qint16 pid;
QVariant::Type type;
for (const auto &dirtyProperty : dirtyProperties) {
- target = dirtyProperty.target;
+ target = dirtyProperty.target->target;
Q_ASSERT(target);
- const auto &property = dirtyProperty.it;
- pid = property->pid;
- type = property->type;
+ pid = dirtyProperty.target->pid;
+ type = dirtyProperty.target->type;
if (Q_UNLIKELY(pid == -1 || type == QVariant::Invalid)) {
qCWarning(lcAnim, "Property update failed for id %d and with type %d", pid, type);
return;
}
- const auto &vec3 = property->vec3;
- changeFlags = property->changeFlags;
+ const auto &vec3 = dirtyProperty.value;
+ changeFlags = dirtyProperty.target->changeFlags;
static const auto toTargetVariant = [](QVariant::Type type, const QVector3D &v) {
switch (int(type)) {
case QVariant::Double:
@@ -108,55 +108,40 @@ void syncDirtyProperties(const QVector<Q3DSNodeAnimation::DirtyProperty> &dirtyP
}
}
-void evaluateNodesAt(const Q3DSAnimator::AnimationList::const_iterator &animBegin,
- const Q3DSAnimator::AnimationList::const_iterator &animEnd,
+void evaluateNodesAt(Q3DSAnimator::AnimationDataList::const_iterator cit,
+ const Q3DSAnimator::AnimationDataList::const_iterator cend,
float time,
Q3DSAnimator::DirtyPropertyList *dirtyList,
bool sync)
{
- using Components = Q3DSNodeAnimation::Property::Components;
-
- auto animIt = animBegin;
- Q3DSGraphObject *target = nullptr;
- while (animIt != animEnd) {
- target = animIt->target;
- Q_ASSERT(target);
- const auto &properties = animIt->properties;
- auto propertiesIt = properties.cbegin();
- const auto &propertiesEnd = properties.cend();
- const auto &keyFrames = animIt->keyFrames;
- while (propertiesIt != propertiesEnd) {
- auto &v = propertiesIt->vec3;
- const auto &components = propertiesIt->componentFlags;
- if (Q_UNLIKELY(components == Components::None)) {
- qWarning("Property animation without no component specified!");
- continue;
- }
- // If sync is set to true we mark all as dirty to make sure the target property and the
- // animation node values are in sync.
- bool changed = sync;
- if (components & Components::X) {
- const auto cbegin = keyFrames.cbegin() + propertiesIt->components[0].offset;
- const auto cend = cbegin + propertiesIt->components[0].size - 1;
- changed |= evaluateAnimation(cbegin, cend, time, &v[0]);
- }
- if (components & Components::Y) {
- const auto cbegin = keyFrames.cbegin() + propertiesIt->components[1].offset;
- const auto cend = cbegin + propertiesIt->components[1].size - 1;
- changed |= evaluateAnimation(cbegin, cend, time, &v[1]);
- }
- if (components & Components::Z) {
- const auto cbegin = keyFrames.cbegin() + propertiesIt->components[2].offset;
- const auto cend = cbegin + propertiesIt->components[2].size - 1;
- changed |= evaluateAnimation(cbegin, cend, time, &v[2]);
- }
+ QVector3D vec3;
+ // If sync is set to true we mark all as dirty to make sure the target property and the
+ // animation node values are in sync.
+ bool changed = sync;
+ while (cit != cend) {
+ if (cit->type == Q3DSAnimationData::DataType::Component) {
+ const auto &componentData = cit->componentData;
+ const auto &component = componentData.component;
+
+ const auto cKfBegin = cit + 1;
+ const auto cKfEnd = cKfBegin + componentData.size - 1;
+ Q_ASSERT(cKfBegin->type == Q3DSAnimationData::DataType::KeyFrame
+ && cKfEnd->type == Q3DSAnimationData::DataType::KeyFrame);
+ changed |= evaluateAnimation(cKfBegin, cKfEnd, time, &componentData.value);
+ vec3[static_cast<int>(component)] = componentData.value;
+ cit = cKfEnd + 1; // Next should be either a component or a target (last kf + 1)
+ Q_ASSERT(cit->type == Q3DSAnimationData::DataType::Component
+ || cit->type == Q3DSAnimationData::DataType::Target);
+ }
+ if (cit->type == Q3DSAnimationData::DataType::Target) {
if (changed)
- dirtyList->push_back({propertiesIt, target});
-
- ++propertiesIt;
+ dirtyList->push_back({&cit->targetData, std::move(vec3)});
+ changed = sync; // reset the changed value
+ ++cit;
}
- ++animIt;
+
+ Q_ASSERT(cit == cend || cit->type == Q3DSAnimationData::DataType::Component);
}
}
@@ -168,7 +153,7 @@ void Q3DSAnimator::goToTime(float time, bool sync)
localTime = time;
dirtyList.clear();
- evaluateNodesAt(animationList.cbegin(), animationList.cend(), localTime, &dirtyList, sync);
+ evaluateNodesAt(animationDataList.cbegin(), animationDataList.cend(), localTime, &dirtyList, sync);
syncDirtyProperties(dirtyList);
if (timeChangeCallback)
diff --git a/src/runtime/animator/q3dsanimator_p.h b/src/runtime/animator/q3dsanimator_p.h
index 6a61c5c..53659af 100644
--- a/src/runtime/animator/q3dsanimator_p.h
+++ b/src/runtime/animator/q3dsanimator_p.h
@@ -53,50 +53,54 @@ QT_BEGIN_NAMESPACE
class Q3DSGraphObject;
class Q3DSSlide;
-struct Q3DSNodeAnimation
+struct Q3DSAnimationData
{
- using KeyFrameList = QVector<Q3DSAnimationUtils::KeyFrame>;
-
- struct Property
+ enum class DataType : quint8
{
- enum class Components : quint8 {
- None,
- X = 0x1,
- Y = 0x2,
- Z = 0x4,
- Dynamic = 0x10
- };
- struct Component
- {
- // Offset and length into the KeyFrameList
- quint16 offset;
- quint16 size;
- } components[3];
- mutable QVector3D vec3;
- qint16 pid;
- qint8 changeFlags;
- Components componentFlags;
- QVariant::Type type;
+ Component,
+ KeyFrame,
+ Target,
+ };
+ enum class Component : quint8 {
+ X,
+ Y,
+ Z
+ };
+ struct ComponentData {
+ mutable float value;
+ quint16 size;
+ Component component;
+ bool dynamic;
};
- using PropertyList = QVector<Property>;
- using PropertyIterator = Q3DSNodeAnimation::PropertyList::const_iterator;
+ using KeyFrameData = Q3DSAnimationUtils::KeyFrame;
- struct DirtyProperty
- {
- PropertyIterator it;
+ struct TargetData {
Q3DSGraphObject *target;
+ QVariant::Type type;
+ qint16 pid;
+ qint8 changeFlags;
+ };
+
+ union {
+ ComponentData componentData;
+ KeyFrameData keyFrameData;
+ TargetData targetData;
};
- Q3DSGraphObject *target;
- PropertyList properties;
- KeyFrameList keyFrames; // Should be ordered (x, y, z, x, ...)
+ DataType type;
+};
+
+Q_DECLARE_TYPEINFO(Q3DSAnimationData, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Q3DSAnimationData::KeyFrameData, Q_MOVABLE_TYPE);
+
+struct Q3DSDirtyAnimationValue
+{
+ const Q3DSAnimationData::TargetData *target;
+ QVector3D value;
};
-Q_DECLARE_TYPEINFO(Q3DSNodeAnimation, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(Q3DSNodeAnimation::DirtyProperty, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(Q3DSNodeAnimation::Property, Q_MOVABLE_TYPE);
-Q_DECLARE_TYPEINFO(Q3DSNodeAnimation::Property::Component, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Q3DSDirtyAnimationValue, Q_MOVABLE_TYPE);
struct Q3DSAnimator
{
@@ -110,10 +114,10 @@ struct Q3DSAnimator
bool active = false;
PlayMode playMode = PlayMode::StopAtEnd;
- using AnimationList = QVector<Q3DSNodeAnimation>;
- AnimationList animationList;
+ using AnimationDataList = QVector<Q3DSAnimationData>;
+ AnimationDataList animationDataList;
- using DirtyPropertyList = QVector<Q3DSNodeAnimation::DirtyProperty>;
+ using DirtyPropertyList = QVector<Q3DSDirtyAnimationValue>;
DirtyPropertyList dirtyList;
using EosCallback = std::function<void()>;
@@ -128,17 +132,13 @@ struct Q3DSAnimator
void advance(float dt);
};
-inline constexpr quint8 operator &(const Q3DSNodeAnimation::Property::Components &l,
- const Q3DSNodeAnimation::Property::Components &r)
-{ return (static_cast<quint8>(l) & static_cast<quint8>(r)); }
-
-bool evaluateAnimation(const Q3DSNodeAnimation::KeyFrameList::const_iterator &cbegin,
- const Q3DSNodeAnimation::KeyFrameList::const_iterator &cend,
+bool evaluateAnimation(const Q3DSAnimator::AnimationDataList::const_iterator &cbegin,
+ const Q3DSAnimator::AnimationDataList::const_iterator &cend,
float time,
float *value);
-void syncDirtyProperties(const QVector<Q3DSNodeAnimation::DirtyProperty> &dirtyProperties);
-void evaluateNodesAt(const Q3DSAnimator::AnimationList::const_iterator &animBegin,
- const Q3DSAnimator::AnimationList::const_iterator &animEnd,
+void syncDirtyProperties(const Q3DSAnimator::DirtyPropertyList &dirtyProperties);
+void evaluateNodesAt(Q3DSAnimator::AnimationDataList::const_iterator cit,
+ const Q3DSAnimator::AnimationDataList::const_iterator cend,
float time,
Q3DSAnimator::DirtyPropertyList *dirtyList,
bool sync = false);
diff --git a/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp b/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp
index 396c826..116cb0d 100644
--- a/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp
+++ b/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp
@@ -62,15 +62,15 @@ static QVector3D toVector3D(const QVariant &qv)
}
};
-static Q3DSNodeAnimation::KeyFrameList buildKeyFramesForTrack(const Q3DSAnimationTrack &track)
+static void addKeyFramesForTrack(const Q3DSAnimationTrack &track, Q3DSAnimator::AnimationDataList *kfl)
{
const auto type = track.type();
const auto &keyFrames = track.keyFrames();
const auto end = keyFrames.constEnd();
const auto begin = keyFrames.constBegin();
auto it = begin;
- Q3DSNodeAnimation::KeyFrameList kfl;
- kfl.reserve(keyFrames.size());
+ Q3DSAnimationData keyFrameData;
+ keyFrameData.type = Q3DSAnimationData::DataType::KeyFrame;
while (it != end) {
switch (type) {
case Q3DSAnimationTrack::EaseInOut:
@@ -109,199 +109,175 @@ static Q3DSNodeAnimation::KeyFrameList buildKeyFramesForTrack(const Q3DSAnimatio
const float p2t = qBound(previous->time, it->time - (dt * easeOut * adjustment), it->time);
const float p2v = it->value;
- kfl.append({it->time, it->value, {p1t, p1v}, {p2t, p2v}});
+ keyFrameData.keyFrameData = {it->time, it->value, {p1t, p1v}, {p2t, p2v}};
+ kfl->push_back(keyFrameData);
}
break;
case Q3DSAnimationTrack::Bezier:
- kfl.append({it->time, it->value, {it->c1time, it->c1value / 100.0f}, {it->c2time, it->c2value / 100.0f}});
+ keyFrameData.keyFrameData = {it->time, it->value, {it->c1time, it->c1value / 100.0f}, {it->c2time, it->c2value / 100.0f}};
+ kfl->push_back(keyFrameData);
break;
default:
- kfl.append({it->time, it->value, {it->time, it->value}, {it->time, it->value}});
+ keyFrameData.keyFrameData = {it->time, it->value, {it->time, it->value}, {it->time, it->value}};
+ kfl->push_back(keyFrameData);
break;
}
++it;
}
- return kfl;
}
void Q3DSAnimationManagerNg::buildSlideAnimation(Q3DSSlide *slide, bool rebuild)
{
- // This code is ridicules, but it will do for now
+ if (!slide)
+ return;
+
Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>();
Q_ASSERT(data);
if (!data->animatorNg)
data->animatorNg = new Q3DSAnimator;
- if (!rebuild && !data->animatorNg->animationList.isEmpty())
+ if (!rebuild && !data->animatorNg->animationDataList.isEmpty())
return;
- auto &propertyTracks = data->animatorNg->animationList;
- propertyTracks.clear();
- using ComponentTracks = QVarLengthArray<const Q3DSAnimationTrack *, 4>;
- using PropTracks = QHash<QString, ComponentTracks>;
- QHash<Q3DSGraphObject *, PropTracks> targetMap;
- // TODO: Instead of using the property string we can use the property idx
- // and the component id should be retrieveable from the track as an enum.
-
- const auto buildHelper = [&targetMap](Q3DSSlide *slide) {
- if (!slide)
- return;
-
- const bool isMaster = !slide->parent();
- const auto tracks = slide->animations();
-
- for (const auto &track : tracks) {
- auto target = track.target();
- auto foundIt = targetMap.find(target);
- const auto split = track.property().split(QChar::fromLatin1('.'));
- const auto propertyStr = split.at(0);
- const int idx = (split.size() > 1) ? componentSuffixToIndex(*split.at(1).toLatin1()) : 0;
- Q_ASSERT(idx >= 0 && idx <= 3);
- if (foundIt == targetMap.constEnd()) {
- ComponentTracks c { nullptr, nullptr, nullptr, nullptr };
- c.insert(idx, &track);
- targetMap.insert(target, {{propertyStr, c}});
- } else {
- auto foundIt2 = foundIt->find(propertyStr);
- if (foundIt2 == foundIt->cend()) {
- ComponentTracks c { nullptr, nullptr, nullptr, nullptr };
- c.insert(idx, &track);
- foundIt->insert(propertyStr, c);
- } else {
- if (isMaster && foundIt2->at(idx))
- continue;
- foundIt2->insert(idx, &track);
- }
- }
- }
- };
-
- buildHelper(slide);
- buildHelper(static_cast<Q3DSSlide *>(slide->parent()));
-
- Q3DSNodeAnimation nodeAnimation; // TODO: Reserve
- for (auto targetIt = targetMap.cbegin(); targetIt != targetMap.cend(); ++targetIt) {
- const auto target = targetIt.key();
- nodeAnimation.target = target;
- nodeAnimation.properties.clear();
- nodeAnimation.keyFrames.clear();
- for (auto propTrack = targetIt->cbegin(); propTrack != targetIt->cend(); ++propTrack) {
- Q3DSNodeAnimation::Property nodeProperty;
- const auto &property = propTrack.key();
- const auto &atracks = propTrack.value();
- const int pid = Q3DSGraphObject::indexOfProperty(target, property.toLatin1());
+ auto &animationDataList = data->animatorNg->animationDataList;
+ animationDataList.clear();
+
+ // NOTE: the assumption here is that tracks are ordered as, e.g., rotation.x, rotation.y...
+ const auto &tracks = slide->animations();
+ auto cit = tracks.cbegin();
+ const auto cend = tracks.cend();
+ while (cit != cend) {
+ const auto &track = *cit;
+ const auto prop = track.property().split('.');
+ const auto comp = (prop.size() > 1) ? Q3DSAnimationData::Component(componentSuffixToIndex(*prop.at(1).toLatin1()))
+ : Q3DSAnimationData::Component::X;
+
+ // Structure: | Cx | K1..Kn | Cy | K1..Kn | Cz | K1..Kn | T | ... |
+ // 1. Create component data
+ Q3DSAnimationData component;
+ component.type = Q3DSAnimationData::DataType::Component;
+ component.componentData.component = comp;
+ component.componentData.size = quint16(track.keyFrames().size());
+ component.componentData.dynamic = track.isDynamic();
+ animationDataList.push_back(component);
+
+ // 2. Add key frames for component track
+ addKeyFramesForTrack(track, &animationDataList);
+
+ // 3. Add the target data (if we're at end, the target changes, or the property changes
+ if ((cit + 1) == cend || (cit->target() != (cit + 1)->target() || !(cit + 1)->property().startsWith(prop[0]))) {
+ Q3DSAnimationData targetData;
+ targetData.type = Q3DSAnimationData::DataType::Target;
+ targetData.targetData.target = track.target();
+
+ const int pid = Q3DSGraphObject::indexOfProperty(track.target(), prop[0].toLatin1());
Q_ASSERT(pid != -1);
- QVector3D vec3;
- quint8 compFlag = 0;
- for (int compPos = 0; compPos != 3; ++compPos) {
- const auto trackPtr = atracks.at(compPos);
- if (!trackPtr)
- continue;
-
- const auto componentKeyFrames = buildKeyFramesForTrack(*trackPtr);
- // Get the start value, which is the value of the first kf.
- if (componentKeyFrames.size() > 0)
- vec3[compPos] = componentKeyFrames.at(0).value;
- compFlag |= (1 << compPos);
- const int offset = nodeAnimation.keyFrames.size();
- const int size = componentKeyFrames.size();
- nodeProperty.components[compPos].size = quint16(size);
- nodeProperty.components[compPos].offset = quint16(offset);
- nodeAnimation.keyFrames += componentKeyFrames;
- if (trackPtr->isDynamic())
- compFlag |= static_cast<quint8>(Q3DSNodeAnimation::Property::Components::Dynamic);
- }
-
- const int changeFlag = targetIt.key()->mapChangeFlags({{property}});
- nodeProperty.vec3 = vec3;
- nodeProperty.changeFlags = qint8(changeFlag);
- nodeProperty.componentFlags = static_cast<Q3DSNodeAnimation::Property::Components>(compFlag);
- nodeProperty.pid = qint16(pid);
+ targetData.targetData.pid = qint16(pid);
+ targetData.targetData.changeFlags = qint8(track.target()->mapChangeFlags({{prop[0]}}));
// TODO: Find a nice solution for getting the type...
- nodeProperty.type = Q3DSGraphObject::readProperty(target, pid).type();
- nodeAnimation.properties.push_back(std::move(nodeProperty));
+ const auto type = Q3DSGraphObject::readProperty(track.target(), pid).type();
+ Q_ASSERT(type != QVariant::Invalid);
+ targetData.targetData.type = type;
+ animationDataList.push_back(targetData);
}
-
- data->animatorNg->animationList.push_back(std::move(nodeAnimation));
+ ++cit;
}
}
void Q3DSAnimationManagerNg::updateDynamicKeyFrames(Q3DSSlide *slide)
{
+ if (!slide)
+ return;
+
Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>();
Q_ASSERT(data);
if (!data->animatorNg)
return;
- auto &animations = data->animatorNg->animationList;
- for (auto &animNode : animations) {
- using Component = Q3DSNodeAnimation::Property::Components;
- for (const auto &property : qAsConst(animNode.properties)) {
- const auto vec3 = toVector3D(Q3DSGraphObject::readProperty(animNode.target, property.pid));
- if ((property.componentFlags & Component::Dynamic) == 0)
- continue;
- if (property.componentFlags & Component::X) {
- auto &kf = *(animNode.keyFrames.begin() + property.components[0].offset);
- kf.value = kf.c1.value = kf.c2.value = vec3[0];
- }
- if (property.componentFlags & Component::Y) {
- auto &kf = *(animNode.keyFrames.begin() + property.components[1].offset);
- kf.value = kf.c1.value = kf.c2.value = vec3[1];
- }
- if (property.componentFlags & Component::Z) {
- auto &kf = *(animNode.keyFrames.begin() + property.components[2].offset);
- kf.value = kf.c1.value = kf.c2.value = vec3[2];
+ auto &animationDataList = data->animatorNg->animationDataList;
+ auto it = animationDataList.begin();
+ const auto end = animationDataList.end();
+ while (it != end) {
+ if (it->type == Q3DSAnimationData::DataType::Component && (it->componentData.dynamic)) {
+ // find the target and the components that needs to be updated
+ QVarLengthArray<Q3DSAnimationData *, 3> components;
+ const auto targetIt = std::find_if(it, end, [&components](Q3DSAnimationData &data) {
+ if (data.type == Q3DSAnimationData::DataType::Target)
+ return true;
+ else if (data.type == Q3DSAnimationData::DataType::Component && data.componentData.dynamic)
+ components.push_back(&data);
+ return false;
+ });
+
+ Q_ASSERT(targetIt != end && targetIt->type == Q3DSAnimationData::DataType::Target);
+ const auto vec3 = toVector3D(Q3DSGraphObject::readProperty(targetIt->targetData.target, targetIt->targetData.pid));
+ // Update the first kf on each track
+ for (auto &component : components) {
+ if (component == nullptr)
+ break;
+
+ Q_ASSERT(component->type == Q3DSAnimationData::DataType::Component);
+ if (component->componentData.size < 1) // No key-frames...
+ continue;
+
+ auto kfData = (component + 1);
+ Q_ASSERT(kfData->type == Q3DSAnimationData::DataType::KeyFrame);
+ auto &kf = kfData->keyFrameData;
+ kf.value = kf.c1.value = kf.c2.value = vec3[static_cast<int>(component->componentData.component)];
+
}
+ it = targetIt;
}
+ ++it;
}
}
void Q3DSAnimationManagerNg::setActive(Q3DSSlide *slide, bool active)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->active = active;
}
void Q3DSAnimationManagerNg::goToTime(Q3DSSlide *slide, float timeMs, bool sync)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->goToTime(timeMs / 1000.f, sync);
}
void Q3DSAnimationManagerNg::setRate(Q3DSSlide *slide, float rate)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->rate = rate;
}
void Q3DSAnimationManagerNg::setDuration(Q3DSSlide *slide, float durationMs)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->duration = durationMs / 1000.f;
}
void Q3DSAnimationManagerNg::setPlayMode(Q3DSSlide *slide, Q3DSSlide::PlayMode mode)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->playMode = mode;
}
void Q3DSAnimationManagerNg::setEosCallback(Q3DSSlide *slide, Q3DSAnimator::EosCallback cb)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->eosCallback = cb;
}
void Q3DSAnimationManagerNg::setTimeChangeCallback(Q3DSSlide *slide, Q3DSAnimator::TimeChangeCallback cb)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->timeChangeCallback = cb;
}
void Q3DSAnimationManagerNg::advance(Q3DSSlide *slide, float dtMs)
{
- if (slide->attached<Q3DSSlideAttached>()->animatorNg)
+ if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg)
slide->attached<Q3DSSlideAttached>()->animatorNg->advance(dtMs / 1000.f);
}
diff --git a/src/runtime/slideplayerng/q3dsslideplayerng.cpp b/src/runtime/slideplayerng/q3dsslideplayerng.cpp
index cdba58c..1791384 100644
--- a/src/runtime/slideplayerng/q3dsslideplayerng.cpp
+++ b/src/runtime/slideplayerng/q3dsslideplayerng.cpp
@@ -185,6 +185,8 @@ void Q3DSSlidePlayerNg::advanceFrame(float dt)
// NOTE: dt is in ms!
Q3DSSlide *slide = m_data.slideDeck->currentSlide();
+ if (slide->parent())
+ Q3DSAnimationManagerNg::advance(static_cast<Q3DSSlide *>(slide->parent()), dt);
Q3DSAnimationManagerNg::advance(slide, dt);
forAllSlideComponents(static_cast<Q3DSSlide *>(slide->parent()), [dt](Q3DSComponentNode *component) {
component->currentSlide()->attached<Q3DSSlideAttached>()->slidePlayer->advanceFrame(dt);
@@ -464,7 +466,7 @@ void Q3DSSlidePlayerNg::reset()
setInternalState(PlayerState::Idle);
}
-void Q3DSSlidePlayerNg::changeState(Q3DSSlide *slide, Q3DSSlidePlayerNg::PlayerState state, bool parentChanged = false)
+void Q3DSSlidePlayerNg::changeState(Q3DSSlide *slide, Q3DSSlidePlayerNg::PlayerState state)
{
// The scene state is the slide and the player state is the state of the animation
if (!slide)
@@ -506,10 +508,6 @@ void Q3DSSlidePlayerNg::changeState(Q3DSSlide *slide, Q3DSSlidePlayerNg::PlayerS
case PlayerState::Ready: // Reset to the initial state
Q3DSAnimationManagerNg::setActive(slide, false);
// Hide all objects
- if (parentChanged) {
- setObjectVisibility(static_cast<Q3DSSlide *>(slide->parent()), -1.0f);
- forAllSlideComponents(static_cast<Q3DSSlide *>(slide->parent()), resetComponentState);
- }
setObjectVisibility(slide, -1.0f);
forAllSlideComponents(slide, resetComponentState);
break;
@@ -552,8 +550,11 @@ void Q3DSSlidePlayerNg::setInternalState(Q3DSSlidePlayerNg::PlayerState newState
if (activeSlide != currentSlide) {
// If the slide changed, stop the previous slide first (skip if slide is already ready or stopped)
// This is usually the case when e.g., changing slides, as the old slide will be stopped first.
- if (activeSlide && (m_data.state != PlayerState::Stopped && m_data.state != PlayerState::Ready))
- changeState(activeSlide, PlayerState::Ready, parentChanged);
+ if (activeSlide && (m_data.state != PlayerState::Stopped && m_data.state != PlayerState::Ready)) {
+ if (parentChanged)
+ changeState(static_cast<Q3DSSlide *>(activeSlide), PlayerState::Ready);
+ changeState(activeSlide, PlayerState::Ready);
+ }
// TODO:
// 1. Build all animation once (might be option to release them, but we'll get back to that).
@@ -570,6 +571,7 @@ void Q3DSSlidePlayerNg::setInternalState(Q3DSSlidePlayerNg::PlayerState newState
m_component->setCurrentSlide(currentSlide);
// Ensure that the slide's animation tracks are built
+ Q3DSAnimationManagerNg::buildSlideAnimation(static_cast<Q3DSSlide *>(currentSlide->parent()));
Q3DSAnimationManagerNg::buildSlideAnimation(currentSlide);
// If this is a real slide change (previous slide != null and != current), then
// we need to update the dynamic key frames
@@ -578,6 +580,7 @@ void Q3DSSlidePlayerNg::setInternalState(Q3DSSlidePlayerNg::PlayerState newState
// All set, now apply the property changes for this slide. Note that the values might
// be out of sync after this, but once the slide changes to playing/paused, the values
// will be synced to match the values from the animator (based on the first kf values).
+ processPropertyChanges(static_cast<Q3DSSlide *>(currentSlide->parent()));
processPropertyChanges(currentSlide);
Q_ASSERT(currentSlide->attached<Q3DSSlideAttached>()->animatorNg);
@@ -588,6 +591,11 @@ void Q3DSSlidePlayerNg::setInternalState(Q3DSSlidePlayerNg::PlayerState newState
m_data.position = 0.0f;
// Update duration, rate, and playmode
+ // If the current slide has a parent, then the parent inherits its child's mode, duration, etc.
+ Q3DSAnimationManagerNg::setPlayMode(static_cast<Q3DSSlide *>(currentSlide->parent()), currentSlide->playMode());
+ Q3DSAnimationManagerNg::setDuration(static_cast<Q3DSSlide *>(currentSlide->parent()), m_data.duration);
+ Q3DSAnimationManagerNg::setRate(static_cast<Q3DSSlide *>(currentSlide->parent()), m_data.playbackRate);
+
Q3DSAnimationManagerNg::setPlayMode(currentSlide, currentSlide->playMode());
Q3DSAnimationManagerNg::setDuration(currentSlide, m_data.duration);
Q3DSAnimationManagerNg::setRate(currentSlide, m_data.playbackRate);
@@ -601,6 +609,7 @@ void Q3DSSlidePlayerNg::setInternalState(Q3DSSlidePlayerNg::PlayerState newState
sendPositionChanged(time);
});
+ changeState(static_cast<Q3DSSlide *>(currentSlide->parent()), newState);
changeState(currentSlide, newState);
if (newState != PlayerState::Idle) {
@@ -612,8 +621,10 @@ void Q3DSSlidePlayerNg::setInternalState(Q3DSSlidePlayerNg::PlayerState newState
if (m_data.state != newState) {
// The change didn't change but the state did, so call changeState() now!
- if (currentSlide == activeSlide)
- changeState(currentSlide, newState, parentChanged);
+ if (currentSlide == activeSlide) {
+ changeState(static_cast<Q3DSSlide *>(currentSlide->parent()), newState);
+ changeState(currentSlide, newState);
+ }
m_data.state = newState;
Q_EMIT stateChanged(m_data.state);
}
diff --git a/src/runtime/slideplayerng/q3dsslideplayerng_p.h b/src/runtime/slideplayerng/q3dsslideplayerng_p.h
index 4e99d2d..cdec113 100644
--- a/src/runtime/slideplayerng/q3dsslideplayerng_p.h
+++ b/src/runtime/slideplayerng/q3dsslideplayerng_p.h
@@ -96,7 +96,7 @@ private:
void init();
void reset();
- void changeState(Q3DSSlide *slide, Q3DSSlidePlayerNg::PlayerState state, bool parentChanged);
+ void changeState(Q3DSSlide *slide, Q3DSSlidePlayerNg::PlayerState state);
void setInternalState(PlayerState newState);
void onDurationChanged(float duration);
void onSlideFinished(Q3DSSlide *slide);