Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion manim/animation/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,26 @@ def identity(mob: Mobject) -> Mobject:

arg_creator = identity

def animation_args(value: Any) -> tuple[Any, ...]:
# ``arg_creator`` may return either a tuple of constructor args (e.g.
# ``(m.set_color, YELLOW)``) or a single mobject (the default identity).
# Only tuples are unpacked; mobjects must be passed as a single argument
# so animations like ``Restore(mob)`` are not called as ``Restore(*mob)``.
if isinstance(value, tuple):
return value
return (value,)

args_list = [arg_creator(submob) for submob in mobject]
if not args_list:
raise ValueError(
f"LaggedStartMap cannot build animations from {mobject!r}: "
"it has no submobjects to map over. Pass a VGroup of the "
"targets to animate, or provide a non-empty mobject."
)
anim_kwargs = dict(kwargs)
if "lag_ratio" in anim_kwargs:
anim_kwargs.pop("lag_ratio")
animations = [animation_class(*args, **anim_kwargs) for args in args_list]
animations = [
animation_class(*animation_args(args), **anim_kwargs) for args in args_list
]
super().__init__(*animations, run_time=run_time, lag_ratio=lag_ratio)
19 changes: 19 additions & 0 deletions tests/module/animation/test_composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from manim.animation.composition import AnimationGroup, LaggedStartMap, Succession
from manim.animation.creation import Create, Write
from manim.animation.fading import FadeIn, FadeOut
from manim.animation.transform import Restore
from manim.constants import DOWN, UP
from manim.mobject.geometry.arc import Circle
from manim.mobject.geometry.line import Line
Expand Down Expand Up @@ -191,6 +192,24 @@ def finish(self):
assert circ_animation.finished


def test_laggedstartmap_restore_builds_subanimations():
mobject = VGroup(Square(), Square().shift(UP))
for submob in mobject:
submob.save_state()
submob.scale(0)
animation = LaggedStartMap(Restore, mobject, lag_ratio=0.1, run_time=1)
assert len(animation.animations) == len(mobject)
assert all(
isinstance(subanimation, Restore) for subanimation in animation.animations
)


def test_laggedstartmap_empty_mobject_raises():
mobject = VGroup()
with pytest.raises(ValueError, match="no submobjects"):
LaggedStartMap(Restore, mobject)


def test_laggedstartmap_only_passes_kwargs_to_subanimations():
mobject = VGroup(Square(), Circle())
animation = LaggedStartMap(
Expand Down
Loading