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

Code before:


DEFAULT_LAGGED_START_LAG_RATIO: float = 0.05


class AnimationGroup(Animation):
    def __init__(
        self,
        *animations: Animation,
        group: typing.Union[Group, "VGroup"] = None,
        run_time: float = None,
        rate_func: typing.Callable[[float], float] = linear,
        lag_ratio: float = 0,
        **kwargs
    ) -> None:
        self.animations = [prepare_animation(anim) for anim in animations]
        self.group = group
        self.animations_with_mobjects = []
        for anim in animations:
            if isinstance(anim.mobject, Mobject):
                self.animations_with_mobjects.append(anim)
        if self.group is None:
            self.group = Group(
                *remove_list_redundancies(
                    [anim.mobject for anim in self.animations_with_mobjects]
                )
            )
        super().__init__(self.group, rate_func=rate_func, lag_ratio=lag_ratio, **kwargs)
        self.run_time = run_time
        self.init_run_time()

    def get_all_mobjects(self) -> Group:
        return self.group

    def get_run_time(self) -> float:
        if super().get_run_time() is None:
            self.init_run_time()
        return super().get_run_time()

    def begin(self) -> None:
        for anim in self.animations:
            anim.begin()

    def finish(self) -> None:
        for anim in self.animations:
            anim.finish()

    def clean_up_from_scene(self, scene: Scene) -> None:
        for anim in self.animations:
            anim.clean_up_from_scene(scene)


Review comment (suggestion):
Would prefer to not keep an extra list of animations with `self.animations_with_mobjects` and would also prefer checking if `anim.mobject` is `None` instead because `Animation` errors if the mobject is not `None` or an instance of `Mobject`, and checking against `None` requires less overhead.
```suggestion
                *remove_list_redundancies(
                    [anim.mobject for anim in self.animations if anim.mobject is not None]
                )
```

Perhaps an extra method/property/attribute could be added to `Animation` like `is_dummy` that could be checked instead of doing this here.

Code after:


DEFAULT_LAGGED_START_LAG_RATIO: float = 0.05


class AnimationGroup(Animation):
    def __init__(
        self,
        *animations: Animation,
        group: typing.Union[Group, "VGroup"] = None,
        run_time: float = None,
        rate_func: typing.Callable[[float], float] = linear,
        lag_ratio: float = 0,
        **kwargs
    ) -> None:
        self.animations = [prepare_animation(anim) for anim in animations]
        self.group = group
        if self.group is None:
            self.group = Group(
                *remove_list_redundancies(
                    [anim.mobject for anim in self.animations if not anim.is_dummy()]
                )
            )
        super().__init__(self.group, rate_func=rate_func, lag_ratio=lag_ratio, **kwargs)
        self.run_time = run_time
        self.init_run_time()

    def get_all_mobjects(self) -> Group:
        return self.group

    def get_run_time(self) -> float:
        if super().get_run_time() is None:
            self.init_run_time()
        return super().get_run_time()

    def begin(self) -> None:
        for anim in self.animations:
            anim.begin()

    def finish(self) -> None:
        for anim in self.animations:
            anim.finish()

    def clean_up_from_scene(self, scene: Scene) -> None:
        for anim in self.animations:
            anim.clean_up_from_scene(scene)

    def update_mobjects(self, dt: float) -> None:
        for anim in self.animations:
            anim.update_mobjects(dt)