Repository: ManimCommunity/manim
File: manim/animation/updaters/mobject_update_utils.py (Python)

Code before:


def always_redraw(func):
    """Redraw a mobject every frame.

    .. manim:: TangentAnimation

        class TangentAnimation(Scene):
            def construct(self):
                ax = Axes()
                sine = ax.plot(np.sin, color=RED)
                alpha = ValueTracker(0)
                point = always_redraw(
                        lambda: Dot(
                            sine.point_from_proportion(alpha.get_value()),
                            color=BLUE)
                    )
                tangent = always_redraw(
                    lambda: TangentLine(
                        sine,
                        alpha=alpha.get_value(),
                        color=YELLOW,
                        length=4)
                )
                self.play(Create(ax), Create(sine), Create(point), Create(tangent))
                self.play(alpha.animate.set_value(1), rate_func=linear, run_time=3)
    """
    mob = func()
    mob.add_updater(lambda _: mob.become(func()))
    return mob


def always_shift(mobject, direction=RIGHT, rate=0.1):
    def normalize(v):
        norm = np.linalg.norm(v)
        if norm == 0:
            return v
        return v / norm

    mobject.add_updater(lambda m, dt: m.shift(dt * rate * normalize(direction)))
    return mobject


def always_rotate(mobject, rate=20 * DEGREES, **kwargs):
    mobject.add_updater(lambda m, dt: m.rotate(dt * rate, **kwargs))
    return mobject


def turn_animation_into_updater(animation, cycle=False, **kwargs):
    """
    Add an updater to the animation's mobject which applies

Review comment (suggestion):
Looking at the latest RTD build logs for this PR (https://readthedocs.org/api/v2/build/21513650.txt), this example currently adds about 7 seconds of render time to the documentation, which is (compared to other examples) a bit much.

I suggest to reduce the rendered length of the example a bit further; for example by removing the creation part of the animation and further reducing the run time of the actual animation. It would be good to get the render time below one second (although this is more of a personal preference rather than a set-in-stone rule that we have).

```suggestion
                self.add(ax, sine, point, tangent)
                self.play(alpha.animate.set_value(1), rate_func=linear, run_time=2)
```

Code after:
    return mobject


def always_redraw(func: Callable[[], Mobject]) -> Mobject:
    """Redraw the mobject constructed by a function every frame.

    This function returns a mobject with an attached updater that
    continuously regenerates the mobject according to the
    specified function.

    Parameters
    ----------
    func
        A function without (required) input arguments that returns
        a mobject.

    Examples
    --------

    .. manim:: TangentAnimation

        class TangentAnimation(Scene):
            def construct(self):
                ax = Axes()
                sine = ax.plot(np.sin, color=RED)
                alpha = ValueTracker(0)
                point = always_redraw(
                        lambda: Dot(
                            sine.point_from_proportion(alpha.get_value()),
                            color=BLUE)
                    )
                tangent = always_redraw(
                    lambda: TangentLine(
                        sine,
                        alpha=alpha.get_value(),
                        color=YELLOW,
                        length=4)
                )
                self.add(ax, sine, point, tangent)
                self.play(alpha.animate.set_value(1), rate_func=linear, run_time=2)
    """
    mob = func()
    mob.add_updater(lambda _: mob.become(func()))
    return mob


def always_shift(mobject, direction=RIGHT, rate=0.1):
    def normalize(v):
        norm = np.linalg.norm(v)
        if norm == 0:
            return v