From 65b870dfc8b30d3c81b8763954c007bc5561a90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Sep 2018 16:05:39 +0200 Subject: [PATCH] Animation: pausing animation should never result in a stopped state. --- src/Magnum/Animation/Player.h | 5 +- src/Magnum/Animation/Player.hpp | 16 ++++-- src/Magnum/Animation/Test/PlayerTest.cpp | 64 ++++++++++++++++++++---- 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/src/Magnum/Animation/Player.h b/src/Magnum/Animation/Player.h index 298f47867..a91ef6b9a 100644 --- a/src/Magnum/Animation/Player.h +++ b/src/Magnum/Animation/Player.h @@ -635,8 +635,9 @@ template& pause(T pauseTime); diff --git a/src/Magnum/Animation/Player.hpp b/src/Magnum/Animation/Player.hpp index a919fca11..e333a92d6 100644 --- a/src/Magnum/Animation/Player.hpp +++ b/src/Magnum/Animation/Player.hpp @@ -183,7 +183,7 @@ template Containers::Optional> playe key = K{}; playIteration = 0; if(playCount != 0) { - state = State::Stopped; + if(state != State::Paused) state = State::Stopped; startTime = {}; } @@ -193,7 +193,7 @@ template Containers::Optional> playe } else { std::tie(playIteration, key) = scaler(timeToUse, duration); if(playCount && playIteration >= playCount) { - state = State::Stopped; + if(state != State::Paused) state = State::Stopped; /* Don't reset the startTime to disambiguate between explicitly stopped and "time run out" animation */ playIteration = playCount - 1; @@ -217,9 +217,15 @@ template std::pair Player::elapsed(const if(elapsed) return *elapsed; /* If not advancing, the animation can be paused -- calculate the iteration - index and keyframe at which it was paused if the duration is nonzero. */ - if(_state == State::Paused && duration) - return _scaler(_startTime, duration); + index and keyframe at which it was paused if the duration is nonzero. If + the paused animation ran out, return the last iteration index and the + duration, otherwise just the calculated value. */ + if(_state == State::Paused && duration) { + const std::pair elapsed = _scaler(_startTime, duration); + if(_playCount && elapsed.first >= _playCount) + return {_playCount - 1, duration}; + return elapsed; + } /* It can be also stopped by running out, in that case return the last iteration index and the duration. Again have to use comparison to diff --git a/src/Magnum/Animation/Test/PlayerTest.cpp b/src/Magnum/Animation/Test/PlayerTest.cpp index b1e116117..9dadde05d 100644 --- a/src/Magnum/Animation/Test/PlayerTest.cpp +++ b/src/Magnum/Animation/Test/PlayerTest.cpp @@ -56,8 +56,10 @@ struct PlayerTest: TestSuite::Tester { void advancePlayCount(); void advancePlayCountInfinite(); void advanceChrono(); - void advanceZeroDuration(); - void advanceZeroDurationChrono(); + void advanceZeroDurationStop(); + void advanceZeroDurationPause(); + void advanceZeroDurationInfinitePlayCount(); + void advanceZeroDurationInfinitePlayCountChrono(); void setState(); @@ -125,8 +127,10 @@ PlayerTest::PlayerTest() { &PlayerTest::advancePlayCount, &PlayerTest::advancePlayCountInfinite, &PlayerTest::advanceChrono, - &PlayerTest::advanceZeroDuration, - &PlayerTest::advanceZeroDurationChrono, + &PlayerTest::advanceZeroDurationStop, + &PlayerTest::advanceZeroDurationPause, + &PlayerTest::advanceZeroDurationInfinitePlayCount, + &PlayerTest::advanceZeroDurationInfinitePlayCountChrono, &PlayerTest::setState, @@ -573,14 +577,14 @@ void PlayerTest::advancePauseTooLate() { CORRADE_COMPARE(player.elapsed(23.75f), std::make_pair(0, 1.75f)); CORRADE_COMPARE(value, 4.0f); - /* Pausing too late will set the state to paused at first */ + /* Pausing too late will set the state to paused */ player.pause(50.0f); CORRADE_COMPARE(player.state(), State::Paused); CORRADE_COMPARE(player.elapsed(50.0f), std::make_pair(0, 3.0f)); - /* But advancing will make it stopped since it's too late */ + /* And advancing will keep it paused, not transforming to stopped */ player.advance(50.5f); - CORRADE_COMPARE(player.state(), State::Stopped); + CORRADE_COMPARE(player.state(), State::Paused); CORRADE_COMPARE(player.elapsed(50.5f), std::make_pair(0, 3.0f)); } @@ -696,7 +700,49 @@ void PlayerTest::advanceChrono() { CORRADE_COMPARE(value, 4.0f); } -void PlayerTest::advanceZeroDuration() { +void PlayerTest::advanceZeroDurationStop() { + Float value = -1.0f; + Player player; + player.add(Track, value) + /* 1.75 secs since the start of the original duration */ + .setDuration(Range1D::fromSize(1.0f + 1.75f, 0.0f)) + .play(2.0f); + + CORRADE_COMPARE(player.duration().size(), 0.0f); + CORRADE_COMPARE(player.state(), State::Playing); + CORRADE_COMPARE(player.elapsed(1.75f), std::make_pair(0, 0.0f)); + CORRADE_COMPARE(value, -1.0f); + + /* The value at 1.75 secs is returned independent of time, state is stopped */ + player.advance(100.0f); + CORRADE_COMPARE(player.state(), State::Stopped); + CORRADE_COMPARE(player.elapsed(100.0f), std::make_pair(0, 0.0f)); + CORRADE_COMPARE(value, 4.0f); +} + +void PlayerTest::advanceZeroDurationPause() { + Float value = -1.0f; + Player player; + player.add(Track, value) + /* 1.75 secs since the start of the original duration */ + .setDuration(Range1D::fromSize(1.0f + 1.75f, 0.0f)) + .play(2.0f); + + CORRADE_COMPARE(player.duration().size(), 0.0f); + CORRADE_COMPARE(player.state(), State::Playing); + CORRADE_COMPARE(player.elapsed(1.75f), std::make_pair(0, 0.0f)); + CORRADE_COMPARE(value, -1.0f); + + /* The value at 1.75 secs is returned independent of time, state is paused + (explicitly not stopped) */ + player.pause(100.0f); + player.advance(100.0f); + CORRADE_COMPARE(player.state(), State::Paused); + CORRADE_COMPARE(player.elapsed(100.0f), std::make_pair(0, 0.0f)); + CORRADE_COMPARE(value, 4.0f); +} + +void PlayerTest::advanceZeroDurationInfinitePlayCount() { Float value = -1.0f; Player player; player.add(Track, value) @@ -723,7 +769,7 @@ void PlayerTest::advanceZeroDuration() { CORRADE_COMPARE(value, 4.0f); } -void PlayerTest::advanceZeroDurationChrono() { +void PlayerTest::advanceZeroDurationInfinitePlayCountChrono() { Float value = -1.0f; Player player; player.add(Track, value)