aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/util/qquickanimation.cpp5
-rw-r--r--tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml54
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp49
3 files changed, 106 insertions, 2 deletions
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 9962313f26..0f0ac2b78d 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -2040,8 +2040,9 @@ void QQuickBulkValueAnimator::updateCurrentTime(int currentTime)
void QQuickBulkValueAnimator::topLevelAnimationLoopChanged()
{
- //check for new from every top-level loop (when the top level animation is started and all subsequent loops)
- if (fromIsSourced)
+ // Check for new "from" value only when animation has one loop.
+ // Otherwise use the initial "from" value for every iteration.
+ if (m_loopCount == 1 && fromIsSourced)
*fromIsSourced = false;
QAbstractAnimationJob::topLevelAnimationLoopChanged();
}
diff --git a/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml b/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml
new file mode 100644
index 0000000000..9b4bfe4faa
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/infiniteAnimationWithoutFrom.qml
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ width: 100
+ height: 100
+
+ // note that 'from' property is missing
+ NumberAnimation {
+ objectName: "anim"
+ to: from+360
+ loops: Animation.Infinite
+ target: rect
+ properties: "rotation"
+ duration: 100
+ }
+
+ Rectangle {
+ objectName: "rect"
+ id: rect
+ width: 30
+ height: 10
+ color: "red"
+ anchors.centerIn: parent
+ transformOrigin: Item.Center
+ }
+}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 10c8fb3487..72e0da91cb 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -119,6 +119,7 @@ private slots:
void cleanupWhenRenderThreadStops();
void changePropertiesDuringAnimation_data();
void changePropertiesDuringAnimation();
+ void infiniteLoopsWithoutFrom();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -2120,6 +2121,54 @@ void tst_qquickanimations::changePropertiesDuringAnimation()
QCOMPARE(stoppedSpy.count(), 0);
}
+void tst_qquickanimations::infiniteLoopsWithoutFrom()
+{
+ // This test checks QTBUG-84375
+ QQuickView view(testFileUrl("infiniteAnimationWithoutFrom.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(view.rootObject());
+
+ QObject *root = view.rootObject();
+ QQuickAbstractAnimation *animation = root->findChild<QQuickAbstractAnimation *>("anim");
+ QVERIFY(animation);
+ QQuickRectangle *rectangle = root->findChild<QQuickRectangle *>("rect");
+ QVERIFY(rectangle);
+
+ qreal prevRotation = rectangle->rotation();
+ int numsCrossedZero = 0;
+ connect(rectangle, &QQuickRectangle::rotationChanged, this, [&]() {
+ const auto rotation = rectangle->rotation();
+ // We take a large range of (180; 360] here, because the animation in
+ // the test runs for a short time, and so there can be huge gaps between
+ // rotation values.
+ const bool prevRotationOldLoop = prevRotation > 180.0 && prevRotation <= 360.0;
+ const bool currRotationNewLoop = rotation >= 0.0 && rotation <= 180.0;
+ if (prevRotationOldLoop && currRotationNewLoop)
+ numsCrossedZero++;
+ prevRotation = rotation;
+ });
+
+ // The logic in lamdba function above requires at least two positions in
+ // a rotation animation - one in [0; 180] range, and another in (180; 360]
+ // range
+ animation->start();
+ animation->pause();
+ QCOMPARE(numsCrossedZero, 0);
+ animation->setCurrentTime(40);
+ animation->setCurrentTime(90);
+ QCOMPARE(numsCrossedZero, 0);
+ animation->setCurrentTime(140);
+ animation->setCurrentTime(190);
+ QCOMPARE(numsCrossedZero, 1);
+ animation->setCurrentTime(240);
+ animation->setCurrentTime(290);
+ QCOMPARE(numsCrossedZero, 2);
+
+ animation->stop();
+}
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"