mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Fixed Animation to work for updating mobjects
This commit is contained in:
parent
bf738b70d7
commit
ec638de1ec
4 changed files with 72 additions and 56 deletions
|
@ -29,17 +29,20 @@ class Animation(object):
|
||||||
self.mobject = mobject
|
self.mobject = mobject
|
||||||
|
|
||||||
def begin(self):
|
def begin(self):
|
||||||
# mobject = self.mobject
|
mobject = self.mobject
|
||||||
# # Make sure it's all up to date
|
|
||||||
# mobject.update()
|
|
||||||
# mobject.suspend_updating()
|
|
||||||
# Keep track of where it started
|
# Keep track of where it started
|
||||||
self.starting_mobject = self.mobject.copy()
|
self.starting_mobject = mobject.copy()
|
||||||
self.update(0)
|
# All calls to mobject's internal updaters
|
||||||
|
# during the animation, either from this Animation
|
||||||
|
# or from the surrounding scene, should do nothing.
|
||||||
|
# It is, however, okay and desirable to call
|
||||||
|
# self.starting_mobject's internal updaters
|
||||||
|
mobject.suspend_updating()
|
||||||
|
self.interpolate(0)
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
|
self.interpolate(1)
|
||||||
self.mobject.resume_updating()
|
self.mobject.resume_updating()
|
||||||
self.update(1)
|
|
||||||
|
|
||||||
def clean_up_from_scene(self, scene):
|
def clean_up_from_scene(self, scene):
|
||||||
if self.is_remover():
|
if self.is_remover():
|
||||||
|
@ -58,13 +61,27 @@ class Animation(object):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def update_mobjects(self, dt):
|
def update_mobjects(self, dt):
|
||||||
|
"""
|
||||||
|
Updates things like starting_mobject, and (for
|
||||||
|
Transforms) target_mobject. Note, since typically
|
||||||
|
(always?) self.mobject will have its updating
|
||||||
|
suspended during the animation, this will do
|
||||||
|
nothing to self.mobject.
|
||||||
|
"""
|
||||||
for mob in self.get_all_mobjects():
|
for mob in self.get_all_mobjects():
|
||||||
mob.update(dt)
|
mob.update(dt)
|
||||||
|
|
||||||
def update(self, alpha):
|
def interpolate(self, alpha):
|
||||||
alpha = np.clip(alpha, 0, 1)
|
alpha = np.clip(alpha, 0, 1)
|
||||||
self.interpolate_mobject(self.rate_func(alpha))
|
self.interpolate_mobject(self.rate_func(alpha))
|
||||||
|
|
||||||
|
def update(self, alpha):
|
||||||
|
"""
|
||||||
|
This method shouldn't exist, but it's here to
|
||||||
|
keep many old scenes from breaking
|
||||||
|
"""
|
||||||
|
self.interpolate(alpha)
|
||||||
|
|
||||||
def interpolate_mobject(self, alpha):
|
def interpolate_mobject(self, alpha):
|
||||||
families = self.get_all_families_zipped()
|
families = self.get_all_families_zipped()
|
||||||
for i, mobs in enumerate(families):
|
for i, mobs in enumerate(families):
|
||||||
|
@ -102,12 +119,8 @@ class Animation(object):
|
||||||
self.get_all_mobjects()
|
self.get_all_mobjects()
|
||||||
)))
|
)))
|
||||||
|
|
||||||
def filter_out(self, *filter_functions):
|
def set_run_time(self, run_time):
|
||||||
self.filter_functions += filter_functions
|
self.run_time = run_time
|
||||||
return self
|
|
||||||
|
|
||||||
def set_run_time(self, time):
|
|
||||||
self.run_time = time
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_run_time(self):
|
def get_run_time(self):
|
||||||
|
|
|
@ -139,7 +139,7 @@ class FadeOut(Transform):
|
||||||
|
|
||||||
def clean_up_from_scene(self, scene=None):
|
def clean_up_from_scene(self, scene=None):
|
||||||
Transform.clean_up_from_scene(self, scene)
|
Transform.clean_up_from_scene(self, scene)
|
||||||
self.update(0)
|
self.interpolate(0)
|
||||||
|
|
||||||
|
|
||||||
class FadeIn(Transform):
|
class FadeIn(Transform):
|
||||||
|
|
|
@ -29,43 +29,12 @@ class Transform(Animation):
|
||||||
self.target_mobject = target_mobject
|
self.target_mobject = target_mobject
|
||||||
self.init_path_func()
|
self.init_path_func()
|
||||||
|
|
||||||
def begin(self):
|
|
||||||
mobject = self.mobject
|
|
||||||
target = self.target_mobject
|
|
||||||
# Note, this potentially changes the structure
|
|
||||||
# of both mobject and target_mobject
|
|
||||||
mobject.align_data(target)
|
|
||||||
super().begin()
|
|
||||||
# Copy target_mobject so as to not mess with caller
|
|
||||||
# self.original_target_mobject = self.target_mobject
|
|
||||||
self.target_mobject.update()
|
|
||||||
self.target_mobject.suspend_updating()
|
|
||||||
self.target_copy = self.target_mobject.copy()
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
super().finish()
|
|
||||||
self.target_mobject.resume_updating()
|
|
||||||
|
|
||||||
def clean_up_from_scene(self, scene):
|
|
||||||
super().clean_up_from_scene(scene)
|
|
||||||
if self.replace_mobject_with_target_in_scene:
|
|
||||||
scene.remove(self.mobject)
|
|
||||||
scene.add(self.target_mobject)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{}To{}".format(
|
return "{}To{}".format(
|
||||||
super().__str__(self),
|
super().__str__(),
|
||||||
str(self.target_mobject)
|
str(self.target_mobject)
|
||||||
)
|
)
|
||||||
|
|
||||||
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_path_func(self):
|
def init_path_func(self):
|
||||||
if self.path_func is not None:
|
if self.path_func is not None:
|
||||||
return
|
return
|
||||||
|
@ -77,11 +46,43 @@ class Transform(Animation):
|
||||||
self.path_arc_axis,
|
self.path_arc_axis,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_all_mobjects(self):
|
def begin(self):
|
||||||
return self.mobject, self.starting_mobject, self.target_mobject
|
# Use a copy of target_mobject for the align_data
|
||||||
|
# call so that the actual target_mobject stays
|
||||||
|
# preserved.
|
||||||
|
self.target_copy = self.target_mobject.copy()
|
||||||
|
# Note, this potentially changes the structure
|
||||||
|
# of both mobject and target_mobject
|
||||||
|
self.mobject.align_data(self.target_copy)
|
||||||
|
super().begin()
|
||||||
|
|
||||||
def interpolate_submobject(self, submob, start, end, alpha):
|
def clean_up_from_scene(self, scene):
|
||||||
submob.interpolate(start, end, alpha, self.path_func)
|
super().clean_up_from_scene(scene)
|
||||||
|
if self.replace_mobject_with_target_in_scene:
|
||||||
|
scene.remove(self.mobject)
|
||||||
|
scene.add(self.target_mobject)
|
||||||
|
|
||||||
|
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 get_all_mobjects(self):
|
||||||
|
return [
|
||||||
|
self.mobject,
|
||||||
|
self.starting_mobject,
|
||||||
|
self.target_mobject,
|
||||||
|
self.target_copy,
|
||||||
|
]
|
||||||
|
|
||||||
|
def interpolate_submobject(self, submob, start, target, target_copy, alpha):
|
||||||
|
submob.interpolate(
|
||||||
|
start, target_copy,
|
||||||
|
alpha, self.path_func
|
||||||
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,7 +279,7 @@ class TransformAnimations(Transform):
|
||||||
start_anim.mobject = self.starting_mobject
|
start_anim.mobject = self.starting_mobject
|
||||||
end_anim.mobject = self.target_mobject
|
end_anim.mobject = self.target_mobject
|
||||||
|
|
||||||
def update(self, alpha):
|
def interpolate(self, alpha):
|
||||||
self.start_anim.update(alpha)
|
self.start_anim.interpolate(alpha)
|
||||||
self.end_anim.update(alpha)
|
self.end_anim.interpolate(alpha)
|
||||||
Transform.update(self, alpha)
|
Transform.interpolate(self, alpha)
|
||||||
|
|
|
@ -483,7 +483,9 @@ class Scene(Container):
|
||||||
for t in self.get_animation_time_progression(animations):
|
for t in self.get_animation_time_progression(animations):
|
||||||
dt = 1 / self.camera.frame_rate
|
dt = 1 / self.camera.frame_rate
|
||||||
for animation in animations:
|
for animation in animations:
|
||||||
animation.update(t / animation.run_time)
|
animation.update_mobjects(dt)
|
||||||
|
animation.interpolate(t / animation.run_time)
|
||||||
|
|
||||||
self.continual_update(dt)
|
self.continual_update(dt)
|
||||||
self.update_frame(moving_mobjects, static_image)
|
self.update_frame(moving_mobjects, static_image)
|
||||||
self.add_frames(self.get_frame())
|
self.add_frames(self.get_frame())
|
||||||
|
|
Loading…
Add table
Reference in a new issue