def wait(self, duration: float = DEFAULT_WAIT_TIME, stop_condition: Callable[[], bool] = None, note: str = None, ignore_presenter_mode: bool = False): if note: log.info(note) self.update_mobjects(dt=0) # Any problems with this? self.lock_static_mobject_data() if self.presenter_mode and not self.skip_animations and not ignore_presenter_mode: while self.hold_on_wait: self.update_frame(dt=1 / self.camera.frame_rate) self.hold_on_wait = True else: time_progression = self.get_wait_time_progression( duration, stop_condition) last_t = 0 for t in time_progression: dt = t - last_t last_t = t self.update_frame(dt) self.emit_frame() if stop_condition is not None and stop_condition(): time_progression.close() break self.unlock_mobject_data() return self
def embed(self, close_scene_on_exit: bool = True) -> None: if not self.preview: # If the scene is just being # written, ignore embed calls return self.stop_skipping() self.linger_after_completion = False self.update_frame() # Save scene state at the point of embedding self.save_state() from IPython.terminal.embed import InteractiveShellEmbed shell = InteractiveShellEmbed() # Have the frame update after each command shell.events.register('post_run_cell', lambda *a, **kw: self.update_frame()) # Use the locals of the caller as the local namespace # once embedded, and add a few custom shortcuts local_ns = inspect.currentframe().f_back.f_locals local_ns["touch"] = self.interact for term in ("play", "wait", "add", "remove", "clear", "save_state", "restore"): local_ns[term] = getattr(self, term) log.info( "Tips: Now the embed iPython terminal is open. But you can't interact with" " the window directly. To do so, you need to type `touch()` or `self.interact()`" ) shell(local_ns=local_ns, stack_depth=2) # End scene when exiting an embed if close_scene_on_exit: raise EndSceneEarlyException()
def interact(self) -> None: # If there is a window, enter a loop # which updates the frame while under # the hood calling the pyglet event loop log.info("Tips: You are now in the interactive mode. Now you can use the keyboard" " and the mouse to interact with the scene. Just press `q` if you want to quit.") self.quit_interaction = False self.lock_static_mobject_data() while not (self.window.is_closing or self.quit_interaction): self.update_frame(1 / self.camera.frame_rate) if self.window.is_closing: self.window.destroy() if self.quit_interaction: self.unlock_mobject_data()
def interact(self) -> None: # If there is a window, enter a loop # which updates the frame while under # the hood calling the pyglet event loop if self.window is None: return log.info( "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`" " if you want to quit.") self.skip_animations = False self.refresh_static_mobjects() while not self.is_window_closing(): self.update_frame(1 / self.camera.fps)
def wait(self, duration: float = DEFAULT_WAIT_TIME, stop_condition: Callable[[], bool] = None, note: str = None, ignore_presenter_mode: bool = False): self.update_mobjects(dt=0) # Any problems with this? if self.presenter_mode and not self.skip_animations and not ignore_presenter_mode: if note: log.info(note) self.hold_loop() else: time_progression = self.get_wait_time_progression( duration, stop_condition) last_t = 0 for t in time_progression: dt = t - last_t last_t = t self.update_frame(dt) self.emit_frame() if stop_condition is not None and stop_condition(): break self.refresh_static_mobjects() return self
def get_configuration(args): global __config_file__ # ensure __config_file__ always exists if args.config_file is not None: if not os.path.exists(args.config_file): log.error(f"Can't find {args.config_file}.") if sys.platform == 'win32': log.info( f"Copying default configuration file to {args.config_file}..." ) os.system(f"copy default_config.yml {args.config_file}") elif sys.platform in ["linux2", "darwin"]: log.info( f"Copying default configuration file to {args.config_file}..." ) os.system(f"cp default_config.yml {args.config_file}") else: log.info("Please create the configuration file manually.") log.info("Read configuration from default_config.yml.") else: __config_file__ = args.config_file global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml") if not (os.path.exists(global_defaults_file) or os.path.exists(__config_file__)): log.info( "There is no configuration file detected. Switch to the config file initializer:" ) init_customization() elif not os.path.exists(__config_file__): log.info( f"Using the default configuration file, which you can modify in `{global_defaults_file}`" ) log.info( "If you want to create a local configuration file, you can create a file named" f" `{__config_file__}`, or run `manimgl --config`") custom_config = get_custom_config() check_temporary_storage(custom_config) write_file = any([args.write_file, args.open, args.finder]) if args.transparent: file_ext = ".mov" elif args.gif: file_ext = ".gif" else: file_ext = ".mp4" dir_config = custom_config["directories"] output_directory = args.video_dir or dir_config["output"] if dir_config["mirror_module_path"] and args.file: to_cut = dir_config["removed_mirror_prefix"] ext = os.path.abspath(args.file) ext = ext.replace(to_cut, "").replace(".py", "") if ext.startswith("_"): ext = ext[1:] output_directory = os.path.join(output_directory, ext) file_writer_config = { "write_to_movie": not args.skip_animations and write_file, "break_into_partial_movies": custom_config["break_into_partial_movies"], "save_last_frame": args.skip_animations and write_file, "save_pngs": args.save_pngs, # If -t is passed in (for transparent), this will be RGBA "png_mode": "RGBA" if args.transparent else "RGB", "movie_file_extension": file_ext, "output_directory": output_directory, "file_name": args.file_name, "input_file_path": args.file or "", "open_file_upon_completion": args.open, "show_file_location_upon_completion": args.finder, "quiet": args.quiet, } module = get_module(args.file) if args.embed is not None: with insert_embed_line(args.file, args.scene_names[0], args.embed) as alt_file: module = get_module(alt_file) config = { "module": module, "scene_names": args.scene_names, "file_writer_config": file_writer_config, "quiet": args.quiet or args.write_all, "write_all": args.write_all, "skip_animations": args.skip_animations, "start_at_animation_number": args.start_at_animation_number, "end_at_animation_number": None, "preview": not write_file, "presenter_mode": args.presenter_mode, "leave_progress_bars": args.leave_progress_bars, "show_animation_progress": args.show_animation_progress, } # Camera configuration config["camera_config"] = get_camera_configuration(args, custom_config) # Default to making window half the screen size # but make it full screen if -f is passed in monitors = get_monitors() mon_index = custom_config["window_monitor"] monitor = monitors[min(mon_index, len(monitors) - 1)] window_width = monitor.width if not (args.full_screen or custom_config["full_screen"]): window_width //= 2 window_height = window_width * 9 // 16 config["window_config"] = { "size": (window_width, window_height), } # Arguments related to skipping stan = config["start_at_animation_number"] if stan is not None: if "," in stan: start, end = stan.split(",") config["start_at_animation_number"] = int(start) config["end_at_animation_number"] = int(end) else: config["start_at_animation_number"] = int(stan) return config
def print_file_ready_message(self, file_path: str) -> None: if not self.quiet: log.info(f"File ready at {file_path}")