From 1d6621e0b0c61246630ec116c51e8d543a303cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 09:43:56 -0300 Subject: [PATCH 01/10] Improve docstrings and typings in mobject_update_utils, and add examples for always and f_always --- .../updaters/mobject_update_utils.py | 229 ++++++++++++++++-- 1 file changed, 206 insertions(+), 23 deletions(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index dee27ff398..cdcf845e92 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -25,16 +25,98 @@ from manim.utils.space_ops import normalize if TYPE_CHECKING: + from typing_extensions import Any, TypeVar + from manim.animation.animation import Animation + MobjectT = TypeVar("MobjectT", bound=Mobject) + + +def assert_is_mobject_method(method: Callable[[MobjectT], None]) -> None: + """Verify that the given `method` is actually a method and belongs to a + :class:`Mobject` or an :class:`OpenGLMobject`. -def assert_is_mobject_method(method: Callable) -> None: + Parameters + ---------- + method + An object which should be a method of :class:`Mobject` or :class:`OpenGLMobject`. + + Raises + ------ + AssertionError + If `method` is not a method or it doesn't belong to :class:`Mobject` + or :class:`OpenGLMobject`. + """ assert inspect.ismethod(method) mobject = method.__self__ assert isinstance(mobject, (Mobject, OpenGLMobject)) -def always(method: Callable, *args, **kwargs) -> Mobject: +def always(method: Callable[[MobjectT], None], *args: Any, **kwargs) -> MobjectT: + r"""Given the `method` of an existing :class:`Mobject`, apply an updater to + this Mobject which modifies it on every frame by repeatedly calling the method. + Additional arguments, both positional (`args`) and keyword arguments (`kwargs`), + may be passed as arguments to `always`. + + Calling `always(mob.method, ...)` is equivalent to calling + `mob.add_updater(lambda mob: mob.method(...))`. + + Parameters + ---------- + method + A Mobject method to call on each frame. + args + Positional arguments to be passed to `method`. + kwargs + Keyword arguments to be passed to `method`. + + Returns + ------- + :class:`Mobject` + The same Mobject whose `method` was passed to `always`, after adding an updater + which repeatedly calls that method. + + Raises + ------ + AssertionError + If `method` is not a method or it doesn't belong to :class:`Mobject` + or :class:`OpenGLMobject`. + + Examples + -------- + + .. manim:: AlwaysUpdatedSquares + + class AlwaysUpdatedSquares(Scene): + def construct(self): + dot_1 = Dot(color=RED).shift(3*LEFT) + dot_2 = Dot(color=BLUE).shift(4*RIGHT) + sq_1 = Square(color=RED) + sq_2 = Square(color=BLUE) + text_1 = Text( + "always(sq_1.next_to, dot_1, DOWN)", + font="Monospace", + color=RED_A, + ).scale(0.4).move_to(2*UP + 4*LEFT) + text_2 = Text( + "sq_2.add_updater(\n\tlambda mob: mob.next_to(dot_2, DOWN)\n)", + font="Monospace", + color=BLUE_A, + ).scale(0.4).move_to(2*UP + 3*RIGHT) + + self.add(dot_1, dot_2, sq_1, sq_2, text_1, text_2) + + # Always place the squares below their respective dots. + # The following two ways are equivalent. + always(sq_1.next_to, dot_1, DOWN) + sq_2.add_updater(lambda mob: mob.next_to(dot_2, DOWN)) + + self.play( + dot_1.animate.shift(2*LEFT), + dot_2.animate.shift(2*LEFT), + run_time=2.0, + ) + """ assert_is_mobject_method(method) mobject = method.__self__ func = method.__func__ @@ -42,11 +124,71 @@ def always(method: Callable, *args, **kwargs) -> Mobject: return mobject -def f_always(method: Callable[[Mobject], None], *arg_generators, **kwargs) -> Mobject: - """ - More functional version of always, where instead - of taking in args, it takes in functions which output +def f_always( + method: Callable[[MobjectT], None], + *arg_generators: Callable[[Any], Any], + **kwargs: Any, +) -> MobjectT: + r"""More functional version of :meth:`always`, where instead + of taking in `args`, it takes in functions which output the relevant arguments. + + Parameters + ---------- + method + A Mobject method to call on each frame. + arg_generators + Functions which, when called, return positional arguments to be passed to `method`. + kwargs + Keyword arguments to be passed to `method`. + + Returns + ------- + :class:`Mobject` + The same Mobject whose `method` was passed to `f_always`, after adding an updater + which repeatedly calls that method. + + Raises + ------ + AssertionError + If `method` is not a method or it doesn't belong to :class:`Mobject` + or :class:`OpenGLMobject`. + + Examples + -------- + + .. manim:: FAlwaysUpdatedSquares + + class FAlwaysUpdatedSquares(Scene): + def construct(self): + sq_1 = Square(color=RED).move_to(DOWN + 4*LEFT) + sq_2 = Square(color=BLUE).move_to(DOWN + 3*RIGHT) + text_1 = Text( + "f_always(sq_1.set_opacity, t.get_value)", + font="Monospace", + color=RED_A, + ).scale(0.35).move_to(UP + 4*LEFT) + text_2 = Text( + "sq_2.add_updater(\n\tlambda mob: mob.set_opacity(t.get_value())\n)", + font="Monospace", + color=BLUE_A, + ).scale(0.35).move_to(UP + 3*RIGHT) + + self.add(sq_1, sq_2, text_1, text_2) + + t = ValueTracker(1.0) + + # Always set the square opacities to the value given by t. + # The following two ways are equivalent. + f_always(sq_1.set_opacity, t.get_value) + sq_2.add_updater( + lambda mob: mob.set_opacity(t.get_value()) + ) + + self.play( + t.animate.set_value(0.1), + run_time=2.0, + ) """ assert_is_mobject_method(method) mobject = method.__self__ @@ -60,10 +202,10 @@ def updater(mob): return mobject -def always_redraw(func: Callable[[], Mobject]) -> Mobject: - """Redraw the mobject constructed by a function every frame. +def always_redraw(func: Callable[[], MobjectT]) -> MobjectT: + """Redraw the Mobject constructed by a function every frame. - This function returns a mobject with an attached updater that + This function returns a Mobject with an attached updater that continuously regenerates the mobject according to the specified function. @@ -71,7 +213,13 @@ def always_redraw(func: Callable[[], Mobject]) -> Mobject: ---------- func A function without (required) input arguments that returns - a mobject. + a Mobject. + + Returns + ------- + :class:`Mobject` + The Mobject returned by the function, after adding an updater to it + which constantly transforms it, according to the given `func`. Examples -------- @@ -106,8 +254,8 @@ def construct(self): def always_shift( - mobject: Mobject, direction: np.ndarray[np.float64] = RIGHT, rate: float = 0.1 -) -> Mobject: + mobject: MobjectT, direction: np.ndarray[np.float64] = RIGHT, rate: float = 0.1 +) -> MobjectT: """A mobject which is continuously shifted along some direction at a certain rate. @@ -122,6 +270,11 @@ def always_shift( Length in Manim units which the mobject travels in one second along the specified direction. + Returns + ------- + :class:`Mobject` + The same Mobject, after adding an updater to it which shifts it continuously. + Examples -------- @@ -144,7 +297,7 @@ def construct(self): return mobject -def always_rotate(mobject: Mobject, rate: float = 20 * DEGREES, **kwargs) -> Mobject: +def always_rotate(mobject: MobjectT, rate: float = 20 * DEGREES, **kwargs) -> MobjectT: """A mobject which is continuously rotated at a certain rate. Parameters @@ -157,6 +310,11 @@ def always_rotate(mobject: Mobject, rate: float = 20 * DEGREES, **kwargs) -> Mob kwags Further arguments to be passed to :meth:`.Mobject.rotate`. + Returns + ------- + :class:`Mobject` + The same Mobject, after adding an updater which rotates it continuously. + Examples -------- @@ -177,15 +335,26 @@ def construct(self): return mobject -def turn_animation_into_updater( - animation: Animation, cycle: bool = False, **kwargs -) -> Mobject: - """ - Add an updater to the animation's mobject which applies - the interpolation and update functions of the animation +def turn_animation_into_updater(animation: Animation, cycle: bool = False) -> Mobject: + """Add an updater to the animation's Mobject, which applies + the interpolation and update functions of the animation. - If cycle is True, this repeats over and over. Otherwise, - the updater will be popped upon completion + If `cycle` is `True`, this repeats over and over. Otherwise, + the updater will be popped upon completion. + + Parameters + ---------- + animation + The animation to convert into an updater. + cycle + Whether to repeat the animation over and over, or do it + only once and remove the updater once finished. + + Returns + ------- + :class:`Mobject` + The Mobject being modified by the original `animation` which + was converted into an updater for this Mobject. Examples -------- @@ -227,5 +396,19 @@ def update(m: Mobject, dt: float): return mobject -def cycle_animation(animation: Animation, **kwargs) -> Mobject: - return turn_animation_into_updater(animation, cycle=True, **kwargs) +def cycle_animation(animation: Animation) -> Mobject: + """Same as `turn_animation_into_updater`, but with `cycle=True`. + + Parameters + ---------- + animation + The animation to convert into an updater which will be repeated + forever. + + Returns + ------- + :class:`Mobject` + The Mobject being modified by the original `animation` which + was converted into an updater for this Mobject. + """ + return turn_animation_into_updater(animation, cycle=True) From b434050b7d19597d5929baf315e1549ec07ca6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 10:09:46 -0300 Subject: [PATCH 02/10] Double backticks, mobject -> Mobject --- .../updaters/mobject_update_utils.py | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index cdcf845e92..2023ca08aa 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -33,7 +33,7 @@ def assert_is_mobject_method(method: Callable[[MobjectT], None]) -> None: - """Verify that the given `method` is actually a method and belongs to a + """Verify that the given ``method`` is actually a method and belongs to a :class:`Mobject` or an :class:`OpenGLMobject`. Parameters @@ -44,7 +44,7 @@ def assert_is_mobject_method(method: Callable[[MobjectT], None]) -> None: Raises ------ AssertionError - If `method` is not a method or it doesn't belong to :class:`Mobject` + If ``method`` is not a method or it doesn't belong to :class:`Mobject` or :class:`OpenGLMobject`. """ assert inspect.ismethod(method) @@ -53,33 +53,33 @@ def assert_is_mobject_method(method: Callable[[MobjectT], None]) -> None: def always(method: Callable[[MobjectT], None], *args: Any, **kwargs) -> MobjectT: - r"""Given the `method` of an existing :class:`Mobject`, apply an updater to + r"""Given the ``method`` of an existing :class:`Mobject`, apply an updater to this Mobject which modifies it on every frame by repeatedly calling the method. - Additional arguments, both positional (`args`) and keyword arguments (`kwargs`), - may be passed as arguments to `always`. + Additional arguments, both positional (``args``) and keyword arguments + (``kwargs``), may be passed as arguments to ``always``. - Calling `always(mob.method, ...)` is equivalent to calling - `mob.add_updater(lambda mob: mob.method(...))`. + Calling ``always(mob.method, ...)`` is equivalent to calling + ``mob.add_updater(lambda mob: mob.method(...))``. Parameters ---------- method A Mobject method to call on each frame. args - Positional arguments to be passed to `method`. + Positional arguments to be passed to ``method``. kwargs - Keyword arguments to be passed to `method`. + Keyword arguments to be passed to ``method``. Returns ------- :class:`Mobject` - The same Mobject whose `method` was passed to `always`, after adding an updater - which repeatedly calls that method. + The same Mobject whose ``method`` was passed to ``always``, after adding + an updater which repeatedly calls that method. Raises ------ AssertionError - If `method` is not a method or it doesn't belong to :class:`Mobject` + If ``method`` is not a method or it doesn't belong to :class:`Mobject` or :class:`OpenGLMobject`. Examples @@ -130,7 +130,7 @@ def f_always( **kwargs: Any, ) -> MobjectT: r"""More functional version of :meth:`always`, where instead - of taking in `args`, it takes in functions which output + of taking in ``args``, it takes in functions which output the relevant arguments. Parameters @@ -138,20 +138,21 @@ def f_always( method A Mobject method to call on each frame. arg_generators - Functions which, when called, return positional arguments to be passed to `method`. + Functions which, when called, return positional arguments to be passed + to ``method``. kwargs - Keyword arguments to be passed to `method`. + Keyword arguments to be passed to ``method``. Returns ------- :class:`Mobject` - The same Mobject whose `method` was passed to `f_always`, after adding an updater - which repeatedly calls that method. + The same Mobject whose ``method`` was passed to ``f_always``, after adding + an updater which repeatedly calls that method. Raises ------ AssertionError - If `method` is not a method or it doesn't belong to :class:`Mobject` + If ``method`` is not a method or it doesn't belong to :class:`Mobject` or :class:`OpenGLMobject`. Examples @@ -206,7 +207,7 @@ def always_redraw(func: Callable[[], MobjectT]) -> MobjectT: """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 + continuously regenerates the Mobject according to the specified function. Parameters @@ -219,7 +220,7 @@ def always_redraw(func: Callable[[], MobjectT]) -> MobjectT: ------- :class:`Mobject` The Mobject returned by the function, after adding an updater to it - which constantly transforms it, according to the given `func`. + which constantly transforms it, according to the given ``func``. Examples -------- @@ -256,19 +257,19 @@ def construct(self): def always_shift( mobject: MobjectT, direction: np.ndarray[np.float64] = RIGHT, rate: float = 0.1 ) -> MobjectT: - """A mobject which is continuously shifted along some direction + """A Mobject which is continuously shifted along some direction at a certain rate. Parameters ---------- mobject - The mobject to shift. + The Mobject to shift. direction The direction to shift. The vector is normalized, the specified magnitude is not relevant. rate - Length in Manim units which the mobject travels in one - second along the specified direction. + Speed (MUnits per second) in which the Mobject travels along the + specified direction. Returns ------- @@ -298,15 +299,14 @@ def construct(self): def always_rotate(mobject: MobjectT, rate: float = 20 * DEGREES, **kwargs) -> MobjectT: - """A mobject which is continuously rotated at a certain rate. + """A Mobject which is continuously rotated at a certain rate. Parameters ---------- mobject - The mobject to be rotated. + The Mobject to be rotated. rate - The angle which the mobject is rotated by - over one second. + The angular speed (angle units per second) in which the Mobject is rotated. kwags Further arguments to be passed to :meth:`.Mobject.rotate`. @@ -339,7 +339,7 @@ def turn_animation_into_updater(animation: Animation, cycle: bool = False) -> Mo """Add an updater to the animation's Mobject, which applies the interpolation and update functions of the animation. - If `cycle` is `True`, this repeats over and over. Otherwise, + If ``cycle`` is ``True``, this repeats over and over. Otherwise, the updater will be popped upon completion. Parameters @@ -353,8 +353,8 @@ def turn_animation_into_updater(animation: Animation, cycle: bool = False) -> Mo Returns ------- :class:`Mobject` - The Mobject being modified by the original `animation` which - was converted into an updater for this Mobject. + The Mobject being modified by the original ``animation`` which was + converted into an updater for this Mobject. Examples -------- @@ -397,7 +397,7 @@ def update(m: Mobject, dt: float): def cycle_animation(animation: Animation) -> Mobject: - """Same as `turn_animation_into_updater`, but with `cycle=True`. + """Same as :meth:`turn_animation_into_updater`, but with ``cycle=True``. Parameters ---------- @@ -408,7 +408,7 @@ def cycle_animation(animation: Animation) -> Mobject: Returns ------- :class:`Mobject` - The Mobject being modified by the original `animation` which + The Mobject being modified by the original ``animation`` which was converted into an updater for this Mobject. """ return turn_animation_into_updater(animation, cycle=True) From 40c63a3083c8a124c00daa9d85f7e1e6eb53ccf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 10:13:56 -0300 Subject: [PATCH 03/10] mobjects -> Mobjects --- manim/animation/updaters/mobject_update_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index 2023ca08aa..ed58075278 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -1,4 +1,4 @@ -"""Utility functions for continuous animation of mobjects.""" +"""Utility functions for continuous animation of Mobjects.""" from __future__ import annotations From 201f8570b2bc52a7917ed513d459820935bb3743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 10:31:58 -0300 Subject: [PATCH 04/10] Update f_always docstring and typings --- manim/animation/updaters/mobject_update_utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index ed58075278..1b9af9fd7a 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -126,20 +126,24 @@ def construct(self): def f_always( method: Callable[[MobjectT], None], - *arg_generators: Callable[[Any], Any], + *arg_generators: Callable[[], Any], **kwargs: Any, ) -> MobjectT: r"""More functional version of :meth:`always`, where instead of taking in ``args``, it takes in functions which output the relevant arguments. + Calling ``f_always(mob.method, generate_arg)`` is equivalent to calling + ``mob.add_updater(lambda mob: mob.method(generate_arg()))``. + Parameters ---------- method A Mobject method to call on each frame. arg_generators Functions which, when called, return positional arguments to be passed - to ``method``. + to ``method``. These functions should have no parameters, or at least + no parameters without default values. kwargs Keyword arguments to be passed to ``method``. From ddc7e2861ec3139faf5a203c65da249e5c5646db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 10:33:19 -0300 Subject: [PATCH 05/10] Update f_always docstring again --- manim/animation/updaters/mobject_update_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index 1b9af9fd7a..7d92258e5d 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -133,8 +133,8 @@ def f_always( of taking in ``args``, it takes in functions which output the relevant arguments. - Calling ``f_always(mob.method, generate_arg)`` is equivalent to calling - ``mob.add_updater(lambda mob: mob.method(generate_arg()))``. + Calling ``f_always(mob.method, get_arg_1, get_arg_2)`` is equivalent to calling + ``mob.add_updater(lambda mob: mob.method(get_arg_1(), get_arg_2()))``. Parameters ---------- From 3091753ac4756bca0fdc663b603f9c64bd59e4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 10:59:48 -0300 Subject: [PATCH 06/10] Add example to cycle_animation --- manim/animation/updaters/mobject_update_utils.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index 7d92258e5d..ee2c5c61d9 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -414,5 +414,20 @@ def cycle_animation(animation: Animation) -> Mobject: :class:`Mobject` The Mobject being modified by the original ``animation`` which was converted into an updater for this Mobject. + + Examples + + .. manim:: IndicateForeverScene + + class IndicateForeverScene(Scene): + def construct(self): + circle = Circle() + self.add(circle) + cycle_animation(Indicate(circle)) + + text = Text("This circle is Indicated forever!").shift(2.5*UP) + + self.play(Write(text)) + self.wait(3) """ return turn_animation_into_updater(animation, cycle=True) From cda4bfdfaafb8b1792a14ec6e027cfdbe02538c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Thu, 24 Oct 2024 11:05:05 -0300 Subject: [PATCH 07/10] Added underline under Examples --- manim/animation/updaters/mobject_update_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index ee2c5c61d9..e87db6b3de 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -416,6 +416,7 @@ def cycle_animation(animation: Animation) -> Mobject: was converted into an updater for this Mobject. Examples + -------- .. manim:: IndicateForeverScene From bbe7f8a6626cbcc384644c981ed7fa55a770fbe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Fri, 25 Oct 2024 18:19:20 -0300 Subject: [PATCH 08/10] Added MobjectMethod Protocol --- .../updaters/mobject_update_utils.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index e87db6b3de..18affb0b65 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -25,14 +25,22 @@ from manim.utils.space_ops import normalize if TYPE_CHECKING: - from typing_extensions import Any, TypeVar + from typing_extensions import Any, ParamSpec, Protocol, TypeVar from manim.animation.animation import Animation MobjectT = TypeVar("MobjectT", bound=Mobject) + MethodArgs = ParamSpec("MethodParams") + class MobjectMethod(Protocol[MobjectT, MethodArgs]): + __self__: MobjectT -def assert_is_mobject_method(method: Callable[[MobjectT], None]) -> None: + def __call__( + self, mobject: MobjectT, *args: MethodArgs.args, **kwargs: MethodArgs.kwargs + ) -> Any: ... + + +def assert_is_mobject_method(method: MobjectMethod[MobjectT, MethodArgs]) -> None: """Verify that the given ``method`` is actually a method and belongs to a :class:`Mobject` or an :class:`OpenGLMobject`. @@ -52,7 +60,11 @@ def assert_is_mobject_method(method: Callable[[MobjectT], None]) -> None: assert isinstance(mobject, (Mobject, OpenGLMobject)) -def always(method: Callable[[MobjectT], None], *args: Any, **kwargs) -> MobjectT: +def always( + method: MobjectMethod[MobjectT, MethodArgs], + *args: MethodArgs.args, + **kwargs: MethodArgs.kwargs, +) -> MobjectT: r"""Given the ``method`` of an existing :class:`Mobject`, apply an updater to this Mobject which modifies it on every frame by repeatedly calling the method. Additional arguments, both positional (``args``) and keyword arguments @@ -125,7 +137,7 @@ def construct(self): def f_always( - method: Callable[[MobjectT], None], + method: MobjectMethod[MobjectT, Any], *arg_generators: Callable[[], Any], **kwargs: Any, ) -> MobjectT: From b2e0493d4bfbab0fb02a8d15e286ac6ddfcc75b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Manr=C3=ADquez?= Date: Fri, 25 Oct 2024 18:23:00 -0300 Subject: [PATCH 09/10] MethodParams -> MethodArgs --- manim/animation/updaters/mobject_update_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index 18affb0b65..811f6538d8 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -30,7 +30,7 @@ from manim.animation.animation import Animation MobjectT = TypeVar("MobjectT", bound=Mobject) - MethodArgs = ParamSpec("MethodParams") + MethodArgs = ParamSpec("MethodArgs") class MobjectMethod(Protocol[MobjectT, MethodArgs]): __self__: MobjectT From eae65a66bcde0b811dab7cd58c9cb6fa6756631a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 23:30:01 +0000 Subject: [PATCH 10/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/animation/updaters/mobject_update_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manim/animation/updaters/mobject_update_utils.py b/manim/animation/updaters/mobject_update_utils.py index ce864cf65a..2fe29c0b55 100644 --- a/manim/animation/updaters/mobject_update_utils.py +++ b/manim/animation/updaters/mobject_update_utils.py @@ -349,7 +349,7 @@ def construct(self): """ mobject.add_updater(lambda m, dt: m.rotate(dt * rate, **kwargs)) return mobject - + def turn_animation_into_updater( animation: Animation, cycle: bool = False, delay: float = 0