mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
Introduced update_submobject to Animation. I'd be surprised if this didn't break something.
This commit is contained in:
@ -18,6 +18,9 @@ class Animation(object):
|
|||||||
"name" : None,
|
"name" : None,
|
||||||
#Does this animation add or remove a mobject form the screen
|
#Does this animation add or remove a mobject form the screen
|
||||||
"remover" : False,
|
"remover" : False,
|
||||||
|
#Options are lagged_start, smoothed_lagged_start,
|
||||||
|
#one_at_a_time, all_at_once
|
||||||
|
"submobject_mode" : "lagged_start",
|
||||||
}
|
}
|
||||||
def __init__(self, mobject, **kwargs):
|
def __init__(self, mobject, **kwargs):
|
||||||
mobject = instantiate(mobject)
|
mobject = instantiate(mobject)
|
||||||
@ -31,8 +34,6 @@ class Animation(object):
|
|||||||
self.update(0)
|
self.update(0)
|
||||||
|
|
||||||
def update_config(self, **kwargs):
|
def update_config(self, **kwargs):
|
||||||
if "path_arc" in kwargs:
|
|
||||||
kwargs["path_arc"]
|
|
||||||
digest_config(self, kwargs)
|
digest_config(self, kwargs)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -49,6 +50,40 @@ class Animation(object):
|
|||||||
alpha = 1.0
|
alpha = 1.0
|
||||||
self.update_mobject(self.rate_func(alpha))
|
self.update_mobject(self.rate_func(alpha))
|
||||||
|
|
||||||
|
def update_mobject(self, alpha):
|
||||||
|
families = self.get_all_families_zipped()
|
||||||
|
for i, mobs in enumerate(families):
|
||||||
|
sub_alpha = self.get_sub_alpha(alpha, i, len(families))
|
||||||
|
self.update_submobject(*list(mobs) + [sub_alpha])
|
||||||
|
return self
|
||||||
|
|
||||||
|
def update_submobject(self, submobject, starting_sumobject, alpha):
|
||||||
|
#Typically ipmlemented by subclass
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_all_families_zipped(self):
|
||||||
|
"""
|
||||||
|
Ordering must match the ording of arguments to update_submobject
|
||||||
|
"""
|
||||||
|
return zip(
|
||||||
|
self.mobject.submobject_family(),
|
||||||
|
self.starting_mobject.submobject_family()
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_sub_alpha(self, alpha, index, num_submobjects):
|
||||||
|
if self.submobject_mode in ["lagged_start", "smoothed_lagged_start"]:
|
||||||
|
prop = float(index)/num_submobjects
|
||||||
|
if self.submobject_mode is "smoothed_lagged_start":
|
||||||
|
prop = smooth(prop)
|
||||||
|
return np.clip(2*alpha - prop, 0, 1)
|
||||||
|
elif self.submobject_mode == "one_at_a_time":
|
||||||
|
lower = float(index)/num_submobjects
|
||||||
|
upper = float(index+1)/num_submobjects
|
||||||
|
return np.clip((alpha-lower)/(upper-lower), 0, 1)
|
||||||
|
elif self.submobject_mode == "all_at_once":
|
||||||
|
return alpha
|
||||||
|
raise Exception("Invalid submobject mode")
|
||||||
|
|
||||||
def filter_out(self, *filter_functions):
|
def filter_out(self, *filter_functions):
|
||||||
self.filter_functions += filter_functions
|
self.filter_functions += filter_functions
|
||||||
return self
|
return self
|
||||||
@ -73,10 +108,6 @@ class Animation(object):
|
|||||||
self.name = name
|
self.name = name
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def update_mobject(self, alpha):
|
|
||||||
#Typically ipmlemented by subclass
|
|
||||||
pass
|
|
||||||
|
|
||||||
def is_remover(self):
|
def is_remover(self):
|
||||||
return self.remover
|
return self.remover
|
||||||
|
|
||||||
|
@ -18,14 +18,12 @@ class Rotating(Animation):
|
|||||||
"rate_func" : None,
|
"rate_func" : None,
|
||||||
"in_place" : True,
|
"in_place" : True,
|
||||||
}
|
}
|
||||||
|
def update_submobject(self, submobject, starting_mobject, alpha):
|
||||||
|
submobject.points = starting_submobject.points
|
||||||
|
|
||||||
def update_mobject(self, alpha):
|
def update_mobject(self, alpha):
|
||||||
|
Animation.update_mobject(self, alpha)
|
||||||
axes = [self.axis] if self.axis is not None else self.axes
|
axes = [self.axis] if self.axis is not None else self.axes
|
||||||
families = [
|
|
||||||
self.mobject.submobject_family(),
|
|
||||||
self.starting_mobject.submobject_family()
|
|
||||||
]
|
|
||||||
for mob, start in zip(*families):
|
|
||||||
mob.points = np.array(start.points)
|
|
||||||
if self.in_place:
|
if self.in_place:
|
||||||
method = self.mobject.rotate_in_place
|
method = self.mobject.rotate_in_place
|
||||||
else:
|
else:
|
||||||
@ -34,14 +32,9 @@ class Rotating(Animation):
|
|||||||
|
|
||||||
|
|
||||||
class ShowPartial(Animation):
|
class ShowPartial(Animation):
|
||||||
CONFIG = {
|
def update_submobject(self, submobject, starting_submobject, alpha):
|
||||||
"submobject_mode" : None
|
submobject.pointwise_become_partial(
|
||||||
}
|
starting_submobject, *self.get_bounds(alpha)
|
||||||
def update_mobject(self, alpha):
|
|
||||||
self.mobject.become_partial(
|
|
||||||
self.starting_mobject,
|
|
||||||
*self.get_bounds(alpha),
|
|
||||||
submobject_partial_creation_mode = self.submobject_mode
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_bounds(self, alpha):
|
def get_bounds(self, alpha):
|
||||||
@ -83,32 +76,6 @@ class ShowPassingFlash(ShowPartial):
|
|||||||
return (lower, upper)
|
return (lower, upper)
|
||||||
|
|
||||||
|
|
||||||
class Flash(Animation):
|
|
||||||
CONFIG = {
|
|
||||||
"color" : "white",
|
|
||||||
"slow_factor" : 0.01,
|
|
||||||
"run_time" : 0.1,
|
|
||||||
"rate_func" : None,
|
|
||||||
}
|
|
||||||
def __init__(self, mobject, **kwargs):
|
|
||||||
self.intermediate = Mobject(color = self.color)
|
|
||||||
self.intermediate.add_points([
|
|
||||||
point + (x, y, 0)
|
|
||||||
for point in self.mobject.points
|
|
||||||
for x in [-1, 1]
|
|
||||||
for y in [-1, 1]
|
|
||||||
])
|
|
||||||
Animation.__init__(self, mobject, **kwargs)
|
|
||||||
|
|
||||||
def update_mobject(self, alpha):
|
|
||||||
#Makes alpha go from 0 to slow_factor to 0 instead of 0 to 1
|
|
||||||
alpha = self.slow_factor * (1.0 - 4 * (alpha - 0.5)**2)
|
|
||||||
self.mobject.interpolate(
|
|
||||||
self.starting_mobject,
|
|
||||||
self.intermediate,
|
|
||||||
alpha
|
|
||||||
)
|
|
||||||
|
|
||||||
class MoveAlongPath(Animation):
|
class MoveAlongPath(Animation):
|
||||||
def __init__(self, mobject, vmobject, **kwargs):
|
def __init__(self, mobject, vmobject, **kwargs):
|
||||||
digest_config(self, kwargs, locals())
|
digest_config(self, kwargs, locals())
|
||||||
@ -131,16 +98,12 @@ class Homotopy(Animation):
|
|||||||
digest_config(self, kwargs)
|
digest_config(self, kwargs)
|
||||||
Animation.__init__(self, mobject, **kwargs)
|
Animation.__init__(self, mobject, **kwargs)
|
||||||
|
|
||||||
|
def update_submobject(self, submob, start, alpha):
|
||||||
|
submob.points = start.points
|
||||||
|
|
||||||
def update_mobject(self, alpha):
|
def update_mobject(self, alpha):
|
||||||
pairs = zip(
|
Animation.update_mobject(self, alpha)
|
||||||
self.mobject.submobject_family(),
|
submob.apply_function(self.function_at_time_t(alpha))
|
||||||
self.starting_mobject.submobject_family()
|
|
||||||
)
|
|
||||||
for mob, start_mob in pairs:
|
|
||||||
mob.become_partial(start_mob, 0, 1)
|
|
||||||
self.mobject.apply_function(
|
|
||||||
self.function_at_time_t(alpha)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PhaseFlow(Animation):
|
class PhaseFlow(Animation):
|
||||||
|
@ -39,14 +39,15 @@ class Transform(Animation):
|
|||||||
else:
|
else:
|
||||||
self.path_func = path_along_arc(self.path_arc)
|
self.path_func = path_along_arc(self.path_arc)
|
||||||
|
|
||||||
|
def get_all_families_zipped(self):
|
||||||
def update_mobject(self, alpha):
|
return zip(*map(
|
||||||
families = map(
|
|
||||||
Mobject.submobject_family,
|
Mobject.submobject_family,
|
||||||
[self.mobject, self.starting_mobject, self.ending_mobject]
|
[self.mobject, self.starting_mobject, self.ending_mobject]
|
||||||
)
|
))
|
||||||
for m, start, end in zip(*families):
|
|
||||||
m.interpolate(start, end, alpha, self.path_func)
|
def update_submobject(self, submob, start, end, alpha):
|
||||||
|
submob.interpolate(start, end, alpha, self.path_func)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
class ClockwiseTransform(Transform):
|
class ClockwiseTransform(Transform):
|
||||||
@ -81,6 +82,9 @@ class ShrinkToCenter(Transform):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class ApplyMethod(Transform):
|
class ApplyMethod(Transform):
|
||||||
|
CONFIG = {
|
||||||
|
"submobject_mode" : "all_at_once"
|
||||||
|
}
|
||||||
def __init__(self, method, *args, **kwargs):
|
def __init__(self, method, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Method is a method of Mobject. *args is for the method,
|
Method is a method of Mobject. *args is for the method,
|
||||||
@ -88,7 +92,11 @@ class ApplyMethod(Transform):
|
|||||||
|
|
||||||
Relies on the fact that mobject methods return the mobject
|
Relies on the fact that mobject methods return the mobject
|
||||||
"""
|
"""
|
||||||
assert(inspect.ismethod(method))
|
if not inspect.ismethod(method):
|
||||||
|
raise Exception(
|
||||||
|
"Whoops, looks like you accidentally invoked " + \
|
||||||
|
"the method you want to animate"
|
||||||
|
)
|
||||||
assert(isinstance(method.im_self, Mobject))
|
assert(isinstance(method.im_self, Mobject))
|
||||||
Transform.__init__(
|
Transform.__init__(
|
||||||
self,
|
self,
|
||||||
@ -119,10 +127,7 @@ class FadeIn(Transform):
|
|||||||
if isinstance(mobject, VMobject):
|
if isinstance(mobject, VMobject):
|
||||||
mobject.set_stroke(width = 0)
|
mobject.set_stroke(width = 0)
|
||||||
Transform.__init__(self, mobject, target, **kwargs)
|
Transform.__init__(self, mobject, target, **kwargs)
|
||||||
# self.mobject.rgbs = self.starting_mobject.rgbs * alpha
|
|
||||||
# if self.mobject.points.shape != self.starting_mobject.points.shape:
|
|
||||||
# self.mobject.points = self.starting_mobject.points
|
|
||||||
# #TODO, Why do you need to do this? Shouldn't points always align?
|
|
||||||
|
|
||||||
class ShimmerIn(DelayByOrder):
|
class ShimmerIn(DelayByOrder):
|
||||||
def __init__(self, mobject, **kwargs):
|
def __init__(self, mobject, **kwargs):
|
||||||
|
130
eola/chapter3.py
130
eola/chapter3.py
@ -288,16 +288,144 @@ class RotateIHat(LinearTransformationScene):
|
|||||||
self.setup()
|
self.setup()
|
||||||
i_hat, j_hat = self.get_basis_vectors()
|
i_hat, j_hat = self.get_basis_vectors()
|
||||||
i_label, j_label = self.get_basis_vector_labels()
|
i_label, j_label = self.get_basis_vector_labels()
|
||||||
self.play(ShowCreation(i_hat))
|
self.add_vector(i_hat)
|
||||||
self.play(Write(i_label, run_time = 1))
|
self.play(Write(i_label, run_time = 1))
|
||||||
self.dither()
|
self.dither()
|
||||||
self.play(FadeOut(i_label))
|
self.play(FadeOut(i_label))
|
||||||
self.apply_transposed_matrix([[0, 1], [-1, 0]])
|
self.apply_transposed_matrix([[0, 1], [-1, 0]])
|
||||||
|
self.dither()
|
||||||
self.play(Write(j_label, run_time = 1))
|
self.play(Write(j_label, run_time = 1))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TransformationsAreFunctions(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject([
|
||||||
|
"""Linear transformations are a
|
||||||
|
special kind of""",
|
||||||
|
"function"
|
||||||
|
])
|
||||||
|
title_start, function = title.split()
|
||||||
|
function.highlight(YELLOW)
|
||||||
|
title.to_edge(UP)
|
||||||
|
|
||||||
|
equation = TexMobject([
|
||||||
|
"L",
|
||||||
|
"(",
|
||||||
|
"\\vec{\\textbf{v}}",
|
||||||
|
") = ",
|
||||||
|
"\\vec{\\textbf{w}}",
|
||||||
|
])
|
||||||
|
L, lp, _input, equals, _output = equation.split()
|
||||||
|
L.highlight(YELLOW)
|
||||||
|
_input.highlight(MAROON_C)
|
||||||
|
_output.highlight(BLUE)
|
||||||
|
equation.scale(2)
|
||||||
|
equation.next_to(title, DOWN, buff = 1)
|
||||||
|
|
||||||
|
starting_vector = TextMobject("Starting vector")
|
||||||
|
starting_vector.shift(DOWN+3*LEFT)
|
||||||
|
starting_vector.highlight(MAROON_C)
|
||||||
|
ending_vector = TextMobject("The vector where it lands")
|
||||||
|
ending_vector.shift(DOWN).to_edge(RIGHT)
|
||||||
|
ending_vector.highlight(BLUE)
|
||||||
|
|
||||||
|
func_arrow = Arrow(function.get_bottom(), L.get_top(), color = YELLOW)
|
||||||
|
start_arrow = Arrow(starting_vector.get_top(), _input.get_bottom(), color = MAROON_C)
|
||||||
|
ending_arrow = Arrow(ending_vector, _output, color = BLUE)
|
||||||
|
|
||||||
|
|
||||||
|
self.add(title)
|
||||||
|
self.play(
|
||||||
|
Write(equation),
|
||||||
|
ShowCreation(func_arrow)
|
||||||
|
)
|
||||||
|
for v, a in [(starting_vector, start_arrow), (ending_vector, ending_arrow)]:
|
||||||
|
self.play(Write(v), ShowCreation(a), run_time = 1)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
class UsedToThinkinfOfFunctionsAsGraphs(VectorScene):
|
||||||
|
def construct(self):
|
||||||
|
self.show_graph()
|
||||||
|
self.show_inputs_and_output()
|
||||||
|
|
||||||
|
def show_graph(self):
|
||||||
|
axes = self.add_axes()
|
||||||
|
graph = FunctionGraph(lambda x : x**2, x_min = -2, x_max = 2)
|
||||||
|
name = TexMobject("f(x) = x^2")
|
||||||
|
name.next_to(graph, RIGHT).to_edge(UP)
|
||||||
|
point = Dot(graph.point_from_proportion(0.8))
|
||||||
|
point_label = TexMobject("(x, x^2)")
|
||||||
|
point_label.next_to(point, DOWN+RIGHT, buff = 0.1)
|
||||||
|
|
||||||
|
self.play(ShowCreation(graph))
|
||||||
|
self.play(Write(name, run_time = 1))
|
||||||
|
self.play(
|
||||||
|
ShowCreation(point),
|
||||||
|
Write(point_label),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def collapse_func(p):
|
||||||
|
return np.dot(p, [RIGHT, RIGHT, OUT]) + (SPACE_HEIGHT+1)*DOWN
|
||||||
|
self.play(
|
||||||
|
ApplyPointwiseFunction(
|
||||||
|
collapse_func, axes,
|
||||||
|
submobject_mode = "all_at_once",
|
||||||
|
),
|
||||||
|
ApplyPointwiseFunction(collapse_func, graph),
|
||||||
|
ApplyMethod(point.shift, 10*DOWN),
|
||||||
|
ApplyMethod(point_label.shift, 10*DOWN),
|
||||||
|
ApplyFunction(lambda m : m.center().to_edge(UP), name),
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.clear()
|
||||||
|
self.add(name)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def show_inputs_and_output(self):
|
||||||
|
numbers = range(-3, 4)
|
||||||
|
inputs = VMobject(*map(TexMobject, map(str, numbers)))
|
||||||
|
inputs.arrange_submobjects(DOWN, buff = 0.5, aligned_edge = RIGHT)
|
||||||
|
arrows = VMobject(*[
|
||||||
|
Arrow(LEFT, RIGHT).next_to(mob)
|
||||||
|
for mob in inputs.split()
|
||||||
|
])
|
||||||
|
outputs = VMobject(*[
|
||||||
|
TexMobject(str(num**2)).next_to(arrow)
|
||||||
|
for num, arrow in zip(numbers, arrows.split())
|
||||||
|
])
|
||||||
|
everyone = VMobject(inputs, arrows, outputs)
|
||||||
|
everyone.center().to_edge(UP, buff = 1.5)
|
||||||
|
|
||||||
|
self.play(Write(inputs, run_time = 1))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
Transform(inputs.copy(), outputs),
|
||||||
|
ShowCreation(arrows)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,11 +46,11 @@ class VectorScene(Scene):
|
|||||||
self.add(axes)
|
self.add(axes)
|
||||||
self.freeze_background()
|
self.freeze_background()
|
||||||
|
|
||||||
def add_vector(self, vector, animate = True, color = YELLOW):
|
def add_vector(self, vector, color = YELLOW, animate = True):
|
||||||
if not isinstance(vector, Arrow):
|
if not isinstance(vector, Arrow):
|
||||||
vector = Vector(vector, color = color)
|
vector = Vector(vector, color = color)
|
||||||
if animate:
|
if animate:
|
||||||
self.play(ShowCreation(vector, submobject_mode = "one_at_a_time"))
|
self.play(ShowCreation(vector))
|
||||||
self.add(vector)
|
self.add(vector)
|
||||||
return vector
|
return vector
|
||||||
|
|
||||||
@ -66,12 +66,11 @@ class VectorScene(Scene):
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_basis_vector_labels(self, animate = False, **kwargs):
|
def get_basis_vector_labels(self, **kwargs):
|
||||||
i_hat, j_hat = self.get_basis_vectors()
|
i_hat, j_hat = self.get_basis_vectors()
|
||||||
return [
|
return [
|
||||||
self.label_vector(
|
self.get_vector_label(
|
||||||
vect, label, color = color,
|
vect, label, color = color,
|
||||||
animate = animate,
|
|
||||||
label_scale_val = 1,
|
label_scale_val = 1,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
@ -81,9 +80,10 @@ class VectorScene(Scene):
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
def label_vector(self, vector, label, animate = True,
|
def get_vector_label(self, vector, label,
|
||||||
direction = "left", rotate = False,
|
direction = "left",
|
||||||
color = WHITE, add_to_vector = False,
|
rotate = False,
|
||||||
|
color = WHITE,
|
||||||
buff_factor = 2,
|
buff_factor = 2,
|
||||||
label_scale_val = VECTOR_LABEL_SCALE_VAL):
|
label_scale_val = VECTOR_LABEL_SCALE_VAL):
|
||||||
if len(label) == 1:
|
if len(label) == 1:
|
||||||
@ -103,9 +103,11 @@ class VectorScene(Scene):
|
|||||||
boundary_point = label.get_critical_point(boundary_dir)
|
boundary_point = label.get_critical_point(boundary_dir)
|
||||||
label.shift(buff_factor*boundary_point)
|
label.shift(buff_factor*boundary_point)
|
||||||
label.shift(vector_vect/2.)
|
label.shift(vector_vect/2.)
|
||||||
|
return label
|
||||||
|
|
||||||
if add_to_vector:
|
|
||||||
vector.add(label)
|
def label_vector(self, vector, label, animate = True, **kwargs):
|
||||||
|
label = self.get_vector_label(vector, label, **kwargs)
|
||||||
if animate:
|
if animate:
|
||||||
self.play(Write(label, run_time = 1))
|
self.play(Write(label, run_time = 1))
|
||||||
self.add(label)
|
self.add(label)
|
||||||
@ -268,8 +270,8 @@ class LinearTransformationScene(VectorScene):
|
|||||||
self.plane = NumberPlane(**self.foreground_plane_kwargs)
|
self.plane = NumberPlane(**self.foreground_plane_kwargs)
|
||||||
self.add_transformable_mobject(self.plane)
|
self.add_transformable_mobject(self.plane)
|
||||||
if self.show_basis_vectors:
|
if self.show_basis_vectors:
|
||||||
self.add_vector((1, 0), self.i_hat_color)
|
self.add_vector((1, 0), self.i_hat_color, animate = False)
|
||||||
self.add_vector((0, 1), self.j_hat_color)
|
self.add_vector((0, 1), self.j_hat_color, animate = False)
|
||||||
|
|
||||||
def add_background_mobject(self, *mobjects):
|
def add_background_mobject(self, *mobjects):
|
||||||
for mobject in mobjects:
|
for mobject in mobjects:
|
||||||
@ -283,9 +285,9 @@ class LinearTransformationScene(VectorScene):
|
|||||||
self.transformable_mobject.append(mobject)
|
self.transformable_mobject.append(mobject)
|
||||||
self.add(mobject)
|
self.add(mobject)
|
||||||
|
|
||||||
def add_vector(self, vector, color = YELLOW, animate = False):
|
def add_vector(self, vector, color = YELLOW, **kwargs):
|
||||||
vector = VectorScene.add_vector(
|
vector = VectorScene.add_vector(
|
||||||
self, vector, color = color, animate = animate
|
self, vector, color = color, **kwargs
|
||||||
)
|
)
|
||||||
self.moving_vectors.append(vector)
|
self.moving_vectors.append(vector)
|
||||||
return vector
|
return vector
|
||||||
|
@ -22,10 +22,6 @@ class Mobject(object):
|
|||||||
"name" : None,
|
"name" : None,
|
||||||
"dim" : 3,
|
"dim" : 3,
|
||||||
"target" : None,
|
"target" : None,
|
||||||
#Options are lagged_start, smoothed_lagged_start,
|
|
||||||
#one_at_a_time, all_at_once
|
|
||||||
"submobject_partial_creation_mode" : "lagged_start",
|
|
||||||
#TODO, probably make this Animations's responsibility?
|
|
||||||
}
|
}
|
||||||
def __init__(self, *submobjects, **kwargs):
|
def __init__(self, *submobjects, **kwargs):
|
||||||
digest_config(self, kwargs)
|
digest_config(self, kwargs)
|
||||||
@ -548,7 +544,7 @@ class Mobject(object):
|
|||||||
def interpolate_color(self, mobject1, mobject2, alpha):
|
def interpolate_color(self, mobject1, mobject2, alpha):
|
||||||
raise Exception("Not implemented")
|
raise Exception("Not implemented")
|
||||||
|
|
||||||
def become_partial(self, mobject, a, b, submobject_partial_creation_mode = None):
|
def become_partial(self, mobject, a, b):
|
||||||
"""
|
"""
|
||||||
Set points in such a way as to become only
|
Set points in such a way as to become only
|
||||||
part of mobject.
|
part of mobject.
|
||||||
@ -557,29 +553,6 @@ class Mobject(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
#TODO, color?
|
#TODO, color?
|
||||||
spcm = submobject_partial_creation_mode or self.submobject_partial_creation_mode
|
|
||||||
pairs = zip(
|
|
||||||
self.family_members_with_points(),
|
|
||||||
mobject.family_members_with_points()
|
|
||||||
)
|
|
||||||
for i, (self_sub, mob_sub) in enumerate(pairs):
|
|
||||||
if spcm in ["lagged_start", "smoothed_lagged_start"]:
|
|
||||||
prop = float(i)/len(pairs)
|
|
||||||
if spcm is "smoothed_lagged_start":
|
|
||||||
prop = smooth(prop)
|
|
||||||
sub_a = np.clip(2*a - prop, 0, 1)
|
|
||||||
sub_b = np.clip(2*b - prop, 0, 1)
|
|
||||||
elif spcm == "one_at_a_time":
|
|
||||||
lower = float(i)/len(pairs)
|
|
||||||
upper = float(i+1)/len(pairs)
|
|
||||||
sub_a = np.clip((a-lower)/(upper-lower), 0, 1)
|
|
||||||
sub_b = np.clip((b-lower)/(upper-lower), 0, 1)
|
|
||||||
elif spcm == "all_at_once":
|
|
||||||
sub_a, sub_b = a, b
|
|
||||||
else:
|
|
||||||
raise Exception("Invalid submobject partial creation mode")
|
|
||||||
self_sub.pointwise_become_partial(mob_sub, sub_a, sub_b)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def pointwise_become_partial(self, mobject, a, b):
|
def pointwise_become_partial(self, mobject, a, b):
|
||||||
raise Exception("Not implemented")
|
raise Exception("Not implemented")
|
||||||
|
@ -41,24 +41,26 @@ class VMobject(Mobject):
|
|||||||
fill_color = None,
|
fill_color = None,
|
||||||
fill_opacity = None,
|
fill_opacity = None,
|
||||||
family = True):
|
family = True):
|
||||||
|
mobs = self.submobject_family() if family else [self]
|
||||||
|
for mob in mobs:
|
||||||
if stroke_color is not None:
|
if stroke_color is not None:
|
||||||
setattr(self, "stroke_rgb", color_to_rgb(stroke_color))
|
mob.stroke_rgb = color_to_rgb(stroke_color)
|
||||||
if stroke_width is not None:
|
if stroke_width is not None:
|
||||||
setattr(self, "stroke_width", stroke_width)
|
mob.stroke_width = stroke_width
|
||||||
if fill_color is not None:
|
if fill_color is not None:
|
||||||
setattr(self, "fill_rgb", color_to_rgb(fill_color))
|
mob.fill_rgb = color_to_rgb(fill_color)
|
||||||
if fill_opacity is not None:
|
if fill_opacity is not None:
|
||||||
setattr(self, "fill_opacity", fill_opacity)
|
mob.fill_opacity = fill_opacity
|
||||||
if family:
|
probably_meant_to_change_opacity = reduce(op.and_, [
|
||||||
kwargs = locals()
|
fill_color is not None,
|
||||||
kwargs.pop("self")
|
fill_opacity is None,
|
||||||
for mob in self.submobjects:
|
mob.fill_opacity == 0
|
||||||
mob.set_style_data(**kwargs)
|
])
|
||||||
|
if probably_meant_to_change_opacity:
|
||||||
|
mob.fill_opacity = 1
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_fill(self, color = None, opacity = None, family = True):
|
def set_fill(self, color = None, opacity = None, family = True):
|
||||||
if self.fill_opacity == 0 and opacity is None:
|
|
||||||
opacity = 1
|
|
||||||
return self.set_style_data(
|
return self.set_style_data(
|
||||||
fill_color = color,
|
fill_color = color,
|
||||||
fill_opacity = opacity,
|
fill_opacity = opacity,
|
||||||
@ -73,11 +75,7 @@ class VMobject(Mobject):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def highlight(self, color, family = True):
|
def highlight(self, color, family = True):
|
||||||
self.set_fill(
|
self.set_fill(color = color, family = family)
|
||||||
color = color,
|
|
||||||
opacity = self.get_fill_opacity(),
|
|
||||||
family = family
|
|
||||||
)
|
|
||||||
self.set_stroke(color = color, family = family)
|
self.set_stroke(color = color, family = family)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -133,7 +133,6 @@ class Arrow(Line):
|
|||||||
"buff" : 0.3,
|
"buff" : 0.3,
|
||||||
"propogate_style_to_family" : False,
|
"propogate_style_to_family" : False,
|
||||||
"preserve_tip_size_when_scaling" : True,
|
"preserve_tip_size_when_scaling" : True,
|
||||||
"submobject_partial_creation_mode" : "one_at_a_time",
|
|
||||||
}
|
}
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if len(args) == 1:
|
if len(args) == 1:
|
||||||
|
Reference in New Issue
Block a user