mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Some cleanups to the way scenes end
This commit is contained in:
parent
a87d3b5f59
commit
22c5e79f5f
1 changed files with 32 additions and 27 deletions
|
@ -64,7 +64,6 @@ class Scene(object):
|
||||||
"preview": True,
|
"preview": True,
|
||||||
"presenter_mode": False,
|
"presenter_mode": False,
|
||||||
"show_animation_progress": False,
|
"show_animation_progress": False,
|
||||||
"linger_after_completion": True,
|
|
||||||
"pan_sensitivity": 3,
|
"pan_sensitivity": 3,
|
||||||
"max_num_saved_states": 50,
|
"max_num_saved_states": 50,
|
||||||
}
|
}
|
||||||
|
@ -117,12 +116,14 @@ class Scene(object):
|
||||||
self.file_writer.begin()
|
self.file_writer.begin()
|
||||||
|
|
||||||
self.setup()
|
self.setup()
|
||||||
if self.presenter_mode:
|
|
||||||
self.wait()
|
|
||||||
try:
|
try:
|
||||||
self.construct()
|
self.construct()
|
||||||
except (EndSceneEarlyException, KeyboardInterrupt):
|
self.interact()
|
||||||
self.linger_after_completion = False
|
except EndScene:
|
||||||
|
pass
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
# Get rid keyboard interupt symbols
|
||||||
|
print("", end="\r")
|
||||||
self.tear_down()
|
self.tear_down()
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
|
@ -142,35 +143,33 @@ class Scene(object):
|
||||||
self.stop_skipping()
|
self.stop_skipping()
|
||||||
self.file_writer.finish()
|
self.file_writer.finish()
|
||||||
if self.window:
|
if self.window:
|
||||||
if self.linger_after_completion:
|
self.window.destroy()
|
||||||
self.interact()
|
self.window = None
|
||||||
else:
|
if self.inside_embed:
|
||||||
self.window.destroy()
|
self.embed_shell.enable_gui(None)
|
||||||
self.window = None
|
self.embed_shell.exiter()
|
||||||
|
|
||||||
def interact(self) -> None:
|
def interact(self) -> None:
|
||||||
# If there is a window, enter a loop
|
# If there is a window, enter a loop
|
||||||
# which updates the frame while under
|
# which updates the frame while under
|
||||||
# the hood calling the pyglet event loop
|
# the hood calling the pyglet event loop
|
||||||
|
if self.window is None:
|
||||||
|
return
|
||||||
log.info(
|
log.info(
|
||||||
"Tips: You are now in the interactive mode. Now you can use the keyboard"
|
"Tips: You are now in the interactive mode. Now you can use the keyboard"
|
||||||
" and the mouse to interact with the scene. Just press `command + q` or `esc`"
|
" and the mouse to interact with the scene. Just press `command + q` or `esc`"
|
||||||
" if you want to quit."
|
" if you want to quit."
|
||||||
)
|
)
|
||||||
|
self.skip_animations = False
|
||||||
self.refresh_static_mobjects()
|
self.refresh_static_mobjects()
|
||||||
try:
|
while not self.is_window_closing():
|
||||||
while True:
|
self.update_frame(1 / self.camera.frame_rate)
|
||||||
self.update_frame(1 / self.camera.frame_rate)
|
|
||||||
except (EndSceneEarlyException, KeyboardInterrupt):
|
|
||||||
return
|
|
||||||
|
|
||||||
def embed(self, close_scene_on_exit: bool = True) -> None:
|
def embed(self, close_scene_on_exit: bool = True) -> None:
|
||||||
if not self.preview:
|
if not self.preview:
|
||||||
# Ignore embed calls when there is no preview
|
return # Embed is only relevant with a preview
|
||||||
return
|
|
||||||
self.inside_embed = True
|
self.inside_embed = True
|
||||||
self.stop_skipping()
|
self.stop_skipping()
|
||||||
self.linger_after_completion = False
|
|
||||||
self.update_frame()
|
self.update_frame()
|
||||||
self.save_state()
|
self.save_state()
|
||||||
|
|
||||||
|
@ -214,8 +213,10 @@ class Scene(object):
|
||||||
# Enables gui interactions during the embed
|
# Enables gui interactions during the embed
|
||||||
def inputhook(context):
|
def inputhook(context):
|
||||||
while not context.input_is_ready():
|
while not context.input_is_ready():
|
||||||
if not self.window.is_closing:
|
if not self.is_window_closing():
|
||||||
self.update_frame(dt=0)
|
self.update_frame(dt=0)
|
||||||
|
if self.is_window_closing():
|
||||||
|
shell.ask_exit()
|
||||||
|
|
||||||
pt_inputhooks.register("manim", inputhook)
|
pt_inputhooks.register("manim", inputhook)
|
||||||
shell.enable_gui("manim")
|
shell.enable_gui("manim")
|
||||||
|
@ -226,7 +227,10 @@ class Scene(object):
|
||||||
# That comes up a fair bit during scene construction, to get around this,
|
# That comes up a fair bit during scene construction, to get around this,
|
||||||
# we (admittedly sketchily) update the global namespace to match the local
|
# we (admittedly sketchily) update the global namespace to match the local
|
||||||
# namespace, since this is just a shell session anyway.
|
# namespace, since this is just a shell session anyway.
|
||||||
shell.events.register("pre_run_cell", lambda: shell.user_global_ns.update(shell.user_ns))
|
shell.events.register(
|
||||||
|
"pre_run_cell",
|
||||||
|
lambda: shell.user_global_ns.update(shell.user_ns)
|
||||||
|
)
|
||||||
|
|
||||||
# Operation to run after each ipython command
|
# Operation to run after each ipython command
|
||||||
def post_cell_func():
|
def post_cell_func():
|
||||||
|
@ -236,13 +240,11 @@ class Scene(object):
|
||||||
|
|
||||||
shell.events.register("post_run_cell", post_cell_func)
|
shell.events.register("post_run_cell", post_cell_func)
|
||||||
|
|
||||||
# Launch shell, with stack_depth=2 indicating we should use caller globals/locals
|
|
||||||
shell(local_ns=local_ns, stack_depth=2)
|
shell(local_ns=local_ns, stack_depth=2)
|
||||||
|
|
||||||
self.inside_embed = False
|
|
||||||
# End scene when exiting an embed
|
# End scene when exiting an embed
|
||||||
if close_scene_on_exit:
|
if close_scene_on_exit:
|
||||||
raise EndSceneEarlyException()
|
raise EndScene()
|
||||||
|
|
||||||
# Only these methods should touch the camera
|
# Only these methods should touch the camera
|
||||||
|
|
||||||
|
@ -259,8 +261,8 @@ class Scene(object):
|
||||||
if self.skip_animations and not ignore_skipping:
|
if self.skip_animations and not ignore_skipping:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.window is not None and (self.window.is_closing or self.quit_interaction):
|
if self.is_window_closing():
|
||||||
raise EndSceneEarlyException()
|
raise EndScene()
|
||||||
|
|
||||||
if self.window:
|
if self.window:
|
||||||
self.window.clear()
|
self.window.clear()
|
||||||
|
@ -444,7 +446,7 @@ class Scene(object):
|
||||||
self.stop_skipping()
|
self.stop_skipping()
|
||||||
if self.end_at_animation_number is not None:
|
if self.end_at_animation_number is not None:
|
||||||
if self.num_plays >= self.end_at_animation_number:
|
if self.num_plays >= self.end_at_animation_number:
|
||||||
raise EndSceneEarlyException()
|
raise EndScene()
|
||||||
|
|
||||||
def stop_skipping(self) -> None:
|
def stop_skipping(self) -> None:
|
||||||
self.virtual_animation_start_time = self.time
|
self.virtual_animation_start_time = self.time
|
||||||
|
@ -707,6 +709,9 @@ class Scene(object):
|
||||||
path = os.path.join(directory, file_name)
|
path = os.path.join(directory, file_name)
|
||||||
return Mobject.load(path)
|
return Mobject.load(path)
|
||||||
|
|
||||||
|
def is_window_closing(self):
|
||||||
|
return self.window and (self.window.is_closing or self.quit_interaction)
|
||||||
|
|
||||||
# Event handling
|
# Event handling
|
||||||
|
|
||||||
def on_mouse_motion(
|
def on_mouse_motion(
|
||||||
|
@ -887,5 +892,5 @@ class SceneState():
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class EndSceneEarlyException(Exception):
|
class EndScene(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Add table
Reference in a new issue