mirror of
https://github.com/3b1b/manim.git
synced 2025-07-31 22:13:30 +08:00
Better Scene mobject management
This commit is contained in:
@ -16,6 +16,8 @@ class Animation(object):
|
|||||||
"run_time" : DEFAULT_ANIMATION_RUN_TIME,
|
"run_time" : DEFAULT_ANIMATION_RUN_TIME,
|
||||||
"rate_func" : smooth,
|
"rate_func" : smooth,
|
||||||
"name" : None,
|
"name" : None,
|
||||||
|
#Does this animation add or remove a mobject form the screen
|
||||||
|
"remover" : False,
|
||||||
}
|
}
|
||||||
def __init__(self, mobject, **kwargs):
|
def __init__(self, mobject, **kwargs):
|
||||||
mobject = instantiate(mobject)
|
mobject = instantiate(mobject)
|
||||||
@ -63,6 +65,9 @@ class Animation(object):
|
|||||||
#Typically ipmlemented by subclass
|
#Typically ipmlemented by subclass
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def is_remover(self):
|
||||||
|
return self.remover
|
||||||
|
|
||||||
def clean_up(self):
|
def clean_up(self):
|
||||||
self.update(1)
|
self.update(1)
|
||||||
|
|
||||||
|
@ -79,12 +79,12 @@ class Scene(object):
|
|||||||
Mobjects will be displayed, from background to foreground,
|
Mobjects will be displayed, from background to foreground,
|
||||||
in the order with which they are entered.
|
in the order with which they are entered.
|
||||||
|
|
||||||
Scene class only keeps track of pointful monjects, all
|
Scene class only keeps track of top-level monjects, all
|
||||||
grouping structure is forgotten as far as Scene is concerned
|
concerns with submobjects is left to animations and subclass
|
||||||
|
implementations of the construct method.
|
||||||
"""
|
"""
|
||||||
if not all_elements_are_instances(mobjects, Mobject):
|
if not all_elements_are_instances(mobjects, Mobject):
|
||||||
raise Exception("Adding something which is not a mobject")
|
raise Exception("Adding something which is not a mobject")
|
||||||
mobjects = self.extract_mobjects_with_points(*mobjects)
|
|
||||||
old_mobjects = filter(lambda m : m not in mobjects, self.mobjects)
|
old_mobjects = filter(lambda m : m not in mobjects, self.mobjects)
|
||||||
self.mobjects = old_mobjects + list(mobjects)
|
self.mobjects = old_mobjects + list(mobjects)
|
||||||
return self
|
return self
|
||||||
@ -95,14 +95,12 @@ class Scene(object):
|
|||||||
by calling add_mobjects_among(locals().values())
|
by calling add_mobjects_among(locals().values())
|
||||||
"""
|
"""
|
||||||
mobjects = filter(lambda x : isinstance(x, Mobject), values)
|
mobjects = filter(lambda x : isinstance(x, Mobject), values)
|
||||||
mobjects = self.extract_mobjects_with_points(*mobjects)
|
|
||||||
self.add(*mobjects)
|
self.add(*mobjects)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def remove(self, *mobjects):
|
def remove(self, *mobjects):
|
||||||
if not all_elements_are_instances(mobjects, Mobject):
|
if not all_elements_are_instances(mobjects, Mobject):
|
||||||
raise Exception("Removing something which is not a mobject")
|
raise Exception("Removing something which is not a mobject")
|
||||||
mobjects = self.extract_mobjects_with_points(*mobjects)
|
|
||||||
# mobjects = filter(lambda m : m in self.mobjects, mobjects)
|
# mobjects = filter(lambda m : m in self.mobjects, mobjects)
|
||||||
if len(mobjects) == 0:
|
if len(mobjects) == 0:
|
||||||
return
|
return
|
||||||
@ -138,12 +136,18 @@ class Scene(object):
|
|||||||
return animations
|
return animations
|
||||||
|
|
||||||
def separate_moving_and_static_mobjects(self, *animations):
|
def separate_moving_and_static_mobjects(self, *animations):
|
||||||
|
"""
|
||||||
|
During an animation, the only mobjects directly influencing
|
||||||
|
display are those with points. This allows for the case
|
||||||
|
where you might have intersections between the families of
|
||||||
|
animated mobjects and static mobjects
|
||||||
|
"""
|
||||||
moving_mobjects = self.extract_mobjects_with_points(
|
moving_mobjects = self.extract_mobjects_with_points(
|
||||||
*[anim.mobject for anim in animations]
|
*[anim.mobject for anim in animations]
|
||||||
)
|
)
|
||||||
static_mobjects = filter(
|
static_mobjects = filter(
|
||||||
lambda m : m not in moving_mobjects,
|
lambda m : m not in moving_mobjects,
|
||||||
self.mobjects
|
self.extract_mobjects_with_points(*self.mobjects)
|
||||||
)
|
)
|
||||||
return moving_mobjects, static_mobjects
|
return moving_mobjects, static_mobjects
|
||||||
|
|
||||||
@ -164,14 +168,12 @@ class Scene(object):
|
|||||||
raise Warning("Called Scene.play with no animations")
|
raise Warning("Called Scene.play with no animations")
|
||||||
return
|
return
|
||||||
self.num_animations += 1
|
self.num_animations += 1
|
||||||
self.add(*[anim.mobject for anim in animations])
|
self.mobjects_from_last_animation = []
|
||||||
|
|
||||||
animations = self.align_run_times(*animations, **kwargs)
|
animations = self.align_run_times(*animations, **kwargs)
|
||||||
moving_mobjects, static_mobjects = \
|
moving_mobjects, static_mobjects = \
|
||||||
self.separate_moving_and_static_mobjects(*animations)
|
self.separate_moving_and_static_mobjects(*animations)
|
||||||
self.update_frame(
|
self.update_frame(static_mobjects)
|
||||||
static_mobjects,
|
|
||||||
include_submobjects = False
|
|
||||||
)
|
|
||||||
static_image = self.get_frame()
|
static_image = self.get_frame()
|
||||||
|
|
||||||
for t in self.get_time_progression(animations):
|
for t in self.get_time_progression(animations):
|
||||||
@ -179,10 +181,25 @@ class Scene(object):
|
|||||||
animation.update(t / animation.run_time)
|
animation.update(t / animation.run_time)
|
||||||
self.update_frame(moving_mobjects, static_image)
|
self.update_frame(moving_mobjects, static_image)
|
||||||
self.frames.append(self.get_frame())
|
self.frames.append(self.get_frame())
|
||||||
|
|
||||||
|
self.clean_up_animations(*animations)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def clean_up_animations(self, *animations):
|
||||||
for animation in animations:
|
for animation in animations:
|
||||||
animation.clean_up()
|
animation.clean_up()
|
||||||
|
if animation.is_remover():
|
||||||
|
self.remove(animation.mobject)
|
||||||
|
else:
|
||||||
|
self.add(animation.mobject)
|
||||||
|
self.mobjects_from_last_animation.append(animation.mobject)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def get_mobjects_from_last_animation(self):
|
||||||
|
if hasattr(self, "mobjects_from_last_animation"):
|
||||||
|
return self.mobjects_from_last_animation
|
||||||
|
return []
|
||||||
|
|
||||||
def play_over_time_range(self, t0, t1, *animations):
|
def play_over_time_range(self, t0, t1, *animations):
|
||||||
needed_scene_time = max(abs(t0), abs(t1))
|
needed_scene_time = max(abs(t0), abs(t1))
|
||||||
existing_scene_time = len(self.frames)*self.frame_duration
|
existing_scene_time = len(self.frames)*self.frame_duration
|
||||||
|
Reference in New Issue
Block a user