Browse Source

Animation: pausing animation should never result in a stopped state.

inverted-ranges
Vladimír Vondruš 8 years ago
parent
commit
65b870dfc8
  1. 5
      src/Magnum/Animation/Player.h
  2. 16
      src/Magnum/Animation/Player.hpp
  3. 64
      src/Magnum/Animation/Test/PlayerTest.cpp

5
src/Magnum/Animation/Player.h

@ -635,8 +635,9 @@ template<class T, class K
* *
* Pauses the currently playing animation at given @p pauseTime. If * Pauses the currently playing animation at given @p pauseTime. If
* @ref state() is not @ref State::Playing, the function does nothing. * @ref state() is not @ref State::Playing, the function does nothing.
* See @ref advance() for a detailed description of behavior when the * If @p pauseTime is too far in the future, the animation will get
* animation gets paused. * paused at the end (i.e., not stopped). See @ref advance() for a
* detailed description of behavior when the animation gets paused.
* @see @ref setState() * @see @ref setState()
*/ */
Player<T, K>& pause(T pauseTime); Player<T, K>& pause(T pauseTime);

16
src/Magnum/Animation/Player.hpp

@ -183,7 +183,7 @@ template<class T, class K> Containers::Optional<std::pair<UnsignedInt, K>> playe
key = K{}; key = K{};
playIteration = 0; playIteration = 0;
if(playCount != 0) { if(playCount != 0) {
state = State::Stopped; if(state != State::Paused) state = State::Stopped;
startTime = {}; startTime = {};
} }
@ -193,7 +193,7 @@ template<class T, class K> Containers::Optional<std::pair<UnsignedInt, K>> playe
} else { } else {
std::tie(playIteration, key) = scaler(timeToUse, duration); std::tie(playIteration, key) = scaler(timeToUse, duration);
if(playCount && playIteration >= playCount) { if(playCount && playIteration >= playCount) {
state = State::Stopped; if(state != State::Paused) state = State::Stopped;
/* Don't reset the startTime to disambiguate between explicitly /* Don't reset the startTime to disambiguate between explicitly
stopped and "time run out" animation */ stopped and "time run out" animation */
playIteration = playCount - 1; playIteration = playCount - 1;
@ -217,9 +217,15 @@ template<class T, class K> std::pair<UnsignedInt, K> Player<T, K>::elapsed(const
if(elapsed) return *elapsed; if(elapsed) return *elapsed;
/* If not advancing, the animation can be paused -- calculate the iteration /* If not advancing, the animation can be paused -- calculate the iteration
index and keyframe at which it was paused if the duration is nonzero. */ index and keyframe at which it was paused if the duration is nonzero. If
if(_state == State::Paused && duration) the paused animation ran out, return the last iteration index and the
return _scaler(_startTime, duration); duration, otherwise just the calculated value. */
if(_state == State::Paused && duration) {
const std::pair<UnsignedInt, K> 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 /* 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 iteration index and the duration. Again have to use comparison to

64
src/Magnum/Animation/Test/PlayerTest.cpp

@ -56,8 +56,10 @@ struct PlayerTest: TestSuite::Tester {
void advancePlayCount(); void advancePlayCount();
void advancePlayCountInfinite(); void advancePlayCountInfinite();
void advanceChrono(); void advanceChrono();
void advanceZeroDuration(); void advanceZeroDurationStop();
void advanceZeroDurationChrono(); void advanceZeroDurationPause();
void advanceZeroDurationInfinitePlayCount();
void advanceZeroDurationInfinitePlayCountChrono();
void setState(); void setState();
@ -125,8 +127,10 @@ PlayerTest::PlayerTest() {
&PlayerTest::advancePlayCount, &PlayerTest::advancePlayCount,
&PlayerTest::advancePlayCountInfinite, &PlayerTest::advancePlayCountInfinite,
&PlayerTest::advanceChrono, &PlayerTest::advanceChrono,
&PlayerTest::advanceZeroDuration, &PlayerTest::advanceZeroDurationStop,
&PlayerTest::advanceZeroDurationChrono, &PlayerTest::advanceZeroDurationPause,
&PlayerTest::advanceZeroDurationInfinitePlayCount,
&PlayerTest::advanceZeroDurationInfinitePlayCountChrono,
&PlayerTest::setState, &PlayerTest::setState,
@ -573,14 +577,14 @@ void PlayerTest::advancePauseTooLate() {
CORRADE_COMPARE(player.elapsed(23.75f), std::make_pair(0, 1.75f)); CORRADE_COMPARE(player.elapsed(23.75f), std::make_pair(0, 1.75f));
CORRADE_COMPARE(value, 4.0f); 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); player.pause(50.0f);
CORRADE_COMPARE(player.state(), State::Paused); CORRADE_COMPARE(player.state(), State::Paused);
CORRADE_COMPARE(player.elapsed(50.0f), std::make_pair(0, 3.0f)); 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); 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)); CORRADE_COMPARE(player.elapsed(50.5f), std::make_pair(0, 3.0f));
} }
@ -696,7 +700,49 @@ void PlayerTest::advanceChrono() {
CORRADE_COMPARE(value, 4.0f); CORRADE_COMPARE(value, 4.0f);
} }
void PlayerTest::advanceZeroDuration() { void PlayerTest::advanceZeroDurationStop() {
Float value = -1.0f;
Player<Float> 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<Float> 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; Float value = -1.0f;
Player<Float> player; Player<Float> player;
player.add(Track, value) player.add(Track, value)
@ -723,7 +769,7 @@ void PlayerTest::advanceZeroDuration() {
CORRADE_COMPARE(value, 4.0f); CORRADE_COMPARE(value, 4.0f);
} }
void PlayerTest::advanceZeroDurationChrono() { void PlayerTest::advanceZeroDurationInfinitePlayCountChrono() {
Float value = -1.0f; Float value = -1.0f;
Player<std::chrono::nanoseconds, Float> player; Player<std::chrono::nanoseconds, Float> player;
player.add(Track, value) player.add(Track, value)

Loading…
Cancel
Save