From bc55de17a036c68cd6755280e216c144c4505a0f Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Wed, 9 May 2018 14:46:40 +0200 Subject: Fix isSlideVisible Check if the slide is the master slide - if it is, then we're visible. Change-Id: I123988001a09d68ae67901a6bd919d3af37f9d01 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index fee148c..8999f93 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -713,7 +713,9 @@ bool Q3DSSlidePlayer::isSlideVisible(Q3DSSlide *slide) if (slide) { Q3DSSlidePlayer *player = slide->attached()->slidePlayer; Q3DSSlideDeck *slideDeck = player->slideDeck(); - if (slideDeck->currentSlide() == slide) { + const bool isMasterSlide = (slideDeck->masterSlide() == slide); + const bool isCurrentSlide = (slideDeck->currentSlide() == slide); + if (isCurrentSlide || isMasterSlide) { Q3DSSlide *parentSlide = slideDeck->parentSlide(); if (parentSlide) { // We're a component and current, continue up the ladder... -- cgit v1.2.3 From a930fdb7005c5493628e38f812bb1bfd5b16ed17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 14 May 2018 14:33:34 +0200 Subject: Fix getStartAndEndTime function For components there are no layers, so look at the node types and get the max endtime from there. Change-Id: Ia6b55062b36fd2c248fc98c9fe772494a93d5dcc Reviewed-by: Andy Nichols --- src/runtime/q3dsslideplayer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index 8999f93..1f58bd5 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -79,6 +79,16 @@ void Q3DSSlideUtils::getStartAndEndTime(Q3DSSlide *slide, qint32 *startTime, qin eTime = obj->endTime(); } + // If we don't have an endtime, then there was no layer, so look at the nodes instead. + if (eTime == -1) { + for (const auto obj : slide->objects()) { + if (!obj->isNode()) + continue; + if (obj->endTime() > eTime) + eTime = obj->endTime(); + } + } + if (startTime) *startTime = slide->startTime(); if (endTime) -- cgit v1.2.3 From 3e7858077e281e477f4209898d3f58314d8ca5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Tue, 15 May 2018 13:10:57 +0200 Subject: Don't send EOS when transition from one state to another When changing slides, the previous slides state might be playing, but the next slide is not yet started, so check the pending state as well. Change-Id: I90ab0ab3d924745749e697af150b6d79340430f0 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index 1f58bd5..a8e60b0 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -696,7 +696,7 @@ void Q3DSSlidePlayer::sendPositionChanged(Q3DSSlide *slide, float pos) if (!qFuzzyCompare(oldPosition, pos)) Q_EMIT positionChanged(pos); - const bool onEOS = (m_data.state == PlayerState::Playing) + const bool onEOS = (m_data.state == PlayerState::Playing && m_data.pendingState == PlayerState::Playing) && ((m_data.position == 0.0f && m_data.playbackRate < 0.0f) || (m_data.position == duration() && m_data.playbackRate > 0.0f)); -- cgit v1.2.3 From a6778041640d1aa86e0a994353407e143c26f605 Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Mon, 14 May 2018 01:06:52 +0200 Subject: Fix misc. component logic Better handling of components. They live their own life, so don't try to enforce anything from the slide that owns the component, it will all be handled by the components slide player. Task-number: QT3DS-1016 Change-Id: If435d6d0799bd52caae133b48119e0a015ff34d0 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 158 ++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 70 deletions(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index a8e60b0..7fdcf45 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -107,40 +107,28 @@ static Q3DSSlidePlayer::PlayerState getInitialSlideState(Q3DSSlide *slide) } -static void updatePosition(Q3DSSlide *slide, float pos, float duration) +static void updatePosition(Q3DSSlide *slide, float newTimeMs, float durationMs) { - const auto updateAnimator = [pos](Qt3DAnimation::QClipAnimator *animator, float duration) { + const auto updateAnimator = [newTimeMs](Qt3DAnimation::QClipAnimator *animator, float durationMs) { if (!animator) return; - const float nt = qBound(0.0f, pos / duration, 1.0f); + const float nt = qBound(0.0f, newTimeMs / durationMs, 1.0f); // NOTE!!!: This is a bit funky, but it means we can avoid tracking the normalized values in the // frontend node. This of course assumes that the limit in the fuzzy compare doesn't change! animator->setNormalizedTime(qFuzzyCompare(nt, animator->normalizedTime()) ? qAbs(nt - (1.0f / 100000.0f)) : nt); }; const auto updateAnimators = [&updateAnimator](const QVector &animators) { for (auto animator : animators) { - const float duration = animator->clip()->duration() * 1000.0f; - updateAnimator(animator, duration); - } - }; - - const auto updateAllComponentPlayers = [pos](Q3DSSlide *slide) { - for (auto obj : slide->objects()) { - if (obj->type() == Q3DSGraphObject::Component) { - Q3DSComponentNode *comp = static_cast(obj); - const float slidePos = pos - obj->startTime(); - Q3DSSlidePlayer *player = comp->masterSlide()->attached()->slidePlayer; - player->seek(slidePos); - } + const float durationMs = animator->clip()->duration() * 1000.0f; + updateAnimator(animator, durationMs); } }; Q3DSSlideAttached *data = slide->attached(); Q_ASSERT(data); - updateAllComponentPlayers(slide); - updateAnimator(data->animator, duration); + updateAnimator(data->animator, durationMs); updateAnimators(data->animators); }; @@ -167,24 +155,9 @@ static void updateAnimators(Q3DSSlide *slide, bool running, bool restart, float updateAnimator(animator); }; - const auto updateAllComponentPlayers = [running](Q3DSSlide *slide) { - for (auto obj : slide->objects()) { - if (obj->type() == Q3DSGraphObject::Component) { - Q3DSComponentNode *comp = static_cast(obj); - Q3DSSlide *compSlide = comp->currentSlide(); - Q3DSSlidePlayer *player = comp->masterSlide()->attached()->slidePlayer; - if (running && compSlide->initialPlayState() == Q3DSSlide::Play) - player->play(); - else - player->stop(); - } - } - }; - Q3DSSlideAttached *data = slide->attached(); Q_ASSERT(data); - updateAllComponentPlayers(slide); updateAnimator(data->animator); updateAnimators(data->animators); } @@ -202,20 +175,9 @@ static void updatePlaybackRate(Q3DSSlide *slide, float rate) updateAnimator(animator); }; - const auto updateAllComponentPlayers = [rate](Q3DSSlide *slide) { - for (auto obj : slide->objects()) { - if (obj->type() == Q3DSGraphObject::Component) { - Q3DSComponentNode *comp = static_cast(obj); - Q3DSSlidePlayer *player = comp->masterSlide()->attached()->slidePlayer; - player->setPlaybackRate(rate); - } - } - }; - Q3DSSlideAttached *data = slide->attached(); Q_ASSERT(data); - updateAllComponentPlayers(slide); updateAnimator(data->animator); updateAnimators(data->animators); } @@ -246,6 +208,43 @@ void Q3DSSlidePlayer::advanceFrame() m_animationManager->applyChanges(); } +void Q3DSSlidePlayer::sceneReady() +{ + Q3DSSlideDeck *slideDeck = m_data.slideDeck; + if (!slideDeck) + return; + + Q3DSSlide *currentSlide = slideDeck->currentSlide(); + Q_ASSERT(currentSlide); + + const bool viewerMode = (m_mode == PlayerMode::Viewer); + if (viewerMode && (currentSlide->initialPlayState() == Q3DSSlide::Play)) + play(); + else + pause(); + + // In viewer-mode we need to go through all components players as well + if (viewerMode) { + static const auto notifyComponentPlayers = [](Q3DSSlide *slide) { + if (!slide) + return; + + const auto &objects = slide->objects(); + std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *obj) { + if (obj->type() == Q3DSGraphObject::Component) { + Q3DSComponentNode *comp = static_cast(obj); + Q3DSSlide *compSlide = comp->currentSlide(); + Q3DSSlidePlayer *player = compSlide->attached()->slidePlayer; + player->sceneReady(); + } + return false; + }); + }; + notifyComponentPlayers(static_cast(currentSlide->parent())); + notifyComponentPlayers(currentSlide); + } +} + float Q3DSSlidePlayer::duration() const { if (m_data.state == PlayerState::Idle) @@ -314,9 +313,14 @@ void Q3DSSlidePlayer::stop() void Q3DSSlidePlayer::pause() { - if (m_data.state != PlayerState::Playing) + if (m_data.state == PlayerState::Paused) return; + if (m_data.state == PlayerState::Idle) { + qCWarning(lcSlidePlayer) << "Pause called in Idle state (no content)"; + return; + } + setInternalState(PlayerState::Paused); } @@ -388,8 +392,6 @@ void Q3DSSlidePlayer::setSlideDeck(Q3DSSlideDeck *slideDeck) // Create a slide deck for this component compMasterData->slidePlayer->setSlideDeck(new Q3DSSlideDeck(compMasterSlide, slide)); } - - Q_ASSERT(compMasterData->slidePlayer->state() == PlayerState::Ready); }; const auto forAllComponentsOnSlide = [this, prepareComponentsOnSlide](Q3DSSlide *slide) { @@ -556,10 +558,28 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide, qCDebug(lcSlidePlayer, "Handling current slide change: from slide \"%s\", to slide \"%s\"", qPrintable(getSlideName(previousSlide)), qPrintable(getSlideName(slide))); + static const auto cleanUpComponentPlayers = [](Q3DSSlide *slide) { + if (!slide) + return; + + const auto &objects = slide->objects(); + std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *obj) { + if (obj->type() == Q3DSGraphObject::Component) { + Q3DSComponentNode *comp = static_cast(obj); + Q3DSSlide *compSlide = comp->currentSlide(); + Q3DSSlideAttached *data = compSlide->attached(); + data->slidePlayer->handleCurrentSlideChanged(nullptr, compSlide); + } + return false; + }); + }; if (previousSlide && slideDidChange) { - if (parentChanged) + if (parentChanged) { + cleanUpComponentPlayers(static_cast(previousSlide->parent())); setSlideTime(static_cast(previousSlide->parent()), -1.0f); + } setSlideTime(previousSlide, -1.0f); + cleanUpComponentPlayers(previousSlide); Q3DSSlideAttached *data = previousSlide->attached(); if (data && data->animator) { // TODO: We probably want to be a bit less brute. @@ -572,7 +592,6 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide, if (slide && slideDidChange && isSlideVisible(slide)) { m_sceneManager->handleSlideChange(previousSlide, slide); m_animationManager->updateAnimations(slide, (m_mode == PlayerMode::Editor)); - if (parentChanged) setSlideTime(static_cast(slide->parent()), 0.0f); setSlideTime(slide, 0.0f); @@ -613,6 +632,26 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide, qint32 endTime = 0; Q3DSSlideUtils::getStartAndEndTime(slide, &startTime, &endTime); onDurationChanged(endTime - startTime); + + static const auto updateComponentSlides = [](Q3DSSlide *slide) { + if (!slide) + return; + const auto &objects = slide->objects(); + std::find_if(objects.constBegin(), objects.constEnd(), [](Q3DSGraphObject *obj) { + if (obj->type() == Q3DSGraphObject::Component) { + Q3DSComponentNode *comp = static_cast(obj); + Q3DSSlide *compSlide = comp->currentSlide(); + Q3DSSlideAttached *data = compSlide->attached(); + data->slidePlayer->handleCurrentSlideChanged(compSlide, nullptr); + if (data->slidePlayer->m_mode == PlayerMode::Viewer) + data->slidePlayer->setInternalState(getInitialSlideState(compSlide)); + } + return false; + }); + }; + if (parentChanged) + updateComponentSlides(static_cast(slide->parent())); + updateComponentSlides(slide); } if (previousSlide != slide) @@ -656,27 +695,6 @@ void Q3DSSlidePlayer::setSlideTime(Q3DSSlide *slide, float time, bool parentVisi && node->flags().testFlag(Q3DSNode::Active) && static_cast(node->attached())->globalVisibility; - if (obj->type() == Q3DSGraphObject::Component) { - Q3DSComponentNode *comp = static_cast(obj); - Q3DSSlide *compMasterSlide = comp->masterSlide(); - Q_ASSERT(compMasterSlide); - Q3DSSlidePlayer *compPlayer = compMasterSlide->attached()->slidePlayer; - Q_ASSERT(compPlayer); - - const float slideTime = time - obj->startTime(); - compPlayer->setSlideTime(compMasterSlide, slideTime, shouldBeVisible); - - if (!shouldBeVisible) { - Q3DSGraphObject *n = compMasterSlide->firstChild(); - while (n) { - compPlayer->setSlideTime(static_cast(n), slideTime, shouldBeVisible); - n = n->nextSibling(); - } - } else { - compPlayer->setSlideTime(comp->currentSlide(), slideTime); - } - } - if (forceUpdate || shouldBeVisible != nodeHasVisibilityTag(node)) updateNodeVisibility(node, shouldBeVisible); } -- cgit v1.2.3 From f92bae2ef0e33b722317467e888e80d16bd6a92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 14 May 2018 12:17:40 +0200 Subject: Always use the slideplayer associated with the slide to update the time Components manage their own objects, so they need to know when the time changes. Change-Id: I4f5a6f8daa9b33fe71b74e4c18657c042d1513d7 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index 7fdcf45..499a4ee 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -186,7 +186,7 @@ Q3DSSlidePlayer::Q3DSSlidePlayer(Q3DSSceneManager *sceneManager, QObject *parent) : QObject(parent) , m_sceneManager(sceneManager) - , m_animationManager(new Q3DSAnimationManager(this)) + , m_animationManager(new Q3DSAnimationManager) { } -- cgit v1.2.3 From dbdfdca92db35e87ca02e0731e47f9497b23204b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 14 May 2018 18:54:13 +0200 Subject: Properly fix getStartAndEndTime This is hopefully the the final iteration... Always go through the property updates and get the values as needed, expecting the caller to know/remember to apply the property changes is just hazardous, so let's just do it in-place. Instead of iterating over the same data several times (layers and nodes) just do it in one go. Change-Id: Ide3d84570d4765567ed300a1107b010bb3e10b82 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 62 +++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index 499a4ee..dbdb7c3 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -44,55 +44,63 @@ QT_BEGIN_NAMESPACE -// NOTE: We assume that the properties for the layer has been applied before this is called -// if it hasn't it will either return the previous value or the odl value void Q3DSSlideUtils::getStartAndEndTime(Q3DSSlide *slide, qint32 *startTime, qint32 *endTime) { Q_ASSERT(startTime != nullptr || endTime != nullptr); - qint32 eTime = -1; + qint32 layerEndTime = -1; + qint32 nodesEndtime = -1; - // First go through the slide's parent (master slide) and look for layers which have - // endtime explicitly set by this slide's property changes + // Check if there are nodes from the parent slide that has property changes on this slide. if (Q3DSSlide *p = static_cast(slide->parent())) { for (auto *obj : p->objects()) { - if (obj->type() != Q3DSGraphObject::Layer) + if (!obj->isNode()) continue; - const QHash props = - slide->propertyChanges(); - const QHash::const_iterator it = - props.find(obj); - if (it == props.constEnd()) + // Look for property updates on "this" slide. + const auto &props = slide->propertyChanges(); + const auto foundIt = props.constFind(obj); + if (foundIt == props.constEnd()) continue; - if ((*it)->keys().contains(QStringLiteral("endtime")) && obj->endTime() > eTime) - eTime = obj->endTime(); + + // If there are property changes for the object, check if it has a new endtime. + std::find_if(foundIt.value()->cbegin(), foundIt.value()->cend(), [&layerEndTime, &nodesEndtime, obj](const Q3DSPropertyChange &propChange) { + if (propChange.name() == QLatin1String("endtime")) { + bool ok = false; + const qint32 value = propChange.value().toInt(&ok); + if (ok) { + if (obj->type() == Q3DSGraphObject::Layer && (value > layerEndTime)) + layerEndTime = value; + else if (value > nodesEndtime) + nodesEndtime = value; + } + } + return false; + }); } } - // Now look for the endtime from the slides explicit layer objects + // Now look for the endtime on nodes on this slide. for (const auto obj : slide->objects()) { - if (obj->type() != Q3DSGraphObject::Layer) + // Skip non-node types. + if (!obj->isNode()) continue; - if (obj->endTime() > eTime) - eTime = obj->endTime(); + // We collect both layer endtimes (if any) and object endtimes in one go. + if (obj->type() == Q3DSGraphObject::Layer && (obj->endTime() > layerEndTime)) + layerEndTime = obj->endTime(); + else if (obj->endTime() > nodesEndtime) + nodesEndtime = obj->endTime(); } - // If we don't have an endtime, then there was no layer, so look at the nodes instead. - if (eTime == -1) { - for (const auto obj : slide->objects()) { - if (!obj->isNode()) - continue; - if (obj->endTime() > eTime) - eTime = obj->endTime(); - } - } + // Final fallback, if neither was found use the value set by the slide. + if (layerEndTime == -1 && nodesEndtime == -1) + nodesEndtime = slide->endTime(); if (startTime) *startTime = slide->startTime(); if (endTime) - *endTime = eTime != -1 ? eTime : slide->endTime(); + *endTime = layerEndTime != -1 ? layerEndTime : nodesEndtime; } static QString getSlideName(Q3DSSlide *slide) -- cgit v1.2.3 From 7a78347e10a1bcaf044367075ff4e5e2df157289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Mon, 14 May 2018 18:57:40 +0200 Subject: Force update the running state This is the same as previous hacks, i.e., we need to force update the property, since it hasn't been updated from the backend. Change-Id: Ib5a09e9b75eea93b6c70cc98ea2d3f5e6c822e26 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index dbdb7c3..648d31d 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -150,12 +150,11 @@ static void updateAnimators(Q3DSSlide *slide, bool running, bool restart, float // NOTE!!!: This is a bit funky, but it means we can avoid tracking the normalized values in the // frontend node. This of course assumes that the limit in the fuzzy compare doesn't change! animator->setNormalizedTime(qFuzzyCompare(animator->normalizedTime(), 0.0f) ? (0.0f + (1.0f / 100000.0f)) : 0.0f); - // NOTE: The running value might not have been updated in the frontend node yet, - // so force update this one as well! - if (animator->isRunning()) - animator->setRunning(false); } animator->clock()->setPlaybackRate(double(rate)); + // NOTE: The running value might not have been updated in the frontend node yet, + // so force update if the values are the same... + animator->setRunning(!running); animator->setRunning(running); }; const auto updateAnimators = [&updateAnimator](const QVector &animators) { -- cgit v1.2.3 From 10f87bf805fc0d95723dda14e478793d3b2d1909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Wed, 16 May 2018 12:48:28 +0200 Subject: Refactor handleSlideChange in the scene manager Move the relevant code to the slide player, as the implementation details belongs there. Also, updating the properties are now done in-place and without extra heap alloctions, which should make the code more performant as well. Change-Id: I5cee4ee24a670faf0245d9fda4ad2a7a66734851 Reviewed-by: Laszlo Agocs --- src/runtime/q3dsslideplayer.cpp | 56 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'src/runtime/q3dsslideplayer.cpp') diff --git a/src/runtime/q3dsslideplayer.cpp b/src/runtime/q3dsslideplayer.cpp index 648d31d..f7c2ee2 100644 --- a/src/runtime/q3dsslideplayer.cpp +++ b/src/runtime/q3dsslideplayer.cpp @@ -597,7 +597,7 @@ void Q3DSSlidePlayer::handleCurrentSlideChanged(Q3DSSlide *slide, } if (slide && slideDidChange && isSlideVisible(slide)) { - m_sceneManager->handleSlideChange(previousSlide, slide); + processPropertyChanges(slide, previousSlide); m_animationManager->updateAnimations(slide, (m_mode == PlayerMode::Editor)); if (parentChanged) setSlideTime(static_cast(slide->parent()), 0.0f); @@ -768,6 +768,60 @@ bool Q3DSSlidePlayer::isSlideVisible(Q3DSSlide *slide) return visible; } +void Q3DSSlidePlayer::processPropertyChanges(Q3DSSlide *currentSlide, + Q3DSSlide *previousSlide) +{ + Q_ASSERT(currentSlide->attached()); + + if (previousSlide) { + auto slideData = static_cast(previousSlide->attached()); + for (Q3DSNode *node : qAsConst(slideData->needsMasterRollback)) { + const Q3DSPropertyChangeList *changeList = node->masterRollbackList(); + if (changeList) { + qCDebug(lcScene, "Rolling back %d changes to master for %s", changeList->count(), node->id().constData()); + node->applyPropertyChanges(*changeList); + node->notifyPropertyChanges(*changeList); + m_sceneManager->updateSubTreeRecursive(node); + } + } + slideData->needsMasterRollback.clear(); + } + + // Find properties on targets that has dynamic properties. + // TODO: Find a better solution (e.g., there can be duplicate updates for e.g., xyz here). + QHash dynamicPropertyChanges; + const auto &tracks = currentSlide->animations(); + std::find_if(tracks.cbegin(), tracks.cend(), [&dynamicPropertyChanges](const Q3DSAnimationTrack &track) { + if (track.isDynamic()) { + auto foundIt = dynamicPropertyChanges.constFind(track.target()); + Q3DSPropertyChangeList changeList; + if (foundIt != dynamicPropertyChanges.constEnd()) + changeList = *foundIt; + const QString property = track.property().split('.')[0]; + const auto value = track.target()->propertyValue(property); + changeList.append(Q3DSPropertyChange::fromVariant(property, value)); + dynamicPropertyChanges[track.target()] = changeList; + } + return false; + }); + + // Filter out properties that we needs to be marked dirty, i.e., eyeball changes. + const auto &propertyChanges = currentSlide->propertyChanges(); + for (auto it = propertyChanges.cbegin(); it != propertyChanges.cend(); ++it) { + std::find_if((*it)->cbegin(), (*it)->cend(), [it](const Q3DSPropertyChange &propChange) { + if (propChange.name() == QLatin1String("eyeball")) + it.key()->notifyPropertyChanges(*it.value()); + + it.key()->applyPropertyChanges(*it.value()); + return false; + }); + } + + // Now update the propeties from dynamic property values + for (auto it = dynamicPropertyChanges.cbegin(), ite = dynamicPropertyChanges.cend(); it != ite; ++it) + it.key()->applyPropertyChanges(it.value()); +} + void Q3DSSlidePlayer::onDurationChanged(float duration) { if (qFuzzyCompare(duration, m_data.duration)) -- cgit v1.2.3