1 | // Aseprite Document Library |
---|---|
2 | // Copyright (C) 2019-2022 Igara Studio S.A. |
3 | // Copyright (C) 2001-2016 David Capello |
4 | // |
5 | // This file is released under the terms of the MIT license. |
6 | // Read LICENSE.txt for more information. |
7 | |
8 | #ifdef HAVE_CONFIG_H |
9 | #include "config.h" |
10 | #endif |
11 | |
12 | #include "doc/handle_anidir.h" |
13 | |
14 | #include "doc/frame.h" |
15 | #include "doc/sprite.h" |
16 | #include "doc/tag.h" |
17 | |
18 | namespace doc { |
19 | |
20 | frame_t calculate_next_frame( |
21 | const Sprite* sprite, |
22 | frame_t frame, |
23 | frame_t frameDelta, |
24 | const Tag* tag, |
25 | bool& pingPongForward) |
26 | { |
27 | if (frameDelta == 0) |
28 | return frame; |
29 | |
30 | frame_t first = frame_t(0); |
31 | frame_t last = sprite->lastFrame(); |
32 | AniDir aniDir = AniDir::FORWARD; |
33 | |
34 | if (tag) { |
35 | frame_t loopFrom, loopTo; |
36 | |
37 | loopFrom = tag->fromFrame(); |
38 | loopTo = tag->toFrame(); |
39 | loopFrom = std::clamp(loopFrom, first, last); |
40 | loopTo = std::clamp(loopTo, first, last); |
41 | |
42 | first = loopFrom; |
43 | last = loopTo; |
44 | aniDir = tag->aniDir(); |
45 | } |
46 | |
47 | frame_t frameRange = (last - first + 1); |
48 | |
49 | switch (aniDir) { |
50 | |
51 | case AniDir::REVERSE: |
52 | frameDelta = -frameDelta; |
53 | [[fallthrough]]; |
54 | |
55 | case AniDir::FORWARD: |
56 | frame += frameDelta; |
57 | while (frame > last) frame -= frameRange; |
58 | while (frame < first) frame += frameRange; |
59 | break; |
60 | |
61 | case AniDir::PING_PONG: { |
62 | bool invertPingPong; |
63 | if (frameDelta < 0) { |
64 | frameDelta = -frameDelta; |
65 | pingPongForward = !pingPongForward; |
66 | invertPingPong = true; |
67 | } |
68 | else |
69 | invertPingPong = false; |
70 | |
71 | while (--frameDelta >= 0) { |
72 | if (pingPongForward) { |
73 | ++frame; |
74 | if (frame > last) { |
75 | frame = last-1; |
76 | if (frame < first) |
77 | frame = first; |
78 | pingPongForward = false; |
79 | } |
80 | } |
81 | else { |
82 | --frame; |
83 | if (frame < first) { |
84 | frame = first+1; |
85 | if (frame > last) |
86 | frame = last; |
87 | pingPongForward = true; |
88 | } |
89 | } |
90 | } |
91 | |
92 | if (invertPingPong) |
93 | pingPongForward = !pingPongForward; |
94 | break; |
95 | } |
96 | } |
97 | |
98 | return frame; |
99 | } |
100 | |
101 | } // namespace doc |
102 |