Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Starting Animations using Scene.play while others are running #1267

Open
AntonBallmaier opened this issue Apr 6, 2021 · 3 comments
Open
Labels
Suggestion Requesting a feature or change for Manim

Comments

@AntonBallmaier
Copy link
Contributor

AntonBallmaier commented Apr 6, 2021

First of all: This might just as well be a bug report - I am unsure...

Motivation

Look at the following scene:

WantedScene.mp4

Swiping a line across the Scene and playing a Flash as soon as it hits a dot... Or more generally: Animate one thing and play additional animations based on the state of the animated thing. Sounds like a job for an update function. Consider the following code:

class UsingUpdater(Scene):
    def construct(self):
        #Setup
        dots = VGroup(*[Dot(RIGHT*random.randrange(-6, 6)+UP*random.randrange(-2, 2)) for i in range(10)])
        line = Line(UP*3, DOWN*3).align_on_border(LEFT)
        self.add(dots)
        self.play(Create(line))

        #Updater
        def flash_hit_dots(mob):
            for dot in dots:
                if dot.get_center()[0] < mob.get_center()[0] and not hasattr(dot, "marked"):
                    self.play(Flash(dot, run_time=0.5))
                    dot.marked = True
        line.add_updater(flash_hit_dots)

        #Animate Line
        self.play(line.animate.align_on_border(RIGHT), run_time=5)
        self.wait()

However, this results in ValueError: write to closed file.

Description of proposed feature

The feature request is quite simple, but I think it is hard to implement: Allow using Scene.play() while an Animation is running.

Additional comments

I have seen quite a few different workarounds for this problem, even in 3b1b's code. Some are based on splitting the animation at each new event, others are based on precalculating all timings in advance - but all of them have one thing in common: They are tedious and error-prone. In case you are wondering, how I created the example Scene: Have a look at this mess...

class Workaround(Scene):
    def construct(self):
        #Setup
        dots = VGroup(*[Dot(RIGHT*random.randrange(-6, 6)+UP*random.randrange(-2, 2)) for i in range(10)])
        line = Line(UP*3, DOWN*3).align_on_border(LEFT)
        self.add(dots)
        self.play(Create(line))

        run_time = 5
        rate_func = smooth
        fps = config["frame_rate"]
        
        #First pass to determine frames to start the flash:
        animations = []
        frames = run_time*fps
        x_0 = line.get_center()[0]
        x_1 = line.copy().align_on_border(RIGHT).get_center()[0]
        for t in range(frames):
            alpha = rate_func(t/frames)
            x = x_0 + alpha*(x_1-x_0)
            for dot in dots:
                if dot.get_center()[0] < x and not hasattr(dot, "marked"):
                    #create dummy wait animation:
                    wait = FadeOut(Mobject(), run_time=t/fps)
                    animations.append(AnimationGroup(wait, Flash(dot, run_time=0.5), lag_ratio=1))
                    dot.marked = True
        
        #Run the animations
        self.play(AnimationGroup(
            ApplyMethod(line.align_on_border, RIGHT, run_time=run_time, rate_func=rate_func),
            *animations
        ))
        self.wait()
@AntonBallmaier AntonBallmaier added the new feature Enhancement specifically adding a new feature (feature request should be used for issues instead) label Apr 6, 2021
@markromanmiller
Copy link
Collaborator

You are correct in judging this a feature and not a bug report - as far as I know we don't expect .play() to be called in an animation. But it could certainly have a more straightforward error message, I think.

From an interface perspective, I think it makes a lot of sense to enable this - perhaps with a flag indicating it's a non-blocking animation (i.e, set the animation to start and then return from the function, don't go forward in the animation within that call to .play(). I'd worry that would require significant refactoring within the code, but it might not, considering LaggedStart and things basically do the same.

Edge case: what happens when in an updater starts an animation near the end of the other animation? Perhaps we should add something that tells the scene to wait for all unblocking animations to finish?

@jsonvillanueva jsonvillanueva added Suggestion Requesting a feature or change for Manim and removed new feature Enhancement specifically adding a new feature (feature request should be used for issues instead) labels Apr 17, 2021
@cckk4467
Copy link

From an interface perspective, I think it makes a lot of sense to enable this - perhaps with a flag indicating it's a non-blocking animation (i.e, set the animation to start and then return from the function, don't go forward in the animation within that call to .play(). I'd worry that would require significant refactoring within the code, but it might not, considering LaggedStart and things basically do the same.

capable to set/unset animation blocking means a lot. And yes, it seems have no need of entire rewriting of the animations part.
Could we see it in 0.6.0? XD

@markromanmiller
Copy link
Collaborator

Could we see it in 0.6.0? XD

probably not, but I'd love to see a PR for it.

@ManimCommunity ManimCommunity locked and limited conversation to collaborators Jun 16, 2022
@MrDiver MrDiver converted this issue into discussion #2788 Jun 16, 2022
@MrDiver MrDiver moved this to 🆕 New in Dev Board Jun 18, 2022
@MrDiver MrDiver reopened this Jun 18, 2022
Repository owner moved this from 🆕 New to 📋 Backlog in Dev Board Jun 18, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
Suggestion Requesting a feature or change for Manim
Projects
Status: 📋 Backlog
Development

Successfully merging a pull request may close this issue.

5 participants