diff options
author | Christian Strømme <christian.stromme@qt.io> | 2019-01-09 16:35:05 +0100 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-01-09 16:43:44 +0000 |
commit | 85ce7c19c965f3dfdbc3eaf7365e8e6d5dc81a3d (patch) | |
tree | ffab010d89bc9e837ff8a64e95957c9375714e8e | |
parent | 66a48481616126929ae29a30b316a0dc930e3b2c (diff) |
Add support for dynamically adding/removing object from a slide
This change adds support for adding objects at run-time in the new
animation system. Note that this is now done in-place and requires
no rebuilding of the animation track for the slide, which means objects
with animations will start immediately at the right place.
Change-Id: I987aa1aeaa272f3506310304b5543bd6f9547d39
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
-rw-r--r-- | src/runtime/q3dsuippresentation_p.h | 5 | ||||
-rw-r--r-- | src/runtime/slideplayerng/q3dsanimationmanagerng.cpp | 87 | ||||
-rw-r--r-- | src/runtime/slideplayerng/q3dsanimationmanagerng_p.h | 2 | ||||
-rw-r--r-- | src/runtime/slideplayerng/q3dsslideplayerng.cpp | 6 | ||||
-rw-r--r-- | tests/manual/standalone/main.cpp | 11 |
5 files changed, 85 insertions, 26 deletions
diff --git a/src/runtime/q3dsuippresentation_p.h b/src/runtime/q3dsuippresentation_p.h index e87a192..2e89a22 100644 --- a/src/runtime/q3dsuippresentation_p.h +++ b/src/runtime/q3dsuippresentation_p.h @@ -668,6 +668,7 @@ public: Q_ENUM(PlayThrough) using PropertyChanges = QHash<Q3DSGraphObject *, Q3DSPropertyChangeList *>; + using AnimationTrackList = QVector<Q3DSAnimationTrack>; Q3DSSlide(); ~Q3DSSlide(); @@ -685,7 +686,7 @@ public: void removePropertyChanges(Q3DSGraphObject *target); Q3DSPropertyChangeList *takePropertyChanges(Q3DSGraphObject *target); - const QVector<Q3DSAnimationTrack> &animations() const { return m_anims; } + const AnimationTrackList &animations() const { return m_anims; } void addAnimation(const Q3DSAnimationTrack &track); void removeAnimation(const Q3DSAnimationTrack &track); @@ -750,7 +751,7 @@ private: QVariant m_playThroughValue; QSet<Q3DSGraphObject *> m_objects; PropertyChanges m_propChanges; - QVector<Q3DSAnimationTrack> m_anims; + AnimationTrackList m_anims; QVector<Q3DSAction> m_actions; QVector<SlideGraphChangeCallback> m_slideGraphChangeCallbacks; // master only QVector<SlideObjectChangeCallback> m_slideObjectChangeCallbacks; diff --git a/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp b/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp index 116cb0d..815ae48 100644 --- a/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp +++ b/src/runtime/slideplayerng/q3dsanimationmanagerng.cpp @@ -126,24 +126,9 @@ static void addKeyFramesForTrack(const Q3DSAnimationTrack &track, Q3DSAnimator:: } } -void Q3DSAnimationManagerNg::buildSlideAnimation(Q3DSSlide *slide, bool rebuild) +static void buildAnimationData(const Q3DSSlide::AnimationTrackList &tracks, + Q3DSAnimator::AnimationDataList *animationDataList) { - if (!slide) - return; - - Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>(); - Q_ASSERT(data); - if (!data->animatorNg) - data->animatorNg = new Q3DSAnimator; - - if (!rebuild && !data->animatorNg->animationDataList.isEmpty()) - return; - - 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) { @@ -159,10 +144,10 @@ void Q3DSAnimationManagerNg::buildSlideAnimation(Q3DSSlide *slide, bool rebuild) component.componentData.component = comp; component.componentData.size = quint16(track.keyFrames().size()); component.componentData.dynamic = track.isDynamic(); - animationDataList.push_back(component); + animationDataList->push_back(component); // 2. Add key frames for component track - addKeyFramesForTrack(track, &animationDataList); + 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]))) { @@ -178,12 +163,33 @@ void Q3DSAnimationManagerNg::buildSlideAnimation(Q3DSSlide *slide, bool rebuild) const auto type = Q3DSGraphObject::readProperty(track.target(), pid).type(); Q_ASSERT(type != QVariant::Invalid); targetData.targetData.type = type; - animationDataList.push_back(targetData); + animationDataList->push_back(targetData); } ++cit; } } +void Q3DSAnimationManagerNg::buildSlideAnimation(Q3DSSlide *slide, bool rebuild) +{ + if (!slide) + return; + + Q3DSSlideAttached *data = slide->attached<Q3DSSlideAttached>(); + Q_ASSERT(data); + if (!data->animatorNg) + data->animatorNg = new Q3DSAnimator; + + if (!rebuild && !data->animatorNg->animationDataList.isEmpty()) + return; + + 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(); + buildAnimationData(tracks, &animationDataList); +} + void Q3DSAnimationManagerNg::updateDynamicKeyFrames(Q3DSSlide *slide) { if (!slide) @@ -281,4 +287,45 @@ void Q3DSAnimationManagerNg::advance(Q3DSSlide *slide, float dtMs) slide->attached<Q3DSSlideAttached>()->animatorNg->advance(dtMs / 1000.f); } +void Q3DSAnimationManagerNg::addObject(Q3DSSlide *slide, Q3DSGraphObject *obj) +{ + if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg) { + auto &animationDataList = slide->attached<Q3DSSlideAttached>()->animatorNg->animationDataList; + const auto tracks = slide->animations(); + Q3DSSlide::AnimationTrackList tracksForObject; + auto cit = tracks.cbegin(); + while (cit != tracks.cend()) { + if (cit->target() == obj) + tracksForObject.push_back(*cit); + ++cit; + } + buildAnimationData(tracksForObject, &animationDataList); + } +} + +void Q3DSAnimationManagerNg::removeObject(Q3DSSlide *slide, Q3DSGraphObject *obj) +{ + if (slide && slide->attached<Q3DSSlideAttached>()->animatorNg) { + Q3DSAnimator *animator = slide->attached<Q3DSSlideAttached>()->animatorNg; + auto &dl = animator->animationDataList; + + auto it = dl.begin(); + const auto end = dl.end(); + auto removeStart = it; + while (it != end) { + if (it->type == Q3DSAnimationData::DataType::Target) { + if (it->targetData.target == obj) + break; + removeStart = it + 1; + Q_ASSERT(removeStart == end || removeStart->type == Q3DSAnimationData::DataType::Component); + } + ++it; + } + + if (it != end) { + Q_ASSERT(removeStart->type == Q3DSAnimationData::DataType::Component && it->type == Q3DSAnimationData::DataType::Target); + dl.erase(removeStart, it + 1); + } + } +} QT_END_NAMESPACE diff --git a/src/runtime/slideplayerng/q3dsanimationmanagerng_p.h b/src/runtime/slideplayerng/q3dsanimationmanagerng_p.h index 0621f9b..389877c 100644 --- a/src/runtime/slideplayerng/q3dsanimationmanagerng_p.h +++ b/src/runtime/slideplayerng/q3dsanimationmanagerng_p.h @@ -58,6 +58,8 @@ namespace Q3DSAnimationManagerNg Q3DSV_PRIVATE_EXPORT void setTimeChangeCallback(Q3DSSlide *slide, Q3DSAnimator::TimeChangeCallback cb); Q3DSV_PRIVATE_EXPORT void buildSlideAnimation(Q3DSSlide *slide, bool rebuild = false); Q3DSV_PRIVATE_EXPORT void updateDynamicKeyFrames(Q3DSSlide *slide); + Q3DSV_PRIVATE_EXPORT void addObject(Q3DSSlide *slide, Q3DSGraphObject *obj); + Q3DSV_PRIVATE_EXPORT void removeObject(Q3DSSlide *slide, Q3DSGraphObject *obj); }; QT_END_NAMESPACE diff --git a/src/runtime/slideplayerng/q3dsslideplayerng.cpp b/src/runtime/slideplayerng/q3dsslideplayerng.cpp index 8e217b3..293701d 100644 --- a/src/runtime/slideplayerng/q3dsslideplayerng.cpp +++ b/src/runtime/slideplayerng/q3dsslideplayerng.cpp @@ -879,21 +879,21 @@ void Q3DSSlidePlayerNg::objectAboutToBeAddedToScene(Q3DSGraphObject *obj) void Q3DSSlidePlayerNg::objectAboutToBeRemovedFromScene(Q3DSGraphObject *obj) { - // TODO: - (void)obj; -// m_animationManager->objectAboutToBeRemovedFromScene(obj); + evaluateDynamicObjectVisibility(obj); } void Q3DSSlidePlayerNg::objectAddedToSlide(Q3DSGraphObject *obj, Q3DSSlide *slide) { qDebug(lcSlidePlayer) << "Dyn.added object" << obj->id() << "to slide" << slide->id(); evaluateDynamicObjectVisibility(obj); + Q3DSAnimationManagerNg::addObject(slide, obj); } void Q3DSSlidePlayerNg::objectRemovedFromSlide(Q3DSGraphObject *obj, Q3DSSlide *slide) { qDebug(lcSlidePlayer) << "Dyn.removed object" << obj->id() << "from slide" << slide->id(); evaluateDynamicObjectVisibility(obj); + Q3DSAnimationManagerNg::removeObject(slide, obj); } QT_END_NAMESPACE diff --git a/tests/manual/standalone/main.cpp b/tests/manual/standalone/main.cpp index c8d207b..2fe598f 100644 --- a/tests/manual/standalone/main.cpp +++ b/tests/manual/standalone/main.cpp @@ -53,9 +53,13 @@ void buildDynamicSpawner(Q3DSUipPresentation *pres, Q3DSLayerNode *layer, Q3DSSl ++dyncounter; newmodel->appendChildNode(newmat); - newmodel->setMesh(QLatin1String("#Sphere")); + newmodel->setMesh(QLatin1String("#Cone")); newmodel->setPosition(QVector3D((qrand() % 600) - 300, (qrand() % 600) - 300, 0)); + Q3DSAnimationTrack anim(Q3DSAnimationTrack::Linear, newmodel, QLatin1String("rotation.y")); + anim.setKeyFrames({ { 0, 0 }, { 1, 45 }, { 2, 0 }, { 3, -45 }, { 4, 0 }, { 5, 45 }, { 6, 0 }, { 7, -45 }, { 8, 0 } }); + slide->addAnimation(anim); + slide->addObject(newmodel); slide->addObject(newmat); @@ -222,9 +226,14 @@ Q3DSUipPresentation *build() Q3DSSlide *masterSlide = mainPres->newObject<Q3DSSlide>("master"); Q3DSSlide *slide1 = mainPres->newObject<Q3DSSlide>("slide1"); slide1->setName(QLatin1String("Slide 1")); + slide1->setPlayMode(Q3DSSlide::PlayThroughTo); + slide1->setPlayThrough(Q3DSSlide::Next); masterSlide->appendChildNode(slide1); Q3DSSlide *slide2 = mainPres->newObject<Q3DSSlide>("slide2"); slide2->setName(QLatin1String("Slide 2")); + slide2->setPlayMode(Q3DSSlide::PlayThroughTo); + slide2->setPlayThrough(Q3DSSlide::Previous); + slide2->setEndTime(1000); masterSlide->appendChildNode(slide2); mainPres->setMasterSlide(masterSlide); |