From 7dcf5eff8eaa46c71f2d7fbabf73f3b5011ea195 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Wed, 14 Dec 2022 14:40:05 -0800 Subject: [PATCH] Kill CONFIG in indication.py --- manimlib/animation/indication.py | 319 ++++++++++++++++--------------- 1 file changed, 169 insertions(+), 150 deletions(-) diff --git a/manimlib/animation/indication.py b/manimlib/animation/indication.py index d42723a7..304097a0 100644 --- a/manimlib/animation/indication.py +++ b/manimlib/animation/indication.py @@ -1,6 +1,7 @@ from __future__ import annotations import math +from os import remove import numpy as np from manimlib.animation.animation import Animation @@ -15,6 +16,7 @@ from manimlib.animation.transform import Transform from manimlib.constants import FRAME_X_RADIUS, FRAME_Y_RADIUS from manimlib.constants import ORIGIN, RIGHT, UP from manimlib.constants import SMALL_BUFF +from manimlib.constants import DEGREES from manimlib.constants import TAU from manimlib.constants import GREY, YELLOW from manimlib.mobject.geometry import Circle @@ -34,30 +36,32 @@ from manimlib.utils.rate_functions import wiggle from typing import TYPE_CHECKING if TYPE_CHECKING: + from typing import Callable from manimlib.constants import ManimColor from manimlib.mobject.mobject import Mobject class FocusOn(Transform): - CONFIG = { - "opacity": 0.2, - "color": GREY, - "run_time": 2, - "remover": True, - } - - def __init__(self, focus_point: np.ndarray, **kwargs): + def __init__( + self, + focus_point: np.ndarray | Mobject, + opacity: float = 0.2, + color: ManimColor = GREY, + run_time: float = 2, + remover: bool = True, + **kwargs + ): self.focus_point = focus_point + self.opacity = opacity + self.color = color # Initialize with blank mobject, while create_target # and create_starting_mobject handle the meat - super().__init__(VMobject(), **kwargs) + super().__init__(VMobject(), run_time=run_time, remover=remover, **kwargs) def create_target(self) -> Dot: little_dot = Dot(radius=0) little_dot.set_fill(self.color, opacity=self.opacity) - little_dot.add_updater( - lambda d: d.move_to(self.focus_point) - ) + little_dot.add_updater(lambda d: d.move_to(self.focus_point)) return little_dot def create_starting_mobject(self) -> Dot: @@ -70,11 +74,17 @@ class FocusOn(Transform): class Indicate(Transform): - CONFIG = { - "rate_func": there_and_back, - "scale_factor": 1.2, - "color": YELLOW, - } + def __init__( + self, + mobject: Mobject, + scale_factor: float = 1.2, + color: ManimColor = YELLOW, + rate_func: Callable[[float], float] = there_and_back, + **kwargs + ): + self.scale_factor = scale_factor + self.color = color + super().__init__(mobject, rate_func=rate_func, **kwargs) def create_target(self) -> Mobject: target = self.mobject.copy() @@ -84,28 +94,30 @@ class Indicate(Transform): class Flash(AnimationGroup): - CONFIG = { - "line_length": 0.2, - "num_lines": 12, - "flash_radius": 0.3, - "line_stroke_width": 3, - "run_time": 1, - } - def __init__( self, - point: np.ndarray, + point: np.ndarray | Mobject, color: ManimColor = YELLOW, + line_length: float = 0.2, + num_lines: int = 12, + flash_radius: float = 0.3, + line_stroke_width: float = 3.0, + run_time: float = 1.0, **kwargs ): self.point = point self.color = color - digest_config(self, kwargs) + self.line_length = line_length + self.num_lines = num_lines + self.flash_radius = flash_radius + self.line_stroke_width = line_stroke_width + self.lines = self.create_lines() animations = self.create_line_anims() super().__init__( *animations, group=self.lines, + run_time=run_time, **kwargs, ) @@ -130,35 +142,43 @@ class Flash(AnimationGroup): ] -class CircleIndicate(Indicate): - CONFIG = { - "rate_func": there_and_back, - "remover": True, - "circle_config": { - "color": YELLOW, - }, - } - - def __init__(self, mobject: Mobject, **kwargs): - digest_config(self, kwargs) - circle = self.get_circle(mobject) - super().__init__(circle, **kwargs) - - def get_circle(self, mobject: Mobject) -> Circle: - circle = Circle(**self.circle_config) - circle.add_updater(lambda c: c.surround(mobject)) - return circle - - def interpolate_mobject(self, alpha: float) -> None: - super().interpolate_mobject(alpha) - self.mobject.set_stroke(opacity=alpha) +class CircleIndicate(Transform): + def __init__( + self, + mobject: Mobject, + scale_factor: float = 1.2, + rate_func: Callable[[float], float] = there_and_back, + stroke_color: ManimColor = YELLOW, + stroke_width: float = 3.0, + remover: bool = True, + **kwargs + ): + circle = Circle(stroke_color=stroke_color, stroke_width=stroke_width) + circle.surround(mobject) + pre_circle = circle.copy().set_stroke(width=0) + pre_circle.scale(1 / scale_factor) + super().__init__( + pre_circle, circle, + rate_func=rate_func, + remover=remover, + **kwargs + ) class ShowPassingFlash(ShowPartial): - CONFIG = { - "time_width": 0.1, - "remover": True, - } + def __init__( + self, + mobject: Mobject, + time_width: float = 0.1, + remover: bool = True, + **kwargs + ): + self.time_width = time_width + super().__init__( + mobject, + remover=remover, + **kwargs + ) def get_bounds(self, alpha: float) -> tuple[float, float]: tw = self.time_width @@ -175,11 +195,17 @@ class ShowPassingFlash(ShowPartial): class VShowPassingFlash(Animation): - CONFIG = { - "time_width": 0.3, - "taper_width": 0.02, - "remover": True, - } + def __init__( + self, + vmobject: VMobject, + time_width: float = 0.3, + taper_width: float = 0.02, + remover: bool = True, + **kwargs + ): + self.time_width = time_width + self.taper_width = taper_width + super().__init__(vmobject, remover=remover, **kwargs) def begin(self) -> None: self.mobject.align_stroke_width_data_to_points() @@ -235,112 +261,94 @@ class VShowPassingFlash(Animation): class FlashAround(VShowPassingFlash): - CONFIG = { - "stroke_width": 4.0, - "color": YELLOW, - "buff": SMALL_BUFF, - "time_width": 1.0, - "n_inserted_curves": 20, - } - - def __init__(self, mobject: Mobject, **kwargs): - digest_config(self, kwargs) - path = self.get_path(mobject) + def __init__( + self, + mobject: Mobject, + time_width: float = 1.0, + stroke_width: float = 4.0, + color: ManimColor = YELLOW, + buff: float = SMALL_BUFF, + n_inserted_curves: int = 20, + **kwargs + ): + path = self.get_path(mobject, buff) if mobject.is_fixed_in_frame: path.fix_in_frame() - path.insert_n_curves(self.n_inserted_curves) + path.insert_n_curves(n_inserted_curves) path.set_points(path.get_points_without_null_curves()) - path.set_stroke(self.color, self.stroke_width) - super().__init__(path, **kwargs) + path.set_stroke(color, stroke_width) + super().__init__(path, time_width=time_width, **kwargs) - def get_path(self, mobject: Mobject) -> SurroundingRectangle: - return SurroundingRectangle(mobject, buff=self.buff) + def get_path(self, mobject: Mobject, buff: float) -> SurroundingRectangle: + return SurroundingRectangle(mobject, buff=buff) class FlashUnder(FlashAround): - def get_path(self, mobject: Mobject) -> Underline: - return Underline(mobject, buff=self.buff) + def get_path(self, mobject: Mobject, buff: float) -> Underline: + return Underline(mobject, buff=buff) class ShowCreationThenDestruction(ShowPassingFlash): - CONFIG = { - "time_width": 2.0, - "run_time": 1, - } + def __init__(self, vmobject: VMobject, time_width: float = 2.0, **kwargs): + super().__init__(vmobject, time_width=time_width, **kwargs) class ShowCreationThenFadeOut(Succession): - CONFIG = { - "remover": True, - } - - def __init__(self, mobject: Mobject, **kwargs): + def __init__(self, mobject: Mobject, remover: bool = True, **kwargs): super().__init__( ShowCreation(mobject), FadeOut(mobject), + remover=remover, **kwargs ) class AnimationOnSurroundingRectangle(AnimationGroup): - CONFIG = { - "surrounding_rectangle_config": {}, - # Function which takes in a rectangle, and spits - # out some animation. Could be some animation class, - # could be something more - "rect_animation": Animation - } + RectAnimationType: type = Animation - def __init__(self, mobject: Mobject, **kwargs): - digest_config(self, kwargs) - if "surrounding_rectangle_config" in kwargs: - kwargs.pop("surrounding_rectangle_config") - self.mobject_to_surround = mobject - - rect = self.get_rect() + def __init__( + self, + mobject: Mobject, + stroke_width: float = 2.0, + stroke_color: ManimColor = YELLOW, + buff: float = SMALL_BUFF, + **kwargs + ): + rect = SurroundingRectangle( + mobject, + stroke_width=stroke_width, + stroke_color=stroke_color, + buff=buff, + ) rect.add_updater(lambda r: r.move_to(mobject)) - - super().__init__( - self.rect_animation(rect, **kwargs), - ) - - def get_rect(self) -> SurroundingRectangle: - return SurroundingRectangle( - self.mobject_to_surround, - **self.surrounding_rectangle_config - ) + super().__init__(self.RectAnimationType(rect, **kwargs)) class ShowPassingFlashAround(AnimationOnSurroundingRectangle): - CONFIG = { - "rect_animation": ShowPassingFlash - } + RectAnimationType = ShowPassingFlash class ShowCreationThenDestructionAround(AnimationOnSurroundingRectangle): - CONFIG = { - "rect_animation": ShowCreationThenDestruction - } + RectAnimationType = ShowCreationThenDestruction class ShowCreationThenFadeAround(AnimationOnSurroundingRectangle): - CONFIG = { - "rect_animation": ShowCreationThenFadeOut - } + RectAnimationType = ShowCreationThenFadeOut class ApplyWave(Homotopy): - CONFIG = { - "direction": UP, - "amplitude": 0.2, - "run_time": 1, - } + def __init__( + self, + mobject: Mobject, + direction: np.ndarray = UP, + amplitude: float = 0.2, + run_time: float = 1.0, + **kwargs + ): - def __init__(self, mobject: Mobject, **kwargs): - digest_config(self, kwargs, locals()) left_x = mobject.get_left()[0] right_x = mobject.get_right()[0] - vect = self.amplitude * self.direction + vect = amplitude * direction def homotopy(x, y, z, t): alpha = (x - left_x) / (right_x - left_x) @@ -352,22 +360,29 @@ class ApplyWave(Homotopy): class WiggleOutThenIn(Animation): - CONFIG = { - "scale_value": 1.1, - "rotation_angle": 0.01 * TAU, - "n_wiggles": 6, - "run_time": 2, - "scale_about_point": None, - "rotate_about_point": None, - } + def __init__( + self, + mobject: Mobject, + scale_value: float = 1.1, + rotation_angle: float = 0.01 * TAU, + n_wiggles: int = 6, + scale_about_point: np.ndarray | None = None, + rotate_about_point: np.ndarray | None = None, + run_time: float = 2, + **kwargs + ): + self.scale_value = scale_value + self.rotation_angle = rotation_angle + self.n_wiggles = n_wiggles + self.scale_about_point = scale_about_point + self.rotate_about_point = rotate_about_point + super().__init__(mobject, run_time=run_time, **kwargs) def get_scale_about_point(self) -> np.ndarray: - if self.scale_about_point is None: - return self.mobject.get_center() + return self.scale_about_point or self.mobject.get_center() def get_rotate_about_point(self) -> np.ndarray: - if self.rotate_about_point is None: - return self.mobject.get_center() + return self.rotate_about_point or self.mobject.get_center() def interpolate_submobject( self, @@ -387,28 +402,32 @@ class WiggleOutThenIn(Animation): class TurnInsideOut(Transform): - CONFIG = { - "path_arc": TAU / 4, - } + def __init__(self, mobject: Mobject, path_arc: float = 90 * DEGREES, **kwargs): + super().__init__(mobject, path_arc=path_arc, **kwargs) def create_target(self) -> Mobject: - return self.mobject.copy().reverse_points() + result = self.mobject.copy().reverse_points() + if isinstance(result, VMobject): + result.refresh_unit_normal() + result.refresh_triangulation() + return result class FlashyFadeIn(AnimationGroup): - CONFIG = { - "fade_lag": 0, - } - - def __init__(self, vmobject: VMobject, stroke_width: float = 2, **kwargs): - digest_config(self, kwargs) + def __init__(self, + vmobject: VMobject, + stroke_width: float = 2.0, + fade_lag: float = 0.0, + time_width: float = 1.0, + **kwargs + ): outline = vmobject.copy() outline.set_fill(opacity=0) outline.set_stroke(width=stroke_width, opacity=1) rate_func = kwargs.get("rate_func", smooth) super().__init__( - FadeIn(vmobject, rate_func=squish_rate_func(rate_func, self.fade_lag, 1)), - VShowPassingFlash(outline, time_width=1), + FadeIn(vmobject, rate_func=squish_rate_func(rate_func, fade_lag, 1)), + VShowPassingFlash(outline, time_width=time_width), **kwargs )