mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
Fix nested tag with "Ping-Pong" repeat mode causes to skip the first frame of the parent tag (fix #4271)
This commit is contained in:
parent
d886e20f6c
commit
99e6e7bd82
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (C) 2021-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2021-2024 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -185,8 +185,19 @@ void Playback::handleEnterFrame(const frame_t frameDelta, const bool firstTime)
|
||||
}
|
||||
else {
|
||||
addTag(t, false, forward);
|
||||
if (!firstTime)
|
||||
if (!firstTime) {
|
||||
goToFirstTagFrame(t);
|
||||
// Handle cases where inner tags will jump to different
|
||||
// frames several times recursively (e.g. one reverse
|
||||
// inside other reverse).
|
||||
//
|
||||
// Consideration for tests:
|
||||
// Playback.OnePingPongInsidePingPongReverse
|
||||
// Playback.OneReverseInsidePingPongReverse
|
||||
// Playback.OnePingPongReverseInsideReverse
|
||||
if (frame != m_frame)
|
||||
handleEnterFrame(frameDelta, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -457,10 +468,11 @@ bool Playback::decrementRepeat(const frame_t frameDelta)
|
||||
|
||||
// New frame outside the tag
|
||||
frame_t newFrame;
|
||||
if (rewind) {
|
||||
if (rewind && !m_playing.empty()) {
|
||||
newFrame = firstTagFrame(m_playing.back()->tag);
|
||||
}
|
||||
else {
|
||||
// Note that 'tag' means 'the last tag removed from m_playing'
|
||||
newFrame = (frameDelta * forward < 0 ? tag->fromFrame()-1: tag->toFrame()+1);
|
||||
}
|
||||
|
||||
@ -473,10 +485,100 @@ bool Playback::decrementRepeat(const frame_t frameDelta)
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
if (newFrame < 0)
|
||||
newFrame = m_sprite->lastFrame();
|
||||
else if (newFrame > m_sprite->lastFrame())
|
||||
newFrame = 0;
|
||||
if (newFrame < 0) {
|
||||
// m_playing.empty() should never happen, because the only
|
||||
// way to have "newFrame < 0" is if we have a tag on
|
||||
// m_playing in REVERSE or PING_PONG_REVERSE which frame 0
|
||||
// is contained into that tag.
|
||||
ASSERT(!m_playing.empty());
|
||||
if (m_playing.empty()) {
|
||||
newFrame = m_sprite->lastFrame();
|
||||
}
|
||||
else {
|
||||
// Special cases arise with PING_PONG_REVERSE aniDir and when
|
||||
// the begining of the tag range matches with the first frame of
|
||||
// the sprite.
|
||||
// Consideration for tests inside:
|
||||
// Playback.OnePingPongInsideOther
|
||||
// A A
|
||||
// >-------< >-------<
|
||||
// B B
|
||||
// <---> >---<
|
||||
// 0 1 2 3 4 0 1 2 3 4
|
||||
PlayTag* parentPlaying = m_playing.back().get();
|
||||
// When parentPlaying is PING_PONG_REVERSE
|
||||
// the next frame will be defined according:
|
||||
// 1. The playloop has more repetitions to decrement
|
||||
// --> go to the next frame of the 'tag'
|
||||
// 2. The playloop has no more repetitions to decrement
|
||||
// --> Start all the playloop again.
|
||||
if (parentPlaying->repeat > 1) {
|
||||
if (parentPlaying->tag->aniDir() == AniDir::PING_PONG_REVERSE)
|
||||
parentPlaying->invertForward();
|
||||
--parentPlaying->repeat;
|
||||
newFrame = tag->toFrame() + 1;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (newFrame > m_sprite->lastFrame()) {
|
||||
// If all the tags were played and
|
||||
// the 'tag' range == timeline range and
|
||||
// the 'tag' is PING_PONG_REVERSE -->
|
||||
// The playloop has to start on the last frame of
|
||||
// the timeline, or the first frame of the most nested
|
||||
// tag (on reverse direction).
|
||||
// Consideration for tests:
|
||||
// Playback.WithTagRepetitions
|
||||
// Playback.OnePingPongInsideOther
|
||||
// Playback.OnePingPongInsideOther14, 15, 18 and 19
|
||||
// A <-- last tag removed from 'm_playing', i.e. 'tag'
|
||||
// >-----<
|
||||
// B <-- most nested tag
|
||||
// ***-***
|
||||
// 0 1 2 3
|
||||
if (m_playing.empty() &&
|
||||
tag->aniDir() == AniDir::PING_PONG_REVERSE &&
|
||||
tag->fromFrame() == 0 &&
|
||||
tag->toFrame() == m_sprite->lastFrame()) {
|
||||
m_frame = m_sprite->lastFrame();
|
||||
handleEnterFrame(frameDelta, false);
|
||||
if (m_playing.size() > 1) {
|
||||
m_playing.back()->invertForward();
|
||||
goToFirstTagFrame(m_playing.back()->tag);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'tag' is contained by other tag and the last frame of each tag
|
||||
// matches in the last frame of the sprite
|
||||
if (!m_playing.empty() &&
|
||||
tag->toFrame() == m_playing.back()->tag->toFrame()) {
|
||||
PlayTag* parentPlaying = m_playing.back().get();
|
||||
// The parentPlaying has no more repetitions to decrement
|
||||
// --> continue to remove the 'parentTag'
|
||||
if (parentPlaying->repeat <= 1)
|
||||
continue;
|
||||
// Consideration for test:
|
||||
// Playback.OnePingPongInsideOther
|
||||
if (parentPlaying->tag->aniDir() == AniDir::PING_PONG ||
|
||||
parentPlaying->tag->aniDir() == AniDir::PING_PONG_REVERSE) {
|
||||
parentPlaying->invertForward();
|
||||
newFrame = tag->fromFrame() - 1;
|
||||
}
|
||||
// Consideration for test:
|
||||
// Playback.OnePingPongInsideForward2
|
||||
else if (parentPlaying->tag->aniDir() == AniDir::FORWARD) {
|
||||
--parentPlaying->repeat;
|
||||
newFrame = parentPlaying->tag->fromFrame();
|
||||
}
|
||||
else
|
||||
newFrame = 0;
|
||||
}
|
||||
else
|
||||
newFrame = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_frame = newFrame;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (c) 2021-2022 Igara Studio S.A.
|
||||
// Copyright (c) 2021-2024 Igara Studio S.A.
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -152,6 +152,47 @@ TEST(Playback, WithTagRepetitions)
|
||||
play = Playback(sprite.get(), 0, Playback::Mode::PlayAll);
|
||||
expect_frames(play, {0,1,2,1,2,3,0,0,0});
|
||||
EXPECT_TRUE(play.isStopped());
|
||||
|
||||
Tag* b = make_tag("B", 0, 3, AniDir::PING_PONG, 2);
|
||||
sprite = make_sprite(4, { b });
|
||||
play = Playback(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0,1,2,3,2,1,0,
|
||||
0,1,2,3,2,1,0,
|
||||
0,1,2,3,2,1,0});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
|
||||
Tag* c = make_tag("C", 0, 3, AniDir::PING_PONG_REVERSE, 2);
|
||||
sprite = make_sprite(4, { c });
|
||||
play = Playback(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0,1,2,3,
|
||||
3,2,1,0,1,2,3,
|
||||
3,2,1,0,1,2,3});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
|
||||
Tag* d = make_tag("D", 0, 3, AniDir::PING_PONG_REVERSE, 2);
|
||||
sprite = make_sprite(4, { d });
|
||||
play = Playback(sprite.get(), 1, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {1,0,1,2,3,
|
||||
3,2,1,0,1,2,3,
|
||||
3,2,1,0,1,2,3});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
|
||||
Tag* e = make_tag("E", 0, 3, AniDir::PING_PONG_REVERSE, 1);
|
||||
sprite = make_sprite(4, { e });
|
||||
play = Playback(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0,
|
||||
3,2,1,0,
|
||||
3,2,1,0,
|
||||
3,2,1,0});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
|
||||
Tag* f = make_tag("F", 0, 3, AniDir::REVERSE, 2);
|
||||
sprite = make_sprite(4, { f });
|
||||
play = Playback(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0,3,2,1,0,
|
||||
3,2,1,0, 3,2,1,0,
|
||||
3,2,1,0, 3,2,1,0});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, LoopTagInfinite)
|
||||
@ -464,39 +505,359 @@ TEST(Playback, PingPongWithInnerReverse)
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
// OnePingPongInsideOther series
|
||||
static std::vector<int> goRight(const int a, const int b) {
|
||||
std::vector<int> out;
|
||||
if (a > b)
|
||||
return out;
|
||||
for (int i=a; i<=b ; ++i)
|
||||
out.push_back(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::vector<int> goLeft(const int a, const int b) {
|
||||
std::vector<int> out;
|
||||
if (a > b)
|
||||
return out;
|
||||
for (int i=b; i>=a ; --i)
|
||||
out.push_back(i);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void concat(std::vector<int>& a, const std::vector<int>& b)
|
||||
{
|
||||
for (size_t i=0; i<b.size(); ++i)
|
||||
a.push_back(b[i]);
|
||||
}
|
||||
|
||||
TEST(Playback, OnePingPongInsideOther)
|
||||
{
|
||||
// A
|
||||
// <------->
|
||||
// B
|
||||
// >---<
|
||||
// 0 1 2 3 4
|
||||
// A repeat = 2 ; B repeat = 2
|
||||
//
|
||||
// A A A
|
||||
// *-------* *-------* *-------*
|
||||
// B B B
|
||||
// *---* *---* *---*
|
||||
// 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
|
||||
const int lastFrame = 4;
|
||||
std::vector<AniDir> A_AniDirs = {AniDir::PING_PONG, AniDir::PING_PONG_REVERSE};
|
||||
std::vector<AniDir> B_AniDirs = {AniDir::PING_PONG, AniDir::PING_PONG_REVERSE};
|
||||
std::vector<int> A_Range = {0,lastFrame};
|
||||
std::vector<std::vector<int>> rangeBs = {{0,2}, {1,3}, {2,4}};
|
||||
std::vector<std::vector<int>> pingPongSeq1 = {{0,1,2,1,0}, {2,1,0,1,2}};
|
||||
std::vector<std::vector<int>> pingPongSeq2 = {{1,2,3,2,1}, {3,2,1,2,3}};
|
||||
std::vector<std::vector<int>> pingPongSeq3 = {{2,3,4,3,2}, {4,3,2,3,4}};
|
||||
std::vector<int> right012 = {0,1,2};
|
||||
|
||||
Tag* tagA = make_tag("A", 0, 4, AniDir::PING_PONG, 2);
|
||||
Tag* tagB = make_tag("B", 1, 3, AniDir::PING_PONG_REVERSE, 3);
|
||||
auto sprite = make_sprite(5, { tagA, tagB });
|
||||
for (auto A_aniDir : A_AniDirs) {
|
||||
for (auto B_aniDir : B_AniDirs) {
|
||||
for (auto B_Range : rangeBs) {
|
||||
std::vector<int> expected;
|
||||
std::vector<int> temp;
|
||||
// A A A
|
||||
// <-------> <-------> <------->
|
||||
// B B B
|
||||
// *---* *---* *---*
|
||||
// 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
|
||||
if (A_aniDir == doc::AniDir::PING_PONG) {
|
||||
|
||||
// Start
|
||||
temp = goRight(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
|
||||
// Tag B playback
|
||||
if (B_Range[0] == 0)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[0] : right012);
|
||||
else if (B_Range[0] == 1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[0] : pingPongSeq2[1]);
|
||||
else if (B_Range[0] == 2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[0] : pingPongSeq3[1]);
|
||||
|
||||
// Reproduce right side of the tag A
|
||||
temp = goRight(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
temp = goLeft(B_Range[1]+1, lastFrame-1);
|
||||
concat(expected, temp);
|
||||
|
||||
// Tag B playback (only if tag B last frame doesn't match with the tag A last frame
|
||||
if (B_Range[1] != A_Range[1]) {
|
||||
if (B_Range[1] == lastFrame - 1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[1] : pingPongSeq2[0]);
|
||||
else if (B_Range[1] == lastFrame - 2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[1] : pingPongSeq1[0]);
|
||||
}
|
||||
|
||||
// Reproduce right side of the tag A
|
||||
temp = goLeft(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
}
|
||||
// A A A
|
||||
// >-------< >-------< >-------<
|
||||
// B B B
|
||||
// *---* *---* *---*
|
||||
// 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
|
||||
else {
|
||||
|
||||
// Start
|
||||
temp = goRight(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
|
||||
// Tag B playback
|
||||
if (B_Range[0] == 0)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[0] : right012);
|
||||
else if (B_Range[0] == 1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[0] : pingPongSeq2[1]);
|
||||
else if (B_Range[0] == 2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[0] : pingPongSeq3[1]);
|
||||
|
||||
// Reproduce right side of the tag A
|
||||
temp = goRight(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
|
||||
// New Start
|
||||
temp = goLeft(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
|
||||
// Tag B playback
|
||||
if (B_Range[1] == lastFrame)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[1] : pingPongSeq3[0]);
|
||||
else if (B_Range[1] == lastFrame-1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[1] : pingPongSeq2[0]);
|
||||
else if (B_Range[1] == lastFrame-2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[1] : pingPongSeq1[0]);
|
||||
|
||||
// Reproduce left side of the tag A
|
||||
temp = goLeft(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
temp = goRight(1, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
|
||||
// Tag B playback (only if tag B first frame doesn't match with the tag A first frame
|
||||
if (B_Range[0] == 1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[0] : pingPongSeq2[1]);
|
||||
else if (B_Range[0] == 2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[0] : pingPongSeq3[1]);
|
||||
|
||||
|
||||
// Reproduce right side of the tag A
|
||||
temp = goRight(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
}
|
||||
|
||||
// Test
|
||||
Tag* tagA = make_tag("A", 0, 4, A_aniDir, 2);
|
||||
Tag* tagB = make_tag("B", B_Range[0], B_Range[1], B_aniDir, 2);
|
||||
auto sprite = make_sprite(lastFrame + 1, { tagA, tagB });
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
|
||||
expect_frames(play, expected);
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Playback, OnePingPongInsideOther1Repeat)
|
||||
{
|
||||
// A repeat = 1 ; B repeat = 1
|
||||
//
|
||||
// A A A
|
||||
// *-------* *-------* *-------*
|
||||
// B B B
|
||||
// *---* *---* *---*
|
||||
// 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
|
||||
|
||||
const int lastFrame = 4;
|
||||
std::vector<AniDir> A_AniDirs = {AniDir::PING_PONG, AniDir::PING_PONG_REVERSE};
|
||||
std::vector<AniDir> B_AniDirs = {AniDir::PING_PONG, AniDir::PING_PONG_REVERSE};
|
||||
std::vector<int> A_Range = {0,lastFrame};
|
||||
std::vector<std::vector<int>> rangeBs = {{0,2}, {1,3}, {2,4}};
|
||||
std::vector<std::vector<int>> pingPongSeq1 = {{0,1,2}, {2,1,0}};
|
||||
std::vector<std::vector<int>> pingPongSeq2 = {{1,2,3}, {3,2,1}};
|
||||
std::vector<std::vector<int>> pingPongSeq3 = {{2,3,4}, {4,3,2}};
|
||||
|
||||
for (auto A_aniDir : A_AniDirs) {
|
||||
for (auto B_aniDir : B_AniDirs) {
|
||||
for (auto B_Range : rangeBs) {
|
||||
std::vector<int> expected;
|
||||
std::vector<int> temp;
|
||||
// A A A
|
||||
// <-------> <-------> <------->
|
||||
// B B B
|
||||
// *---* *---* *---*
|
||||
// 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
|
||||
if (A_aniDir == doc::AniDir::PING_PONG) {
|
||||
|
||||
// Start
|
||||
temp = goRight(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
// Tag B playback
|
||||
if (B_Range[0] == 0) {
|
||||
temp = {0};
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[0] : temp);
|
||||
}
|
||||
else if (B_Range[0] == 1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[0] : pingPongSeq2[1]);
|
||||
else if (B_Range[0] == 2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[0] : pingPongSeq3[1]);
|
||||
// Reproduce right side of the tag A
|
||||
temp = goRight(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
|
||||
// Fresh sequence start
|
||||
temp = goRight(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
// Tag B playback
|
||||
if (B_Range[0] == 0)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[0] : pingPongSeq1[1]);
|
||||
else if (B_Range[0] == 1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[0] : pingPongSeq2[1]);
|
||||
else if (B_Range[0] == 2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[0] : pingPongSeq3[1]);
|
||||
// Reproduce right side of the tag A
|
||||
temp = goRight(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
|
||||
}
|
||||
// A A A
|
||||
// >-------< >-------< >-------<
|
||||
// B B B
|
||||
// *---* *---* *---*
|
||||
// 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
|
||||
else {
|
||||
// Start
|
||||
temp = {0};
|
||||
// Tag B playback
|
||||
if (B_Range[0] == 0 && B_aniDir == doc::AniDir::PING_PONG)
|
||||
concat(expected, pingPongSeq1[0]);
|
||||
else
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
|
||||
// Fresh sequence start
|
||||
// Reproduce right side of the tag A
|
||||
temp = goLeft(B_Range[1]+1, lastFrame);
|
||||
concat(expected, temp);
|
||||
|
||||
// Tag B playback
|
||||
if (B_Range[1] == lastFrame)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq3[1] : pingPongSeq3[0]);
|
||||
else if (B_Range[1] == lastFrame-1)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq2[1] : pingPongSeq2[0]);
|
||||
else if (B_Range[1] == lastFrame-2)
|
||||
concat(expected, B_aniDir == doc::AniDir::PING_PONG ? pingPongSeq1[1] : pingPongSeq1[0]);
|
||||
|
||||
// Reproduce left side of the tag A
|
||||
temp = goLeft(0, B_Range[0]-1);
|
||||
concat(expected, temp);
|
||||
// Sequence end
|
||||
}
|
||||
|
||||
// Test
|
||||
Tag* tagA = make_tag("A", 0, 4, A_aniDir, 1);
|
||||
Tag* tagB = make_tag("B", B_Range[0], B_Range[1], B_aniDir, 1);
|
||||
auto sprite = make_sprite(lastFrame + 1, { tagA, tagB });
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
|
||||
expect_frames(play, expected);
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Playback, OnePingPongInsideForward)
|
||||
{
|
||||
// A
|
||||
// -------->
|
||||
// B
|
||||
// <--->
|
||||
// 0 1 2 3 4
|
||||
|
||||
Tag* tagA = make_tag("A", 0, 4, AniDir::FORWARD, 2);
|
||||
Tag* tagB = make_tag("B", 2, 4, AniDir::PING_PONG, 2);
|
||||
auto sprite = make_sprite(5, { tagA, tagB });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0,1 , 2,3,4,3,2,
|
||||
0,1 , 2,3,4,3,2});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, OnePingPongInsideForward2)
|
||||
{
|
||||
// A
|
||||
// -------->
|
||||
// B
|
||||
// <--->
|
||||
// 0 1 2 3 4 5
|
||||
|
||||
Tag* tagA = make_tag("A", 1, 5, AniDir::FORWARD, 2);
|
||||
Tag* tagB = make_tag("B", 3, 5, AniDir::PING_PONG, 2);
|
||||
auto sprite = make_sprite(6, { tagA, tagB });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 3,2,1,2,3,2,1, 4, 1,2,3,2,1,2,3, 0,
|
||||
0, 3,2,1,2,3,2,1, 4, 1,2,3,2,1,2,3, 0, });
|
||||
expect_frames(play, {0 , 1,2 , 3,4,5,4,3, 1,2 , 3,4,5,4,3,
|
||||
0 , 1,2 , 3,4,5,4,3, 1,2 , 3,4,5,4,3});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, OnePingPongInsideOther3)
|
||||
TEST(Playback, OnePingPongInsidePingPongReverse)
|
||||
{
|
||||
// A
|
||||
// <------->
|
||||
// B
|
||||
// >---<
|
||||
// 0 1 2 3 4
|
||||
// A
|
||||
// >-------<
|
||||
// B
|
||||
// <--->
|
||||
// 0 1 2 3 4 5
|
||||
|
||||
Tag* tagA = make_tag("A", 0, 4, AniDir::PING_PONG, 3);
|
||||
Tag* tagB = make_tag("B", 1, 3, AniDir::PING_PONG_REVERSE, 2);
|
||||
auto sprite = make_sprite(5, { tagA, tagB });
|
||||
Tag* tagA = make_tag("A", 1, 5, AniDir::PING_PONG_REVERSE, 2);
|
||||
Tag* tagB = make_tag("B", 3, 5, AniDir::PING_PONG, 2);
|
||||
auto sprite = make_sprite(6, { tagA, tagB });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 3,2,1,2,3, 4, 1,2,3,2,1, 0, 3,2,1,2,3, 4,
|
||||
0, 3,2,1,2,3, 4, 1,2,3,2,1, 0, 3,2,1,2,3, 4, 0 });
|
||||
expect_frames(play, {0 , 5,4,3,4,5 , 2,1,2 , 3,4,5,4,3,
|
||||
0 , 5,4,3,4,5 , 2,1,2 , 3,4,5,4,3});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, OneReverseInsidePingPongReverse)
|
||||
{
|
||||
// A
|
||||
// >-------<
|
||||
// B
|
||||
// <----
|
||||
// 0 1 2 3 4 5
|
||||
|
||||
Tag* tagA = make_tag("A", 1, 5, AniDir::PING_PONG_REVERSE, 2);
|
||||
Tag* tagB = make_tag("B", 3, 5, AniDir::REVERSE, 2);
|
||||
auto sprite = make_sprite(6, { tagA, tagB });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0 , 3,4,5,3,4,5 , 2,1,2 , 5,4,3,5,4,3,
|
||||
0 , 3,4,5,3,4,5 , 2,1,2 , 5,4,3,5,4,3});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, OnePingPongReverseInsideReverse)
|
||||
{
|
||||
// A
|
||||
// <--------
|
||||
// B
|
||||
// >---<
|
||||
// 0 1 2 3 4 5
|
||||
|
||||
Tag* tagA = make_tag("A", 1, 5, AniDir::REVERSE, 2);
|
||||
Tag* tagB = make_tag("B", 3, 5, AniDir::PING_PONG_REVERSE, 2);
|
||||
auto sprite = make_sprite(6, { tagA, tagB });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0 , 3,4,5,4,3 , 2,1, 3,4,5,4,3 , 2,1,
|
||||
0 , 3,4,5,4,3 , 2,1, 3,4,5,4,3 , 2,1});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
@ -536,6 +897,96 @@ TEST(Playback, TwoLoopsInCascadeReverse)
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, TwoLoopsInCascadeReversePingPongReverse1)
|
||||
{
|
||||
// A
|
||||
// <----
|
||||
// B
|
||||
// >---<
|
||||
// 0 1 2 3 4
|
||||
|
||||
Tag* a = make_tag("A", 1, 3, AniDir::REVERSE, 2);
|
||||
Tag* b = make_tag("B", 2, 4, AniDir::PING_PONG_REVERSE, 2);
|
||||
auto sprite = make_sprite(5, { a, b });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 3,2,1,3,2,1, 4,3,2,3,4,
|
||||
0, 3,2,1,3,2,1, 4,3,2,3,4, 0 });
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, TwoLoopsInCascadeReversePingPongReverse2)
|
||||
{
|
||||
// A
|
||||
// <------
|
||||
// B
|
||||
// >---<
|
||||
// 0 1 2 3 4
|
||||
|
||||
Tag* a = make_tag("A", 0, 3, AniDir::REVERSE, 2);
|
||||
Tag* b = make_tag("B", 2, 4, AniDir::PING_PONG_REVERSE, 2);
|
||||
auto sprite = make_sprite(5, { a, b });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 3,2,1,0, 4,3,2,3,4,
|
||||
3,2,1,0,3,2,1,0, 4,3,2,3,4 });
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, TwoLoopsInCascadeReversePingPongReverse3)
|
||||
{
|
||||
// A
|
||||
// <--------
|
||||
// B
|
||||
// >---<
|
||||
// 0 1 2 3 4
|
||||
|
||||
Tag* a = make_tag("A", 0, 4, AniDir::REVERSE, 2);
|
||||
Tag* b = make_tag("B", 2, 4, AniDir::PING_PONG_REVERSE, 2);
|
||||
auto sprite = make_sprite(5, { a, b });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 2,3,4,3,2, 1,0,
|
||||
2,3,4,3,2, 1,0, 2,3,4,3,2, 1,0,});
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, TwoLoopsInCascadePingPongReverseReverse1)
|
||||
{
|
||||
// A
|
||||
// >-----<
|
||||
// B
|
||||
// <----
|
||||
// 0 1 2 3 4
|
||||
|
||||
Tag* a = make_tag("A", 0, 3, AniDir::PING_PONG_REVERSE, 2);
|
||||
Tag* b = make_tag("B", 2, 4, AniDir::REVERSE, 2);
|
||||
auto sprite = make_sprite(5, { a, b });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 1,2,3, 4,3,2,4,3,2,
|
||||
3,2,1,0,1,2,3, 4,3,2,4,3,2 });
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, TwoLoopsInCascadePingPongReverseReverse2)
|
||||
{
|
||||
// A
|
||||
// >---<
|
||||
// B
|
||||
// <----
|
||||
// 0 1 2 3 4
|
||||
|
||||
Tag* a = make_tag("A", 1, 3, AniDir::PING_PONG_REVERSE, 2);
|
||||
Tag* b = make_tag("B", 2, 4, AniDir::REVERSE, 2);
|
||||
auto sprite = make_sprite(5, { a, b });
|
||||
|
||||
Playback play(sprite.get(), 0, Playback::Mode::PlayInLoop);
|
||||
expect_frames(play, {0, 3,2,1,2,3, 4,3,2,4,3,2,
|
||||
0, 3,2,1,2,3, 4,3,2,4,3,2, 0 });
|
||||
EXPECT_FALSE(play.isStopped());
|
||||
}
|
||||
|
||||
TEST(Playback, ThreeLoopsInCascade)
|
||||
{
|
||||
// A
|
||||
|
Loading…
x
Reference in New Issue
Block a user