def show_overall_effect(self, matrix): everything = self.get_mobjects() everything = list_difference_update(everything, matrix.submobject_family()) self.play(*map(FadeOut, everything) + [Animation(matrix)]) new_matrix = matrix.copy() new_matrix.center().to_edge(UP) self.play(Transform(matrix, new_matrix)) self.wait() self.remove(matrix) self.setup() everything = self.get_mobjects() self.play(*map(FadeIn, everything) + [Animation(matrix)]) func = self.get_matrix_transformation([[1, 1], [-1, 0]]) bases = VMobject(self.i_hat, self.j_hat) new_bases = VMobject(*[ Vector(func(v.get_end()), color=v.get_color()) for v in bases.split() ]) self.play(ApplyPointwiseFunction(func, self.plane), Transform(bases, new_bases), Animation(matrix), run_time=3) self.wait()
def draw_lines_through_center(self): point_mobs = self.point_mobs angles = self.get_point_mob_angles() all_arcs = self.all_arcs lines = self.get_center_lines() self.add_foreground_mobjects(self.center_dot) for line in lines: self.play(ShowCreation(line)) self.play(FadeIn(all_arcs), Animation(point_mobs)) self.remove(self.circle) self.dither() self.play( all_arcs.space_out_submobjects, 1.5, Animation(point_mobs), rate_func = there_and_back, run_time = 1.5, ) self.dither() self.change_point_mobs( [0, 0, np.mean(angles[:2])+np.pi-angles[2]] ) self.dither() for x in range(3): self.change_point_mobs([0, 0, np.pi/2]) self.dither()
def update_config(self, **kwargs): Animation.update_config(self, **kwargs) if "path_arc" in kwargs: self.path_func = path_along_arc( kwargs["path_arc"], kwargs.get("path_arc_axis", OUT) )
def __init__(self, mobject, **kwargs): digest_config(self, kwargs) if self.scale_about_point is None: self.scale_about_point = mobject.get_center() if self.rotate_about_point is None: self.rotate_about_point = mobject.get_center() Animation.__init__(self, mobject, **kwargs)
def update_config(self, **kwargs): Animation.update_config(self, **kwargs) # If AnimationGroup is called with any configuration, # it is propagated to the sub_animations for anim in self.sub_anims: anim.update_config(**kwargs)
def update_mobject(self, alpha): Animation.update_mobject(self, alpha) angle_revs = self.rotate_func(alpha) self.mobject.rotate( angle_revs * 2 * np.pi, ) self.mobject.set_color(color_func(angle_revs))
def construct(self): self.add_dots_at_alphas(*np.linspace(0.2, 0.8, 4)) self.highlight_dots_by_pair() rect_alphas = self.get_rect_alphas() self.play(ShowCreation(self.dots)) self.add_connecting_lines() self.play(ShowCreation(self.connecting_lines)) self.let_dots_wonder(2) self.move_dots_to_alphas(rect_alphas) midpoint = Dot( center_of_mass([d.get_center() for d in self.dots]), color = RED ) self.play(ShowCreation(midpoint)) self.dither() angles = [line.get_angle() for line in self.connecting_lines] angle_mean = np.mean(angles) self.play( *[ ApplyMethod(line.rotate_in_place, angle_mean-angle) for line, angle in zip(self.connecting_lines, angles) ] + [Animation(midpoint)], rate_func = there_and_back ) self.add(self.connecting_lines.copy(), midpoint) self.connecting_lines = VGroup() self.dither() self.add_connecting_lines(cyclic = True) self.play( ShowCreation(self.connecting_lines), Animation(self.dots) ) self.dither()
def __init__(self, mobject, **kwargs): digest_config(self, kwargs) mobject.next_to(self.x_start * RIGHT + SPACE_HEIGHT * UP, UP) self.total_vert_shift = \ 2*SPACE_HEIGHT + mobject.get_height() + 2*MED_SMALL_BUFF Animation.__init__(self, mobject, **kwargs)
def construct(self): rect = Rectangle(width=5, height=3) # f = lambda t : 4*np.sin(t*np.pi/2) f = lambda t: 4 * t g = lambda t: 3 * smooth(t) curve = ParametricFunction(lambda t: f(t) * RIGHT + g(t) * DOWN) curve.highlight(YELLOW) curve.center() rect = Rectangle() rect.replace(curve, stretch=True) regions = [] for vect, color in (UP + RIGHT, BLUE), (DOWN + LEFT, GREEN): region = curve.copy() region.add_control_points(3 * [rect.get_corner(vect)]) region.set_stroke(width=0) region.set_fill(color=color, opacity=0.5) regions.append(region) upper_right, lower_left = regions v_lines, h_lines = VGroup(), VGroup() for alpha in np.linspace(0, 1, 30): point = curve.point_from_proportion(alpha) top_point = curve.points[0][1] * UP + point[0] * RIGHT left_point = curve.points[0][0] * RIGHT + point[1] * UP v_lines.add(Line(top_point, point)) h_lines.add(Line(left_point, point)) v_lines.highlight(BLUE_E) h_lines.highlight(GREEN_E) equation = TexMobject("\\int_0^1 g\\,df", "+\\int_0^1 f\\,dg", "= \\big(fg \\big)_0^1") equation.to_edge(UP) equation.highlight_by_tex("\\int_0^1 g\\,df", upper_right.get_color()) equation.highlight_by_tex("+\\int_0^1 f\\,dg", lower_left.get_color()) left_brace = Brace(rect, LEFT) down_brace = Brace(rect, DOWN) g_T = left_brace.get_text("$g(t)\\big|_0^1$") f_T = down_brace.get_text("$f(t)\\big|_0^1$") self.draw_curve(curve) self.play(ShowCreation(rect)) self.play(*map(Write, [down_brace, left_brace, f_T, g_T])) self.dither() self.play(FadeIn(upper_right)) self.play( ShowCreation(v_lines, submobjects="one_at_a_time", run_time=2), Animation(curve), Animation(rect)) self.play(Write(equation[0])) self.dither() self.play(FadeIn(lower_left)) self.play( ShowCreation(h_lines, submobjects="one_at_a_time", run_time=2), Animation(curve), Animation(rect)) self.play(Write(equation[1])) self.dither() self.play(Write(equation[2])) self.dither()
def __init__(self, decimal_number_mobject, number_update_func, **kwargs): digest_config(self, kwargs, locals()) if self.tracked_mobject: dmc = decimal_number_mobject.get_center() tmc = self.tracked_mobject.get_center() self.diff_from_tracked_mobject = dmc - tmc self.diff_from_tracked_mobject = dmc - tmc Animation.__init__(self, decimal_number_mobject, **kwargs)
def introduce_coordinate_plane(self): plane = NumberPlane() x_axis, y_axis = plane.get_axes().copy().split() x_label, y_label = plane.get_axis_labels().split() number_line = NumberLine(tick_frequency = 1) x_tick_marks = number_line.get_tick_marks() y_tick_marks = x_tick_marks.copy().rotate(np.pi/2) tick_marks = VMobject(x_tick_marks, y_tick_marks) tick_marks.highlight(WHITE) plane_lines = filter( lambda m : isinstance(m, Line), plane.submobject_family() ) origin_words = TextMobject("Origin") origin_words.shift(2*UP+2*LEFT) dot = Dot(radius = 0.1).highlight(RED) line = Line(origin_words.get_bottom(), dot.get_corner(UP+LEFT)) unit_brace = Brace(Line(RIGHT, 2*RIGHT)) one = TexMobject("1").next_to(unit_brace, DOWN) self.add(x_axis, x_label) self.wait() self.play(ShowCreation(y_axis)) self.play(Write(y_label, run_time = 1)) self.wait(2) self.play( Write(origin_words), GrowFromCenter(dot), ShowCreation(line), run_time = 1 ) self.wait(2) self.play( FadeOut(VMobject(origin_words, dot, line)) ) self.remove(origin_words, dot, line) self.wait() self.play( ShowCreation(tick_marks, submobject_mode = "one_at_a_time") ) self.play( GrowFromCenter(unit_brace), Write(one, run_time = 1) ) self.wait(2) self.remove(unit_brace, one) self.play( *map(GrowFromCenter, plane_lines) + [ Animation(x_axis), Animation(y_axis) ]) self.wait() self.play( FadeOut(plane), Animation(VMobject(x_axis, y_axis, tick_marks)) ) self.remove(plane) self.add(tick_marks)
def scroll_through_patrons(self): logo_box = Square(side_length=2.5) logo_box.to_corner(DOWN + LEFT, buff=MED_LARGE_BUFF) total_width = FRAME_X_RADIUS - logo_box.get_right()[0] black_rect = Rectangle( fill_color=BLACK, fill_opacity=1, stroke_width=0, width=FRAME_WIDTH, height=0.6 * FRAME_HEIGHT, ) black_rect.to_edge(UP, buff=0) line = DashedLine(FRAME_X_RADIUS * LEFT, FRAME_X_RADIUS * RIGHT) line.move_to(ORIGIN) self.add(line) thanks = TextMobject("Funded by the community, with special thanks to:") thanks.scale(0.9) thanks.next_to(black_rect.get_bottom(), UP, SMALL_BUFF) thanks.set_color(YELLOW) underline = Line(LEFT, RIGHT) underline.scale_to_fit_width(thanks.get_width() + MED_SMALL_BUFF) underline.next_to(thanks, DOWN, SMALL_BUFF) thanks.add(underline) self.add(thanks) patrons = VGroup(*map(TextMobject, self.specific_patrons)) patrons.scale(self.patron_scale_val) for patron in patrons: if patron.get_width() > self.max_patron_width: patron.scale_to_fit_width(self.max_patron_width) columns = VGroup(*[ VGroup(*patrons[i::self.n_patron_columns]) for i in range(self.n_patron_columns) ]) for column in columns: for n, name in enumerate(column): name.shift(n * self.name_y_spacing * DOWN) columns.arrange_submobjects( RIGHT, buff=LARGE_BUFF, aligned_edge=UP, ) columns.scale_to_fit_width(total_width - 1) columns.next_to(black_rect, DOWN, 3 * LARGE_BUFF) columns.to_edge(RIGHT) thanks.align_to(columns, alignment_vect=RIGHT) self.play( columns.move_to, 2 * DOWN, DOWN, columns.to_edge, RIGHT, Animation(black_rect), Animation(line), Animation(thanks), rate_func=None, run_time=self.run_time, )
def update_mobject(self, alpha): Animation.update_mobject(self, alpha) angle_revs = self.rotate_func(alpha) # We do a clockwise rotation self.mobject.rotate( -angle_revs * TAU, about_point = ORIGIN ) self.mobject.set_color(color_func(angle_revs))
def grow_number_line(self): line = NumberLine(stroke_width=2).add_numbers() line.rotate(self.v.get_angle()) self.play(Write(line), Animation(self.v)) self.play(line.highlight, self.v.get_color(), Animation(self.v), rate_func=there_and_back) self.dither()
def __init__(self, homotopy, mobject, **kwargs): """ Homotopy a function from (x, y, z, t) to (x', y', z') """ def function_at_time_t(t): return lambda p: homotopy(p[0], p[1], p[2], t) self.function_at_time_t = function_at_time_t digest_config(self, kwargs) Animation.__init__(self, mobject, **kwargs)
def __init__(self, AnimationClass, mobjects, **kwargs): full_kwargs = AnimationClass.CONFIG full_kwargs.update(kwargs) full_kwargs["mobject"] = Mobject( *[mob.get_point_mobject() for mob in mobjects]) self.centers_container = AnimationClass(**full_kwargs) full_kwargs.pop("mobject") Animation.__init__(self, Mobject(*mobjects), **full_kwargs) self.name = str(self) + AnimationClass.__name__
def update_mobject(self, alpha): Animation.update_mobject(self, alpha) angle = alpha * self.num_spirils * 2 * np.pi vert_shift = alpha * self.total_vert_shift start_center = self.mobject.get_center() self.mobject.shift(self.spiril_radius * OUT) self.mobject.rotate(angle, axis=UP, about_point=start_center) self.mobject.shift(vert_shift * DOWN)
def __init__(self, clock, **kwargs): assert (isinstance(clock, Clock)) rot_kwargs = {"axis": OUT, "in_place": True} self.hour_rotation = Rotating(clock.hour_hand, radians=-2 * np.pi, **rot_kwargs) self.minute_rotation = Rotating(clock.minute_hand, radians=-12 * 2 * np.pi, **rot_kwargs) Animation.__init__(self, clock, **kwargs)
def update_mobject(self, alpha): Animation.update_mobject(self, alpha) if self.in_place and self.about_point is None: self.about_point = self.mobject.get_center() self.mobject.rotate( alpha * self.radians, axis=self.axis, about_point=self.about_point, about_edge=self.about_edge, )
def __init__(self, walk_func, rev_func, coords_to_point, **kwargs): self.walk_func = walk_func self.rev_func = rev_func self.coords_to_point = coords_to_point self.compound_walker = VGroup() self.compound_walker.walker = PiCreature(color=RED) self.compound_walker.walker.scale(0.35) self.compound_walker.arrow = Arrow(ORIGIN, RIGHT) #, buff = 0) self.compound_walker.digest_mobject_attrs() Animation.__init__(self, self.compound_walker, **kwargs)
def clean_up(self, surrounding_scene=None): Animation.clean_up(self, surrounding_scene) if self.replace_mobject_with_target_in_scene \ and surrounding_scene is not None: if hasattr(self, "parent"): self.parent.remove(self.mobject) if not self.remover: self.parent.add(self.original_target_mobject) surrounding_scene.remove(self.mobject) if not self.remover: surrounding_scene.add(self.original_target_mobject)
def __init__(self, AnimationClass, mobjects, **kwargs): full_kwargs = AnimationClass.CONFIG full_kwargs.update(kwargs) full_kwargs["mobject"] = Mobject(*[ mob.get_point_mobject() for mob in mobjects ]) self.centers_container = AnimationClass(**full_kwargs) full_kwargs.pop("mobject") Animation.__init__(self, Mobject(*mobjects), **full_kwargs) self.name = str(self) + AnimationClass.__name__
def update_mobject(self, alpha): Animation.update_mobject(self, alpha) cur_x, cur_y = cur_coords = self.walk_func(alpha) cur_point = self.coords_to_point(cur_x, cur_y) self.mobject.shift(cur_point - self.mobject.walker.get_center()) rev = self.rev_func(cur_coords) self.mobject.walker.set_fill(rev_to_color(rev)) if self.show_arrows: self.mobject.arrow.set_fill(rev_to_color(rev)) self.mobject.arrow.rotate( rev * TAU, about_point=self.mobject.arrow.get_start())
def update_mobject(self, alpha): Animation.update_mobject(self, alpha) cur_x, cur_y = cur_coords = self.walk_func(alpha) self.mobject.walker.move_to(self.coords_to_point(cur_x, cur_y)) rev = self.rev_func(cur_coords) self.mobject.walker.set_color(color_func(rev)) self.mobject.arrow.set_color(color_func(rev)) self.mobject.arrow.rotate( rev * TAU, about_point=ORIGIN #self.mobject.arrow.get_start() )
def __init__(self, walk_func, rev_func, coords_to_point, show_arrows = True, **kwargs): self.walk_func = walk_func self.rev_func = rev_func self.coords_to_point = coords_to_point self.compound_walker = VGroup() base_walker = Dot().scale(5) # PiCreature().scale(0.8) # self.compound_walker.walker = base_walker.scale(0.35).set_stroke(BLACK, 1.5) #PiCreature() if show_arrows: self.compound_walker.arrow = Arrow(ORIGIN, 0.5 * RIGHT, buff = 0).set_stroke(BLACK, 1.5) self.compound_walker.digest_mobject_attrs() Animation.__init__(self, self.compound_walker, **kwargs)
def __init__(self, mobject, target_mobject, **kwargs): # Copy target_mobject so as to not mess with caller self.original_target_mobject = target_mobject target_mobject = target_mobject.copy() mobject.align_data(target_mobject) self.target_mobject = target_mobject digest_config(self, kwargs) self.init_path_func() Animation.__init__(self, mobject, **kwargs) self.name += "To" + str(target_mobject)
def construct(self): vector = Vector([-2, 3]) plane = NumberPlane() axis_labels = plane.get_axis_labels() other_vectors = VMobject(*map(Vector, [[1, 2], [2, -1], [4, 0]])) colors = [GREEN_B, MAROON_B, PINK] for v, color in zip(other_vectors.split(), colors): v.highlight(color) shift_val = 4 * RIGHT + DOWN dot = Dot(radius=0.1) dot.highlight(RED) tail_word = TextMobject("Tail") tail_word.shift(0.5 * DOWN + 2.5 * LEFT) line = Line(tail_word, dot) self.play(ShowCreation(vector, submobject_mode="one_at_a_time")) self.dither(2) self.play(ShowCreation(plane, summobject_mode="lagged_start"), Animation(vector)) self.play(Write(axis_labels, run_time=1)) self.dither() self.play(GrowFromCenter(dot), ShowCreation(line), Write(tail_word, run_time=1)) self.dither() self.play(FadeOut(tail_word), ApplyMethod(VMobject(dot, line).scale, 0.01)) self.remove(tail_word, line, dot) self.dither() self.play( ApplyMethod(vector.shift, shift_val, path_arc=3 * np.pi / 2, run_time=3)) self.play( ApplyMethod(vector.shift, -shift_val, rate_func=rush_into, run_time=0.5)) self.dither(3) self.play( ShowCreation(other_vectors, submobject_mode="one_at_a_time", run_time=3)) self.dither(3) x_axis, y_axis = plane.get_axes().split() x_label = axis_labels.split()[0] x_axis = x_axis.copy() x_label = x_label.copy() everything = VMobject(*self.mobjects) self.play(FadeOut(everything), Animation(x_axis), Animation(x_label))
def __init__(self, clock, **kwargs): digest_config(self, kwargs) assert (isinstance(clock, Clock)) rot_kwargs = {"axis": OUT, "about_point": clock.get_center()} hour_radians = -self.hours_passed * 2 * np.pi / 12 self.hour_rotation = Rotating(clock.hour_hand, radians=hour_radians, **rot_kwargs) self.minute_rotation = Rotating(clock.minute_hand, radians=12 * hour_radians, **rot_kwargs) Animation.__init__(self, clock, **kwargs)
def __init__(self, mobject, **kwargs): self.old_angles = [] for (i, sector) in enumerate(mobject.submobjects): self.old_angles.append(sector.angle) self.old_angles = np.array(self.old_angles) self.old_start_angles = np.cumsum( self.old_angles) - self.old_angles + TAU / 4 digest_config(self, kwargs) Animation.__init__(self, mobject, **kwargs)
def __init__(self, *sub_anims, **kwargs): sub_anims = filter(lambda x: not(x.empty), sub_anims) digest_config(self, locals()) self.update_config(**kwargs) # Handles propagation to self.sub_anims if len(sub_anims) == 0: self.empty = True self.run_time = 0 else: self.run_time = max([a.run_time for a in sub_anims]) everything = Mobject(*[a.mobject for a in sub_anims]) Animation.__init__(self, everything, **kwargs)
def __init__(self, *sub_anims, **kwargs): sub_anims = [x for x in sub_anims if not (x.empty)] digest_config(self, locals()) self.update_config(**kwargs) # Handles propagation to self.sub_anims if len(sub_anims) == 0: self.empty = True self.run_time = 0 else: self.run_time = max([a.run_time for a in sub_anims]) everything = Mobject(*[a.mobject for a in sub_anims]) Animation.__init__(self, everything, **kwargs)
def show_curvature(self): positive_curve, negative_curve = [ self.get_graph( self.graph.underlying_function, x_min = x_min, x_max = x_max, color = color, ).set_stroke(width = 6) for x_min, x_max, color in [ (self.x2, self.x3, PINK), (self.x1, self.x2, RED), ] ] dot = Dot() def get_dot_update_func(curve): def update_dot(dot): dot.move_to(curve.points[-1]) return dot return update_dot self.play( ShowCreation(positive_curve, run_time = 3), UpdateFromFunc(dot, get_dot_update_func(positive_curve)) ) self.play(FadeOut(dot)) self.wait() self.animate_secant_slope_group_change( self.ss_group, target_x = self.x3, run_time = 4, added_anims = [Animation(positive_curve)] ) self.play(*map(FadeOut, [self.ss_group, positive_curve])) self.animate_secant_slope_group_change( self.ss_group, target_x = self.x1, run_time = 0 ) self.play(FadeIn(self.ss_group)) self.play( ShowCreation(negative_curve, run_time = 3), UpdateFromFunc(dot, get_dot_update_func(negative_curve)) ) self.play(FadeOut(dot)) self.animate_secant_slope_group_change( self.ss_group, target_x = self.x2, run_time = 4, added_anims = [Animation(negative_curve)] ) self.wait(2) self.play(*map(FadeOut, [ self.graph, self.ss_group, negative_curve, self.second_deriv_words ]))
def __init__(self, decimal_number_mobject, number_update_func, **kwargs): digest_config(self, kwargs, locals()) self.decimal_number_config = dict( decimal_number_mobject.initial_config ) for attr in "num_decimal_places", "show_ellipsis": value = getattr(self, attr) if value is not None: self.decimal_number_config[attr] = value if hasattr(self.decimal_number_mobject, "background_rectangle"): self.decimal_number_config["include_background_rectangle"] = True if self.tracked_mobject: dmc = decimal_number_mobject.get_center() tmc = self.tracked_mobject.get_center() self.diff_from_tracked_mobject = dmc - tmc Animation.__init__(self, decimal_number_mobject, **kwargs)
def __init__(self, clock, **kwargs): digest_config(self, kwargs) assert(isinstance(clock, Clock)) rot_kwargs = { "axis": OUT, "about_point": clock.get_center() } hour_radians = -self.hours_passed * 2 * np.pi / 12 self.hour_rotation = Rotating( clock.hour_hand, radians=hour_radians, **rot_kwargs ) self.minute_rotation = Rotating( clock.minute_hand, radians=12 * hour_radians, **rot_kwargs ) Animation.__init__(self, clock, **kwargs)
def __init__(self, **kwargs): digest_config(self, kwargs) x_axis = NumberLine( x_min = -3, x_max = 3, color = BLUE_E ) y_axis = x_axis.copy().rotate(np.pi/2) circle = Circle(color = WHITE) self.trig_lines = [ Line(ORIGIN, RIGHT, color = color) for color in self.sin_color, self.cos_color, self.tan_color ] mobject = VMobject( x_axis, y_axis, circle, *self.trig_lines ) mobject.to_edge(RIGHT) self.center = mobject.get_center() Animation.__init__(self, mobject, **kwargs)
def __init__(self, AnimationClass, mobject, arg_creator=None, **kwargs): digest_config(self, kwargs) for key in "rate_func", "run_time", "lag_ratio": if key in kwargs: kwargs.pop(key) if arg_creator is None: def arg_creator(mobject): return (mobject,) self.subanimations = [ AnimationClass( *arg_creator(submob), run_time=self.run_time, rate_func=squish_rate_func( self.rate_func, beta, beta + self.lag_ratio ), **kwargs ) for submob, beta in zip( mobject, np.linspace(0, 1 - self.lag_ratio, len(mobject)) ) ] Animation.__init__(self, mobject, **kwargs)
def __init__(self, mobject=None, **kwargs): if mobject is None: mobject = Line(3 * LEFT, 3 * RIGHT) Animation.__init__(self, mobject, **kwargs)
def __init__(self, *args, **kwargs): return Animation.__init__(self, Group(), *args, **kwargs)
def __init__(self, mobject, tracked_mobject, **kwargs): digest_config(self, kwargs, locals()) tcp = self.tracked_critical_point self.diff = mobject.get_critical_point(tcp) - \ tracked_mobject.get_critical_point(tcp) Animation.__init__(self, mobject, **kwargs)
def __init__(self, tex_list, **kwargs): mobject = TexMobject(self.curr_tex).shift(start_center) Animation.__init__(self, mobject, **kwargs)
def __init__(self, mobject, path, **kwargs): digest_config(self, kwargs, locals()) Animation.__init__(self, mobject, **kwargs)
def __init__(self, vmobject, **kwargs): if not isinstance(vmobject, VMobject): raise Exception("DrawBorderThenFill only works for VMobjects") self.reached_halfway_point_before = False Animation.__init__(self, vmobject, **kwargs)
def __init__(self, *args, **kwargs): """ Each arg will either be an animation, or an animation class followed by its arguments (and potentially a dict for configuration). For example, Succession( ShowCreation(circle), Transform, circle, square, Transform, circle, triangle, ApplyMethod, circle.shift, 2*UP, {"run_time" : 2}, ) """ animations = [] state = { "animations": animations, "curr_class": None, "curr_class_args": [], "curr_class_config": {}, } def invoke_curr_class(state): if state["curr_class"] is None: return anim = state["curr_class"]( *state["curr_class_args"], **state["curr_class_config"] ) state["animations"].append(anim) anim.update(1) state["curr_class"] = None state["curr_class_args"] = [] state["curr_class_config"] = {} for arg in args: if isinstance(arg, Animation): animations.append(arg) arg.update(1) invoke_curr_class(state) elif isinstance(arg, type) and issubclass(arg, Animation): invoke_curr_class(state) state["curr_class"] = arg elif isinstance(arg, dict): state["curr_class_config"] = arg else: state["curr_class_args"].append(arg) invoke_curr_class(state) for anim in animations: anim.update(0) animations = filter(lambda x: not(x.empty), animations) self.run_times = [anim.run_time for anim in animations] if "run_time" in kwargs: run_time = kwargs.pop("run_time") warnings.warn( "Succession doesn't currently support explicit run_time.") run_time = sum(self.run_times) self.num_anims = len(animations) if self.num_anims == 0: self.empty = True self.animations = animations # Have to keep track of this run_time, because Scene.play # might very well mess with it. self.original_run_time = run_time # critical_alphas[i] is the start alpha of self.animations[i] # critical_alphas[i + 1] is the end alpha of self.animations[i] critical_times = np.concatenate(([0], np.cumsum(self.run_times))) self.critical_alphas = map(lambda x: np.true_divide( x, run_time), critical_times) if self.num_anims > 0 else [0.0] # self.scene_mobjects_at_time[i] is the scene's mobjects at start of self.animations[i] # self.scene_mobjects_at_time[i + 1] is the scene mobjects at end of self.animations[i] self.scene_mobjects_at_time = [None for i in range(self.num_anims + 1)] self.scene_mobjects_at_time[0] = Group() for i in range(self.num_anims): self.scene_mobjects_at_time[i + 1] = self.scene_mobjects_at_time[i].copy() self.animations[i].clean_up(self.scene_mobjects_at_time[i + 1]) self.current_alpha = 0 # If self.num_anims == 0, this is an invalid index, but so it goes self.current_anim_index = 0 if self.num_anims > 0: self.mobject = self.scene_mobjects_at_time[0] self.mobject.add(self.animations[0].mobject) else: self.mobject = Group() Animation.__init__(self, self.mobject, run_time=run_time, **kwargs)
def __init__(self, mobject, update_function, **kwargs): digest_config(self, kwargs, locals()) Animation.__init__(self, mobject, **kwargs)