mirror of
https://github.com/3b1b/manim.git
synced 2025-08-02 02:35:22 +08:00
Write class is looking pretty nice.
This commit is contained in:
@ -33,7 +33,7 @@ class Rotating(Animation):
|
|||||||
|
|
||||||
class ShowPartial(Animation):
|
class ShowPartial(Animation):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"one_submobject_at_a_time" : False
|
"submobject_mode" : None
|
||||||
}
|
}
|
||||||
def update_mobject(self, alpha):
|
def update_mobject(self, alpha):
|
||||||
pairs = zip(
|
pairs = zip(
|
||||||
@ -41,7 +41,11 @@ class ShowPartial(Animation):
|
|||||||
self.mobject.submobject_family()
|
self.mobject.submobject_family()
|
||||||
)
|
)
|
||||||
for i, (start, mob) in enumerate(pairs):
|
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)
|
lower = float(i)/len(pairs)
|
||||||
upper = float(i+1)/len(pairs)
|
upper = float(i+1)/len(pairs)
|
||||||
sub_alpha = (alpha-lower)/(upper-lower)
|
sub_alpha = (alpha-lower)/(upper-lower)
|
||||||
@ -61,10 +65,17 @@ class ShowCreation(ShowPartial):
|
|||||||
|
|
||||||
class ShowCreationPerSubmobject(ShowCreation):
|
class ShowCreationPerSubmobject(ShowCreation):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"one_submobject_at_a_time" : True,
|
"submobject_mode" : "one_at_a_time",
|
||||||
"run_time" : 3
|
"run_time" : 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Write(ShowCreation):
|
||||||
|
CONFIG = {
|
||||||
|
"run_time" : 3,
|
||||||
|
"rate_func" : None,
|
||||||
|
"submobject_mode" : "lagged_start",
|
||||||
|
}
|
||||||
|
|
||||||
class ShowPassingFlash(ShowPartial):
|
class ShowPassingFlash(ShowPartial):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"time_width" : 0.1
|
"time_width" : 0.1
|
||||||
|
@ -470,11 +470,14 @@ class Mobject(object):
|
|||||||
for index in indices:
|
for index in indices:
|
||||||
submob = self.submobjects[index]
|
submob = self.submobjects[index]
|
||||||
if submob in new_submobjects:
|
if submob in new_submobjects:
|
||||||
submob = submob.copy()
|
submob = self.repeat_submobject(submob)
|
||||||
new_submobjects.append(submob)
|
new_submobjects.append(submob)
|
||||||
self.submobjects = new_submobjects
|
self.submobjects = new_submobjects
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def repeat_submobject(self, submob):
|
||||||
|
return submob.copy()
|
||||||
|
|
||||||
def interpolate(self, mobject1, mobject2, alpha, path_func):
|
def interpolate(self, mobject1, mobject2, alpha, path_func):
|
||||||
"""
|
"""
|
||||||
Turns target_mobject into an interpolation between mobject1
|
Turns target_mobject into an interpolation between mobject1
|
||||||
|
@ -32,7 +32,9 @@ class SVGMobject(VMobject):
|
|||||||
for child in element.childNodes
|
for child in element.childNodes
|
||||||
])
|
])
|
||||||
elif element.tagName == 'path':
|
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':
|
elif element.tagName == 'use':
|
||||||
result += self.use_to_mobjects(element)
|
result += self.use_to_mobjects(element)
|
||||||
elif element.tagName == 'rect':
|
elif element.tagName == 'rect':
|
||||||
@ -50,21 +52,18 @@ class SVGMobject(VMobject):
|
|||||||
self.handle_transforms(g_element, mob)
|
self.handle_transforms(g_element, mob)
|
||||||
return mob.submobjects
|
return mob.submobjects
|
||||||
|
|
||||||
def path_to_mobject(self, path_element):
|
def path_string_to_mobject(self, path_string):
|
||||||
return VMobjectFromSVGPathstring(
|
return VMobjectFromSVGPathstring(path_string)
|
||||||
path_element.getAttribute('d')
|
|
||||||
)
|
|
||||||
|
|
||||||
def use_to_mobjects(self, use_element):
|
def use_to_mobjects(self, use_element):
|
||||||
#Remove initial "#" character
|
#Remove initial "#" character
|
||||||
ref = use_element.getAttribute("xlink:href")[1:]
|
ref = use_element.getAttribute("xlink:href")[1:]
|
||||||
try:
|
if ref not in self.ref_to_element:
|
||||||
return self.get_mobjects_from(
|
|
||||||
self.ref_to_element[ref]
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
warnings.warn("%s not recognized"%ref)
|
warnings.warn("%s not recognized"%ref)
|
||||||
return
|
return VMobject()
|
||||||
|
return self.get_mobjects_from(
|
||||||
|
self.ref_to_element[ref]
|
||||||
|
)
|
||||||
|
|
||||||
# <circle class="st1" cx="143.8" cy="268" r="22.6"/>
|
# <circle class="st1" cx="143.8" cy="268" r="22.6"/>
|
||||||
|
|
||||||
@ -184,7 +183,7 @@ class VMobjectFromSVGPathstring(VMobject):
|
|||||||
if not is_closed(points):
|
if not is_closed(points):
|
||||||
#Both handles and new anchor are the start
|
#Both handles and new anchor are the start
|
||||||
new_points = points[[0, 0, 0]]
|
new_points = points[[0, 0, 0]]
|
||||||
self.mark_paths_closed = True
|
# self.mark_paths_closed = True
|
||||||
self.growing_path.add_control_points(new_points)
|
self.growing_path.add_control_points(new_points)
|
||||||
|
|
||||||
def string_to_points(self, coord_string):
|
def string_to_points(self, coord_string):
|
||||||
|
@ -1,8 +1,28 @@
|
|||||||
from vectorized_mobject import VMobject
|
from vectorized_mobject import VMobject
|
||||||
from svg_mobject import SVGMobject
|
from svg_mobject import SVGMobject, VMobjectFromSVGPathstring
|
||||||
from helpers import *
|
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):
|
class TexMobject(SVGMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
@ -13,6 +33,7 @@ class TexMobject(SVGMobject):
|
|||||||
"should_center" : True,
|
"should_center" : True,
|
||||||
"next_to_direction" : RIGHT,
|
"next_to_direction" : RIGHT,
|
||||||
"next_to_buff" : 0.2,
|
"next_to_buff" : 0.2,
|
||||||
|
"initial_scale_val" : TEX_MOB_SCALE_VAL,
|
||||||
}
|
}
|
||||||
def __init__(self, expression, **kwargs):
|
def __init__(self, expression, **kwargs):
|
||||||
digest_config(self, kwargs, locals())
|
digest_config(self, kwargs, locals())
|
||||||
@ -20,6 +41,12 @@ class TexMobject(SVGMobject):
|
|||||||
self.move_into_position()
|
self.move_into_position()
|
||||||
self.organize_submobjects()
|
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):
|
def generate_points(self):
|
||||||
if isinstance(self.expression, list):
|
if isinstance(self.expression, list):
|
||||||
self.handle_list_expression()
|
self.handle_list_expression()
|
||||||
@ -34,7 +61,8 @@ class TexMobject(SVGMobject):
|
|||||||
def handle_list_expression(self):
|
def handle_list_expression(self):
|
||||||
#TODO, next_to not sufficient?
|
#TODO, next_to not sufficient?
|
||||||
subs = [
|
subs = [
|
||||||
TexMobject(expr)
|
# TexMobject(expr)
|
||||||
|
self.__class__(expr)
|
||||||
for expr in self.expression
|
for expr in self.expression
|
||||||
]
|
]
|
||||||
for sm1, sm2 in zip(subs, subs[1:]):
|
for sm1, sm2 in zip(subs, subs[1:]):
|
||||||
@ -53,13 +81,15 @@ class TexMobject(SVGMobject):
|
|||||||
|
|
||||||
def move_into_position(self):
|
def move_into_position(self):
|
||||||
self.center()
|
self.center()
|
||||||
self.scale(TEX_MOB_SCALE_VAL)
|
self.scale(self.initial_scale_val)
|
||||||
self.init_colors()
|
self.init_colors()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TextMobject(TexMobject):
|
class TextMobject(TexMobject):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"template_tex_file" : TEMPLATE_TEXT_FILE,
|
"template_tex_file" : TEMPLATE_TEXT_FILE,
|
||||||
|
"initial_scale_val" : TEXT_MOB_SCALE_VAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,9 +146,8 @@ class VMobject(Mobject):
|
|||||||
but will be tracked in a separate special list for when
|
but will be tracked in a separate special list for when
|
||||||
it comes time to display.
|
it comes time to display.
|
||||||
"""
|
"""
|
||||||
subpath_mobject = VMobject(
|
subpath_mobject = self.copy()#TODO, better way?
|
||||||
is_subpath = True
|
subpath_mobject.is_subpath = True
|
||||||
)
|
|
||||||
subpath_mobject.set_points(points)
|
subpath_mobject.set_points(points)
|
||||||
self.add(subpath_mobject)
|
self.add(subpath_mobject)
|
||||||
return subpath_mobject
|
return subpath_mobject
|
||||||
@ -190,9 +189,9 @@ class VMobject(Mobject):
|
|||||||
Mobject.align_points(self, mobject)
|
Mobject.align_points(self, mobject)
|
||||||
is_subpath = self.is_subpath or mobject.is_subpath
|
is_subpath = self.is_subpath or mobject.is_subpath
|
||||||
self.is_subpath = mobject.is_subpath = 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
|
self.mark_paths_closed = mobject.mark_paths_closed = mark_closed
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def align_points_with_larger(self, larger_mobject):
|
def align_points_with_larger(self, larger_mobject):
|
||||||
assert(isinstance(larger_mobject, VMobject))
|
assert(isinstance(larger_mobject, VMobject))
|
||||||
@ -208,7 +207,7 @@ class VMobject(Mobject):
|
|||||||
self.points = np.zeros((1, 3))
|
self.points = np.zeros((1, 3))
|
||||||
n = n-1
|
n = n-1
|
||||||
if curr == 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
|
return self
|
||||||
points = np.array([self.points[0]])
|
points = np.array([self.points[0]])
|
||||||
num_curves = curr-1
|
num_curves = curr-1
|
||||||
@ -237,6 +236,11 @@ class VMobject(Mobject):
|
|||||||
center = self.get_center()
|
center = self.get_center()
|
||||||
return VectorizedPoint(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):
|
def interpolate_color(self, mobject1, mobject2, alpha):
|
||||||
attrs = [
|
attrs = [
|
||||||
"stroke_rgb",
|
"stroke_rgb",
|
||||||
@ -285,7 +289,7 @@ class VectorizedPoint(VMobject):
|
|||||||
}
|
}
|
||||||
def __init__(self, location = ORIGIN, **kwargs):
|
def __init__(self, location = ORIGIN, **kwargs):
|
||||||
VMobject.__init__(self, **kwargs)
|
VMobject.__init__(self, **kwargs)
|
||||||
self.set_points([location])
|
self.set_points(np.array([location]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,8 +85,7 @@ class Line(VMobject):
|
|||||||
def pointify(self, mob_or_point):
|
def pointify(self, mob_or_point):
|
||||||
if isinstance(mob_or_point, Mobject):
|
if isinstance(mob_or_point, Mobject):
|
||||||
return mob_or_point.get_center()
|
return mob_or_point.get_center()
|
||||||
else:
|
return np.array(mob_or_point)
|
||||||
return np.array(mob_or_point)
|
|
||||||
|
|
||||||
def generate_points(self):
|
def generate_points(self):
|
||||||
self.set_points_as_corners([self.start, self.end])
|
self.set_points_as_corners([self.start, self.end])
|
||||||
|
Reference in New Issue
Block a user