from manimlib.animation.animation import Animation 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 class ShowPartial(Animation): """ Abstract class for ShowCreation and ShowPassingFlash """ def interpolate_submobject(self, submob, start_submob, alpha): submob.pointwise_become_partial( start_submob, *self.get_bounds(alpha) ) def get_bounds(self, alpha): raise Exception("Not Implemented") class ShowCreation(ShowPartial): CONFIG = { "lag_ratio": 1, } def get_bounds(self, alpha): return (0, alpha) class Uncreate(ShowCreation): CONFIG = { "rate_func": lambda t: smooth(1 - t), "remover": True } 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, **kwargs): self.check_validity_of_input(vmobject) Animation.__init__(self, vmobject, **kwargs) def check_validity_of_input(self, vmobject): if not isinstance(vmobject, VMobject): raise Exception( "DrawBorderThenFill only works for VMobjects" ) def begin(self): self.outline = self.get_outline() super().begin() def get_outline(self): outline = self.mobject.copy() outline.set_fill(opacity=0) outline.set_stroke( color=self.get_stroke_color(outline), width=self.stroke_width ) return outline def get_stroke_color(self, vmobject): 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): return [*super().get_all_mobjects(), self.outline] def interpolate_submobject(self, submob, start, outline, alpha): index, subalpha = integer_interpolate(0, 2, alpha) if index == 0: submob.pointwise_become_partial( outline, 0, subalpha ) submob.match_style(outline) else: submob.interpolate(outline, start, subalpha) 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, mobject, **kwargs): digest_config(self, kwargs) self.set_default_config_from_length(mobject) DrawBorderThenFill.__init__(self, mobject, **kwargs) def set_default_config_from_length(self, mobject): length = len(mobject.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, 0.2) class ShowIncreasingSubsets(Animation): def __init__(self, group, **kwargs): self.all_submobs = list(group.submobjects) Animation.__init__(self, group, **kwargs) def interpolate_mobject(self, alpha): n_submobs = len(self.all_submobs) index = int(alpha * n_submobs) self.mobject.submobjects = self.all_submobs[:index]