mirror of
https://github.com/3b1b/manim.git
synced 2025-07-30 13:34:19 +08:00
Improved stage_scenes and refactored get_movie_output_directory methods
This commit is contained in:
@ -2,7 +2,7 @@ import os
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
# Things anyone wishing to use this repository for their
|
# Things anyone wishing to use this repository for their
|
||||||
# own use will want to change this
|
# own use will want to change
|
||||||
MEDIA_DIR = os.path.join(
|
MEDIA_DIR = os.path.join(
|
||||||
os.path.expanduser('~'),
|
os.path.expanduser('~'),
|
||||||
"Dropbox (3Blue1Brown)/3Blue1Brown Team Folder"
|
"Dropbox (3Blue1Brown)/3Blue1Brown Team Folder"
|
||||||
|
@ -146,7 +146,7 @@ def handle_scene(scene, **config):
|
|||||||
if (platform.system() == "Linux"):
|
if (platform.system() == "Linux"):
|
||||||
commands = ["xdg-open"]
|
commands = ["xdg-open"]
|
||||||
elif (platform.system() == "Windows"):
|
elif (platform.system() == "Windows"):
|
||||||
commands = ["start"]
|
commands = ["start"]
|
||||||
|
|
||||||
if config["show_file_in_finder"]:
|
if config["show_file_in_finder"]:
|
||||||
commands.append("-R")
|
commands.append("-R")
|
||||||
@ -238,10 +238,10 @@ def main():
|
|||||||
module = get_module(config["file"])
|
module = get_module(config["file"])
|
||||||
scene_names_to_classes = dict(inspect.getmembers(module, is_scene))
|
scene_names_to_classes = dict(inspect.getmembers(module, is_scene))
|
||||||
|
|
||||||
config["output_directory"] = os.path.join(
|
# config["output_directory"] = os.path.join(
|
||||||
ANIMATIONS_DIR,
|
# ANIMATIONS_DIR,
|
||||||
config["file"].replace(".py", "")
|
# config["file"].replace(".py", "")
|
||||||
)
|
# )
|
||||||
|
|
||||||
scene_kwargs = dict([
|
scene_kwargs = dict([
|
||||||
(key, config[key])
|
(key, config[key])
|
||||||
@ -250,7 +250,6 @@ def main():
|
|||||||
"frame_duration",
|
"frame_duration",
|
||||||
"skip_animations",
|
"skip_animations",
|
||||||
"write_to_movie",
|
"write_to_movie",
|
||||||
"output_directory",
|
|
||||||
"save_pngs",
|
"save_pngs",
|
||||||
"movie_file_extension",
|
"movie_file_extension",
|
||||||
"start_at_animation_number",
|
"start_at_animation_number",
|
||||||
|
@ -29,6 +29,32 @@ def add_extension_if_not_present(file_name, extension):
|
|||||||
return file_name
|
return file_name
|
||||||
|
|
||||||
|
|
||||||
|
def get_scene_output_directory(scene_class):
|
||||||
|
file_path = os.path.abspath(inspect.getfile(scene_class))
|
||||||
|
|
||||||
|
# TODO, is there a better way to do this?
|
||||||
|
parts = file_path.split(os.path.sep)
|
||||||
|
if "manim" in parts:
|
||||||
|
sub_parts = parts[parts.index("manim") + 1:]
|
||||||
|
file_path = os.path.join(*sub_parts)
|
||||||
|
file_path = file_path.replace(".pyc", "")
|
||||||
|
file_path = file_path.replace(".py", "")
|
||||||
|
return os.path.join(ANIMATIONS_DIR, file_path)
|
||||||
|
|
||||||
|
|
||||||
|
def get_movie_output_directory(scene_class, camera_config, frame_duration):
|
||||||
|
directory = get_scene_output_directory(scene_class)
|
||||||
|
sub_dir = "%dp%d" % (
|
||||||
|
camera_config["pixel_shape"][0],
|
||||||
|
int(1.0 / frame_duration)
|
||||||
|
)
|
||||||
|
return os.path.join(directory, sub_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def get_image_output_directory(scene_class, sub_dir="images"):
|
||||||
|
return os.path.join(get_scene_output_directory(scene_class), sub_dir)
|
||||||
|
|
||||||
|
|
||||||
class Scene(Container):
|
class Scene(Container):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"camera_class": Camera,
|
"camera_class": Camera,
|
||||||
@ -41,14 +67,12 @@ class Scene(Container):
|
|||||||
"save_frames": False,
|
"save_frames": False,
|
||||||
"save_pngs": False,
|
"save_pngs": False,
|
||||||
"pngs_mode": "RGBA",
|
"pngs_mode": "RGBA",
|
||||||
"output_directory": ANIMATIONS_DIR,
|
|
||||||
"movie_file_extension": ".mp4",
|
"movie_file_extension": ".mp4",
|
||||||
"name": None,
|
"name": None,
|
||||||
"always_continually_update": False,
|
"always_continually_update": False,
|
||||||
"random_seed": 0,
|
"random_seed": 0,
|
||||||
"start_at_animation_number": None,
|
"start_at_animation_number": None,
|
||||||
"end_at_animation_number": None,
|
"end_at_animation_number": None,
|
||||||
"include_render_quality_in_output_directory": True,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@ -543,10 +567,10 @@ class Scene(Container):
|
|||||||
self.get_image().show()
|
self.get_image().show()
|
||||||
|
|
||||||
def get_image_file_path(self, name=None, dont_update=False):
|
def get_image_file_path(self, name=None, dont_update=False):
|
||||||
folder = "images"
|
sub_dir = "images"
|
||||||
if dont_update:
|
if dont_update:
|
||||||
folder = str(self)
|
sub_dir = str(self)
|
||||||
path = os.path.join(self.output_directory, folder)
|
path = get_image_output_directory(self.__class__, sub_dir)
|
||||||
file_name = add_extension_if_not_present(name or str(self), ".png")
|
file_name = add_extension_if_not_present(name or str(self), ".png")
|
||||||
return os.path.join(path, file_name)
|
return os.path.join(path, file_name)
|
||||||
|
|
||||||
@ -562,16 +586,9 @@ class Scene(Container):
|
|||||||
image.save(path)
|
image.save(path)
|
||||||
|
|
||||||
def get_movie_file_path(self, name=None, extension=None):
|
def get_movie_file_path(self, name=None, extension=None):
|
||||||
directory = self.output_directory
|
directory = get_movie_output_directory(
|
||||||
if self.include_render_quality_in_output_directory:
|
self.__class__, self.camera_config, self.frame_duration
|
||||||
sub_dir = "%dp%d" % (
|
)
|
||||||
self.camera.pixel_shape[0],
|
|
||||||
int(1.0 / self.frame_duration)
|
|
||||||
)
|
|
||||||
directory = os.path.join(directory, sub_dir)
|
|
||||||
if not os.path.exists(directory):
|
|
||||||
os.makedirs(directory)
|
|
||||||
|
|
||||||
if extension is None:
|
if extension is None:
|
||||||
extension = self.movie_file_extension
|
extension = self.movie_file_extension
|
||||||
if name is None:
|
if name is None:
|
||||||
|
@ -1,59 +1,68 @@
|
|||||||
import inspect
|
import inspect
|
||||||
import itertools as it
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from constants import ANIMATIONS_DIR
|
from constants import ANIMATIONS_DIR
|
||||||
from constants import STAGED_SCENES_DIR
|
from constants import PRODUCTION_QUALITY_CAMERA_CONFIG
|
||||||
|
from constants import PRODUCTION_QUALITY_FRAME_DURATION
|
||||||
from extract_scene import get_module
|
from extract_scene import get_module
|
||||||
from extract_scene import is_scene
|
from extract_scene import is_scene
|
||||||
|
from scene.scene import get_movie_output_directory
|
||||||
|
|
||||||
|
|
||||||
def get_sorted_scene_names(module_name):
|
def get_sorted_scene_classes(module_name):
|
||||||
module = get_module(module_name)
|
module = get_module(module_name)
|
||||||
line_to_scene = {}
|
line_to_scene = {}
|
||||||
for name, scene_class in inspect.getmembers(module, is_scene):
|
for name, scene_class in inspect.getmembers(module, is_scene):
|
||||||
|
if inspect.getmodule(scene_class) != module:
|
||||||
|
continue
|
||||||
lines, line_no = inspect.getsourcelines(scene_class)
|
lines, line_no = inspect.getsourcelines(scene_class)
|
||||||
line_to_scene[line_no] = name
|
line_to_scene[line_no] = scene_class
|
||||||
return [
|
return [
|
||||||
line_to_scene[line_no]
|
line_to_scene[index]
|
||||||
for line_no in sorted(line_to_scene.keys())
|
for index in sorted(line_to_scene.keys())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def stage_animations(module_name):
|
def stage_animations(module_name):
|
||||||
scene_names = get_sorted_scene_names(module_name)
|
scene_classes = get_sorted_scene_classes(module_name)
|
||||||
animation_dir = os.path.join(
|
if len(scene_classes) == 0:
|
||||||
ANIMATIONS_DIR, module_name.replace(".py", "")
|
print("There are no rendered animations from this module")
|
||||||
|
return
|
||||||
|
animation_dir = get_movie_output_directory(
|
||||||
|
scene_classes[0],
|
||||||
|
PRODUCTION_QUALITY_CAMERA_CONFIG,
|
||||||
|
PRODUCTION_QUALITY_FRAME_DURATION,
|
||||||
)
|
)
|
||||||
files = os.listdir(animation_dir)
|
files = os.listdir(animation_dir)
|
||||||
sorted_files = []
|
sorted_files = []
|
||||||
for scene in scene_names:
|
for scene_class in scene_classes:
|
||||||
for clip in filter(lambda f : f.startswith(scene), files):
|
scene_name = scene_class.__name__
|
||||||
sorted_files.append(
|
for clip in filter(lambda f: f.startswith(scene_name + "."), files):
|
||||||
os.path.join(animation_dir, clip)
|
sorted_files.append(os.path.join(animation_dir, clip))
|
||||||
)
|
|
||||||
staged_scenes_dir = os.path.join(animation_dir, "staged_scenes")
|
animation_subdir = os.path.dirname(animation_dir)
|
||||||
count = 0
|
count = 0
|
||||||
while True:
|
while True:
|
||||||
staged_scenes_dir = os.path.join(
|
staged_scenes_dir = os.path.join(
|
||||||
animation_dir, "staged_scenes_%d"%count
|
animation_subdir, "staged_scenes_%d" % count
|
||||||
)
|
)
|
||||||
if not os.path.exists(staged_scenes_dir):
|
if not os.path.exists(staged_scenes_dir):
|
||||||
os.makedirs(staged_scenes_dir)
|
os.makedirs(staged_scenes_dir)
|
||||||
break
|
break
|
||||||
#Otherwise, keep trying new names until
|
# Otherwise, keep trying new names until
|
||||||
#there is a free one
|
# there is a free one
|
||||||
count += 1
|
count += 1
|
||||||
for count, f in enumerate(sorted_files):
|
for count, f in enumerate(sorted_files):
|
||||||
symlink_name = os.path.join(
|
symlink_name = os.path.join(
|
||||||
staged_scenes_dir,
|
staged_scenes_dir,
|
||||||
"Scene_%03d"%count + f.split(os.sep)[-1]
|
"Scene_%03d" % count + f.split(os.sep)[-1]
|
||||||
)
|
)
|
||||||
os.symlink(f, symlink_name)
|
os.symlink(f, symlink_name)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
raise Exception("No module given.")
|
raise Exception("No module given.")
|
||||||
module_name = sys.argv[1]
|
module_name = sys.argv[1]
|
||||||
stage_animations(module_name)
|
stage_animations(module_name)
|
||||||
|
Reference in New Issue
Block a user