From 187de0163ff143bb1570776ef8fb6626061c281a Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 14 Dec 2022 10:58:35 -0800 Subject: [PATCH] Kill config in creation.py --- manimlib/animation/creation.py | 200 +++++++++++++++++++-------------- 1 file changed, 118 insertions(+), 82 deletions(-) diff --git a/manimlib/animation/creation.py b/manimlib/animation/creation.py index 86c5ca05..901f4267 100644 --- a/manimlib/animation/creation.py +++ b/manimlib/animation/creation.py @@ -5,11 +5,10 @@ from abc import ABC, abstractmethod import numpy as np from manimlib.animation.animation import Animation +from manimlib.constants import WHITE from manimlib.mobject.svg.string_mobject import StringMobject -from manimlib.mobject.types.vectorized_mobject import VGroup from manimlib.mobject.types.vectorized_mobject import VMobject from manimlib.utils.bezier import integer_interpolate -from manimlib.utils.config_ops import digest_config from manimlib.utils.rate_functions import linear from manimlib.utils.rate_functions import double_smooth from manimlib.utils.rate_functions import smooth @@ -18,15 +17,17 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: from manimlib.mobject.mobject import Mobject + from manimlib.scene.scene import Scene + from manimlib.constants import ManimColor class ShowPartial(Animation, ABC): """ Abstract class for ShowCreation and ShowPassingFlash """ - CONFIG = { - "should_match_start": False, - } + def __init__(self, mobject: Mobject, should_match_start: bool = False, **kwargs): + self.should_match_start = should_match_start + super().__init__(mobject, **kwargs) def begin(self) -> None: super().begin() @@ -53,39 +54,56 @@ class ShowPartial(Animation, ABC): class ShowCreation(ShowPartial): - CONFIG = { - "lag_ratio": 1, - } + def __init__(self, mobject: Mobject, lag_ratio: float = 1.0, **kwargs): + super().__init__(mobject, lag_ratio=lag_ratio, **kwargs) def get_bounds(self, alpha: float) -> tuple[float, float]: return (0, alpha) class Uncreate(ShowCreation): - CONFIG = { - "rate_func": lambda t: smooth(1 - t), - "remover": True, - "should_match_start": True, - } + def __init__( + self, + mobject: Mobject, + rate_func: Callable[[float], float] = lambda t: smooth(1 - t), + remover: bool = True, + should_match_start: bool = True, + **kwargs, + ): + super().__init__( + mobject, + rate_func=rate_func, + remover=remover, + should_match_start=should_match_start, + **kwargs, + ) class DrawBorderThenFill(Animation): - CONFIG = { - "run_time": 2, - "rate_func": double_smooth, - "stroke_width": 2, - "stroke_color": None, - "draw_border_animation_config": {}, - "fill_animation_config": {}, - } - - def __init__(self, vmobject: VMobject, **kwargs): + def __init__( + self, + vmobject: VMobject, + run_time: float = 2.0, + rate_func: Callable[[float], float] = double_smooth, + stroke_width: float = 2.0, + stroke_color: ManimColor = None, + draw_border_animation_config: dict = {}, + fill_animation_config: dict = {}, + **kwargs + ): assert(isinstance(vmobject, VMobject)) - self.sm_to_index = dict([ - (hash(sm), 0) - for sm in vmobject.get_family() - ]) - super().__init__(vmobject, **kwargs) + self.sm_to_index = {hash(sm): 0 for sm in vmobject.get_family()} + self.stroke_width = stroke_width + self.stroke_color = stroke_color + self.draw_border_animation_config = draw_border_animation_config + self.fill_animation_config = fill_animation_config + super().__init__( + vmobject, + run_time=run_time, + rate_func=rate_func, + **kwargs + ) + self.mobject = vmobject def begin(self) -> None: # Trigger triangulation calculation @@ -104,21 +122,14 @@ class DrawBorderThenFill(Animation): def get_outline(self) -> VMobject: outline = self.mobject.copy() outline.set_fill(opacity=0) - for sm in outline.get_family(): + for sm in outline.family_members_with_points(): sm.set_stroke( - color=self.get_stroke_color(sm), - width=float(self.stroke_width) + color=self.stroke_color or sm.get_stroke_color(), + width=self.stroke_width, ) return outline - def get_stroke_color(self, vmobject: VMobject) -> str: - if self.stroke_color: - return self.stroke_color - elif vmobject.get_stroke_width() > 0: - return vmobject.get_stroke_color() - return vmobject.get_color() - - def get_all_mobjects(self) -> list[VMobject]: + def get_all_mobjects(self) -> list[Mobject]: return [*super().get_all_mobjects(), self.outline] def interpolate_submobject( @@ -146,39 +157,51 @@ class DrawBorderThenFill(Animation): class Write(DrawBorderThenFill): - CONFIG = { - # To be figured out in - # set_default_config_from_lengths - "run_time": None, - "lag_ratio": None, - "rate_func": linear, - } + def __init__( + self, + vmobject: VMobject, + run_time: float = -1, # If negative, this will be reassigned + lag_ratio: float = -1, # If negative, this will be reassigned + rate_func: Callable[[float], float] = linear, + stroke_color: ManimColor = WHITE, + **kwargs + ): + family_size = len(vmobject.family_members_with_points()) + super().__init__( + vmobject, + run_time=self.compute_run_time(family_size, run_time), + lag_ratio=self.compute_lag_ratio(family_size, lag_ratio), + rate_func=rate_func, + stroke_color=stroke_color, + **kwargs + ) - def __init__(self, vmobject: VMobject, **kwargs): - digest_config(self, kwargs) - self.set_default_config_from_length(vmobject) - super().__init__(vmobject, **kwargs) + def compute_run_time(self, family_size: int, run_time: float): + if run_time < 0: + return 1 if family_size < 15 else 2 + return run_time - def set_default_config_from_length(self, vmobject: VMobject) -> None: - length = len(vmobject.family_members_with_points()) - if self.run_time is None: - if length < 15: - self.run_time = 1 - else: - self.run_time = 2 - if self.lag_ratio is None: - self.lag_ratio = min(4.0 / (length + 1.0), 0.2) + def compute_lag_ratio(self, family_size: int, lag_ratio: float): + if lag_ratio < 0: + return min(4.0 / (family_size + 1.0), 0.2) + return lag_ratio class ShowIncreasingSubsets(Animation): - CONFIG = { - "suspend_mobject_updating": False, - "int_func": np.round, - } - - def __init__(self, group: Mobject, **kwargs): + def __init__( + self, + group: Mobject, + int_func: Callable[[float], float] = np.round, + suspend_mobject_updating: bool = False, + **kwargs + ): self.all_submobs = list(group.submobjects) - super().__init__(group, **kwargs) + self.int_func = int_func + super().__init__( + group, + suspend_mobject_updating=suspend_mobject_updating, + **kwargs + ) def interpolate_mobject(self, alpha: float) -> None: n_submobs = len(self.all_submobs) @@ -190,9 +213,13 @@ class ShowIncreasingSubsets(Animation): class ShowSubmobjectsOneByOne(ShowIncreasingSubsets): - CONFIG = { - "int_func": np.ceil, - } + def __init__( + self, + group: Mobject, + int_func: Callable[[float], float] = np.ceil, + **kwargs + ): + super().__init__(group, int_func=int_func, **kwargs) def update_submobject_list(self, index: int) -> None: # N = len(self.all_submobs) @@ -203,18 +230,27 @@ class ShowSubmobjectsOneByOne(ShowIncreasingSubsets): class AddTextWordByWord(ShowIncreasingSubsets): - CONFIG = { - # If given a value for run_time, it will - # override the time_per_word - "run_time": None, - "time_per_word": 0.2, - "rate_func": linear, - } - - def __init__(self, string_mobject, **kwargs): + def __init__( + self, + string_mobject: StringMobject, + time_per_word: float = 0.2, + run_time: float = -1.0, # If negative, it will be recomputed with time_per_word + rate_func: Callable[[float], float] = linear, + **kwargs + ): assert isinstance(string_mobject, StringMobject) grouped_mobject = string_mobject.build_groups() - digest_config(self, kwargs) - if self.run_time is None: - self.run_time = self.time_per_word * len(grouped_mobject) - super().__init__(grouped_mobject, **kwargs) + if run_time < 0: + run_time = time_per_word * len(grouped_mobject) + super().__init__( + grouped_mobject, + run_time=run_time, + rate_func=rate_func, + **kwargs + ) + self.string_mobject = string_mobject + + def clean_up_from_scene(self, scene: Scene) -> None: + scene.remove(self.mobject) + if not self.is_remover(): + scene.add(self.string_mobject)