New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added is_running
attribute to :class:~.Animation
and made :class:~.AnimationGroup
aware of running animations
#747
Added is_running
attribute to :class:~.Animation
and made :class:~.AnimationGroup
aware of running animations
#747
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good stuff.
manim/animation/composition.py
Outdated
if hasattr(anim, 'starting_mobject'): | ||
anim.update_mobjects(dt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: an animation only has a starting_object
if its begin()
method has been called, correct? So this conditional is checking whether the animation is currently running?
If so, we should make note to implement a cleaner way of doing that in the future. Not in this PR tho.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I've looked at today, I think there are some animations that don't set starting_object
when their begin
is called. It might actually be better to refactor this still on this PR: maybe by adding a boolean has_started
set to False
on Animation.__init__
, and to true in all the implementing begin
methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Suggest is_running
.
manim/animation/composition.py
Outdated
def finish(self): | ||
for anim in self.animations: | ||
anim.finish() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see why this finish has to go. But if we just delete it, then the parent class' finish
method will be called. For extra clarity, we may just want to override finish
with a pass
so that the parent class is not called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't really investigated what finish
actually does for animations, but it sounds like a good approach.
I've been trying to investigate the two errors in for What could be broken here that |
Looked into it for a bit for I got nothing 🤔 |
Sure, but as you say: in this case, the data seems reasonable to me. What worries me is that I don't obtain the same fragments (i.e., the Square and the remaining
I was also wondering about that; I'm not sure. Maybe Flash is mainly supposed to be used with Dot etc.? |
What do you mean? It is probably normal due ot the t value issue #183. (maybe).
Aaaand. I don't know. Probably. |
Flash is located at the center of the Mobject. I don't know if there is a way of changing the radius around the center. But what you got seems to me what is intended. I agree with @behackl , I think there is something else going on here. |
Look at the images I've posted above: the third one is I don't know why rendering it with |
I'll put some more work into this to implement the refactor discussed with @leotrs above -- but I still need help with figuring out what actually causes the tests to fail. |
I just came back to look at this for a sec. I checked out this branch and rendered both @behackl, the frame you posted is generated with However, the kicker is that I get the same "generated" and "expected" diffs as @behackl does. This means that when ran with pytest, there is a flash, but when rendering a video or last frame, there is no flash. The plot thickens! Note: @huguesdevimeux originally posted the result of rendering these on master, not on this branch. Also, he rendered |
49d7dbb
to
59484bf
Compare
I sort of forgot about this PR for a while; I've now incorporated the changes discussed above:
Ready for review. |
is_running
attribute to :class:~.Animation
and made :class:~.AnimationGroup
aware of running animations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good generally, but I think something broke due to recent changes in the library since this has last been looked at... particularly with the following code:
class MyTest(Scene):
def construct(self):
s = Square()
self.play(
AnimationGroup(
s.animate.shift(LEFT),
s.animate.shift(RIGHT),
lag_ratio=1
)
)
MyTest.mp4
Actually, even using the earlier example above:
class MyTest(Scene):
def construct(self):
sq = Square(color=color.RED, fill_opacity=0.7)
anim = AnimationGroup(
ApplyMethod(sq.shift, LEFT),
ApplyMethod(sq.shift, RIGHT),
lag_ratio=1
)
self.play(anim)
self.wait()
MyTest.mp4
I forgot to update the PR description. The problem with the example there is that multiple animations are applied to the same mobject, which is discouraged in general. The intention of this PR was that class AG(Scene):
def construct(self):
s1, s2, s3 = (Square() for _ in range(3))
VGroup(s1, s2, s3).arrange(DOWN).center()
self.play(
AnimationGroup(
s1.animate.shift(RIGHT).set(fill_opacity=1),
s2.animate.shift(RIGHT).set(fill_opacity=1),
s3.animate.shift(RIGHT).set(fill_opacity=1),
lag_ratio=1
)
) should essentially behave like class AG(Scene):
def construct(self):
s1, s2, s3 = (Square() for _ in range(3))
VGroup(s1, s2, s3).arrange(DOWN).center()
self.play(s1.animate.shift(RIGHT).set(fill_opacity=1))
self.play(s2.animate.shift(RIGHT).set(fill_opacity=1))
self.play(s3.animate.shift(RIGHT).set(fill_opacity=1)) (In particular: the mobjects shouldn't all be added at the beginning of the animation, but only when it is "their turn" in the animation timeline.) However, after just checking my example again, it doesn't seem like this PR is changing this behavior. I'm leaning towards simply closing this PR for now -- the animations in |
It would definitely be nice to provide time ranges for AnimationGroup with start/end times individually... rather than having to sort out the math with lag_ratio/length. Definitely an enhancement needed here. But since this PR isn't changing the behavior, whether you wish to close this PR and reopen in the future, or start a new PR altogether, I'd be interested in setting start/end times directly. |
Motivation
There are two severe issues with how
AnimationGroup
runs right now (that this PR is concerned with 🙃):AnimationGroup.interpolate
callsinterpolate
on all animations included in the group, independent of whether the animation time is within their correspondingstart_time
/end_time
intervals determined byAnimationGroup.build_animations_with_timings
.AnimationGroup.begin
currently causes all included animations to callbegin()
at the beginning of the group. This causes problems in situations where the same mobject is animated in several different animations in an AnimationGroup.Explanation for Changes
The first issue is solved in a more or less clean way, for the second I am not really sure that calling
begin
andfinish
in the way currently implemented by this PR will work in all situations. If someone more familiar with animations has a better idea, I'd appreciate it.Testing Status
This fixes the behavior in the example
as discussed on Discord, and the square first moves left, and then right:
Acknowledgement