diff --git a/animation/simple_animations.py b/animation/simple_animations.py index 331c4e0f..0ae54a2f 100644 --- a/animation/simple_animations.py +++ b/animation/simple_animations.py @@ -33,7 +33,7 @@ class Rotating(Animation): class ShowPartial(Animation): CONFIG = { - "one_submobject_at_a_time" : False + "submobject_mode" : None } def update_mobject(self, alpha): pairs = zip( @@ -41,7 +41,11 @@ class ShowPartial(Animation): self.mobject.submobject_family() ) for i, (start, mob) in enumerate(pairs): - if self.one_submobject_at_a_time: + if self.submobject_mode == "lagged_start": + sub_alpha = 2*alpha - float(i)/len(pairs) + sub_alpha = max(0, sub_alpha) + sub_alpha = min(1, sub_alpha) + elif self.submobject_mode == "one_at_a_time": lower = float(i)/len(pairs) upper = float(i+1)/len(pairs) sub_alpha = (alpha-lower)/(upper-lower) @@ -61,10 +65,17 @@ class ShowCreation(ShowPartial): class ShowCreationPerSubmobject(ShowCreation): CONFIG = { - "one_submobject_at_a_time" : True, + "submobject_mode" : "one_at_a_time", "run_time" : 3 } +class Write(ShowCreation): + CONFIG = { + "run_time" : 3, + "rate_func" : None, + "submobject_mode" : "lagged_start", + } + class ShowPassingFlash(ShowPartial): CONFIG = { "time_width" : 0.1 diff --git a/mobject/mobject.py b/mobject/mobject.py index a443e612..199c0546 100644 --- a/mobject/mobject.py +++ b/mobject/mobject.py @@ -470,11 +470,14 @@ class Mobject(object): for index in indices: submob = self.submobjects[index] if submob in new_submobjects: - submob = submob.copy() + submob = self.repeat_submobject(submob) new_submobjects.append(submob) self.submobjects = new_submobjects return self + def repeat_submobject(self, submob): + return submob.copy() + def interpolate(self, mobject1, mobject2, alpha, path_func): """ Turns target_mobject into an interpolation between mobject1 diff --git a/mobject/svg_mobject.py b/mobject/svg_mobject.py index fb8e535f..e2776a06 100644 --- a/mobject/svg_mobject.py +++ b/mobject/svg_mobject.py @@ -32,7 +32,9 @@ class SVGMobject(VMobject): for child in element.childNodes ]) elif element.tagName == 'path': - result.append(self.path_to_mobject(element)) + result.append(self.path_string_to_mobject( + element.getAttribute('d') + )) elif element.tagName == 'use': result += self.use_to_mobjects(element) elif element.tagName == 'rect': @@ -50,21 +52,18 @@ class SVGMobject(VMobject): self.handle_transforms(g_element, mob) return mob.submobjects - def path_to_mobject(self, path_element): - return VMobjectFromSVGPathstring( - path_element.getAttribute('d') - ) + def path_string_to_mobject(self, path_string): + return VMobjectFromSVGPathstring(path_string) def use_to_mobjects(self, use_element): #Remove initial "#" character ref = use_element.getAttribute("xlink:href")[1:] - try: - return self.get_mobjects_from( - self.ref_to_element[ref] - ) - except: + if ref not in self.ref_to_element: warnings.warn("%s not recognized"%ref) - return + return VMobject() + return self.get_mobjects_from( + self.ref_to_element[ref] + ) # @@ -184,7 +183,7 @@ class VMobjectFromSVGPathstring(VMobject): if not is_closed(points): #Both handles and new anchor are the start new_points = points[[0, 0, 0]] - self.mark_paths_closed = True + # self.mark_paths_closed = True self.growing_path.add_control_points(new_points) def string_to_points(self, coord_string): diff --git a/mobject/tex_mobject.py b/mobject/tex_mobject.py index 39e7e3ef..4dc09a5a 100644 --- a/mobject/tex_mobject.py +++ b/mobject/tex_mobject.py @@ -1,8 +1,28 @@ from vectorized_mobject import VMobject -from svg_mobject import SVGMobject +from svg_mobject import SVGMobject, VMobjectFromSVGPathstring from helpers import * -TEX_MOB_SCALE_VAL = 0.05 +TEX_MOB_SCALE_VAL = 0.1 +TEXT_MOB_SCALE_VAL = 0.2 + + +class TexSymbol(VMobjectFromSVGPathstring): + def become_partial(self, mobject, a, b): + #TODO, this assumes a = 0 + if b < 0.5: + b = 2*b + width = 1 + opacity = 0 + else: + width = 2 - 2*b + opacity = 2*b - 1 + b = 1 + VMobjectFromSVGPathstring.become_partial( + self, mobject, 0, b + ) + self.set_stroke(width = width) + self.set_fill(opacity = opacity) + class TexMobject(SVGMobject): CONFIG = { @@ -13,6 +33,7 @@ class TexMobject(SVGMobject): "should_center" : True, "next_to_direction" : RIGHT, "next_to_buff" : 0.2, + "initial_scale_val" : TEX_MOB_SCALE_VAL, } def __init__(self, expression, **kwargs): digest_config(self, kwargs, locals()) @@ -20,6 +41,12 @@ class TexMobject(SVGMobject): self.move_into_position() self.organize_submobjects() + def path_string_to_mobject(self, path_string): + #Overwrite superclass default to use + #specialized path_string mobject + return TexSymbol(path_string) + + def generate_points(self): if isinstance(self.expression, list): self.handle_list_expression() @@ -34,7 +61,8 @@ class TexMobject(SVGMobject): def handle_list_expression(self): #TODO, next_to not sufficient? subs = [ - TexMobject(expr) + # TexMobject(expr) + self.__class__(expr) for expr in self.expression ] for sm1, sm2 in zip(subs, subs[1:]): @@ -53,13 +81,15 @@ class TexMobject(SVGMobject): def move_into_position(self): self.center() - self.scale(TEX_MOB_SCALE_VAL) + self.scale(self.initial_scale_val) self.init_colors() + class TextMobject(TexMobject): CONFIG = { "template_tex_file" : TEMPLATE_TEXT_FILE, + "initial_scale_val" : TEXT_MOB_SCALE_VAL, } diff --git a/mobject/vectorized_mobject.py b/mobject/vectorized_mobject.py index 3d4b1625..6aba9548 100644 --- a/mobject/vectorized_mobject.py +++ b/mobject/vectorized_mobject.py @@ -146,9 +146,8 @@ class VMobject(Mobject): but will be tracked in a separate special list for when it comes time to display. """ - subpath_mobject = VMobject( - is_subpath = True - ) + subpath_mobject = self.copy()#TODO, better way? + subpath_mobject.is_subpath = True subpath_mobject.set_points(points) self.add(subpath_mobject) return subpath_mobject @@ -190,9 +189,9 @@ class VMobject(Mobject): Mobject.align_points(self, mobject) is_subpath = self.is_subpath or mobject.is_subpath self.is_subpath = mobject.is_subpath = is_subpath - mark_closed = self.mark_paths_closed and mobject.mark_paths_closed + mark_closed = self.mark_paths_closed and mobject.mark_paths_closed self.mark_paths_closed = mobject.mark_paths_closed = mark_closed - return self + return self def align_points_with_larger(self, larger_mobject): assert(isinstance(larger_mobject, VMobject)) @@ -208,7 +207,7 @@ class VMobject(Mobject): self.points = np.zeros((1, 3)) n = n-1 if curr == 1: - self.points = np.repeat(self.points, n+1) + self.points = np.repeat(self.points, 3*n+1, axis = 0) return self points = np.array([self.points[0]]) num_curves = curr-1 @@ -237,6 +236,11 @@ class VMobject(Mobject): center = self.get_center() return VectorizedPoint(center) + def repeat_submobject(self, submobject): + if submobject.is_subpath: + return VectorizedPoint(submobject.points[0]) + return submobject.copy() + def interpolate_color(self, mobject1, mobject2, alpha): attrs = [ "stroke_rgb", @@ -285,7 +289,7 @@ class VectorizedPoint(VMobject): } def __init__(self, location = ORIGIN, **kwargs): VMobject.__init__(self, **kwargs) - self.set_points([location]) + self.set_points(np.array([location])) diff --git a/topics/geometry.py b/topics/geometry.py index 5e807aeb..4918d8e3 100644 --- a/topics/geometry.py +++ b/topics/geometry.py @@ -85,8 +85,7 @@ class Line(VMobject): def pointify(self, mob_or_point): if isinstance(mob_or_point, Mobject): return mob_or_point.get_center() - else: - return np.array(mob_or_point) + return np.array(mob_or_point) def generate_points(self): self.set_points_as_corners([self.start, self.end])