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

Code before:
)

if TYPE_CHECKING:
    from manim.scene.scene import Scene

from .. import logger
from ..mobject import mobject, opengl_mobject
from ..mobject.mobject import Mobject
from ..mobject.opengl_mobject import OpenGLMobject
from ..utils.rate_functions import smooth

DEFAULT_ANIMATION_RUN_TIME: float = 1.0
DEFAULT_ANIMATION_LAG_RATIO: float = 0.0


class Animation:
    def __new__(
        cls,
        mobject: Optional[Mobject] = None,
        *args,
        use_default: bool = False,
        **kwargs,
    ):
        overrides = Mobject.animation_overrides
        if not use_default and cls in overrides and type(mobject) in overrides[cls]:
            func = overrides[cls][type(mobject)]
            anim = func(mobject, *args, **kwargs)
            return anim
        return super().__new__(cls)

    def __init__(
        self,
        mobject: Optional[Mobject],
        # If lag_ratio is 0, the animation is applied to all submobjects
        # at the same time
        # If 1, it is applied to each successively.
        # If 0 < lag_ratio < 1, its applied to each
        # with lagged start times
        lag_ratio: float = DEFAULT_ANIMATION_LAG_RATIO,
        run_time: float = DEFAULT_ANIMATION_RUN_TIME,
        rate_func: Callable[[float], float] = smooth,
        name: str = None,
        remover: bool = False,  # remove a mobject from the screen?
        suspend_mobject_updating: bool = True,
        **kwargs,
    ) -> None:
        self._typecheck_input(mobject)
        self.run_time: float = run_time
        self.rate_func: Callable[[float], float] = rate_func
        self.name: Optional[str] = name
        self.remover: bool = remover

Review comment (suggestion):
I'd prefer this logic to be under `Mobject`, something like
```py
class Mobject:
    @classmethod
    def animation_override_for(cls, animation_class):
        if no_override_for_anim:
            return None

        return func_for_override
```
Just so the overriding logic is less spread out over multiple files and such.

I think I'd also like the overrides to be stored under the class they're for, rather than all of them under `Mobject`. So it'd be like `cls.animation_overrides[animation_class]` instead of `Mobject.animation_overrides[animation_class][cls]`

Code after:
from ..utils.rate_functions import smooth

DEFAULT_ANIMATION_RUN_TIME: float = 1.0
DEFAULT_ANIMATION_LAG_RATIO: float = 0.0


class Animation:
    def __new__(
        cls,
        mobject: Optional[Mobject] = None,
        *args,
        use_override: bool = True,
        **kwargs,
    ):
        if isinstance(mobject, Mobject) and use_override:
            func = mobject.animation_override_for(cls)
            if func is not None:
                anim = func(mobject, *args, **kwargs)
                logger.debug(
                    (
                        f"The {cls.__name__} animation has been is overridden for "
                        f"{type(mobject).__name__} mobjects. use_override = False can "
                        f" be used as keyword argument to prevent animation overriding."
                    )
                )
                return anim
        return super().__new__(cls)

    def __init__(
        self,
        mobject: Optional[Mobject],
        # If lag_ratio is 0, the animation is applied to all submobjects
        # at the same time
        # If 1, it is applied to each successively.
        # If 0 < lag_ratio < 1, its applied to each
        # with lagged start times
        lag_ratio: float = DEFAULT_ANIMATION_LAG_RATIO,
        run_time: float = DEFAULT_ANIMATION_RUN_TIME,
        rate_func: Callable[[float], float] = smooth,
        name: str = None,
        remover: bool = False,  # remove a mobject from the screen?
        suspend_mobject_updating: bool = True,
        **kwargs,
    ) -> None:
        self._typecheck_input(mobject)
        self.run_time: float = run_time
        self.rate_func: Callable[[float], float] = rate_func
        self.name: Optional[str] = name
        self.remover: bool = remover
        self.suspend_mobject_updating: bool = suspend_mobject_updating
        self.lag_ratio: float = lag_ratio