2018-12-22 14:27:22 -08:00
|
|
|
import argparse
|
|
|
|
import colour
|
2022-04-12 19:19:59 +08:00
|
|
|
from contextlib import contextmanager
|
2021-01-02 20:47:51 -08:00
|
|
|
import importlib
|
2022-04-12 19:19:59 +08:00
|
|
|
import inspect
|
2018-12-22 14:27:22 -08:00
|
|
|
import os
|
2022-04-12 19:19:59 +08:00
|
|
|
from screeninfo import get_monitors
|
2018-12-22 14:27:22 -08:00
|
|
|
import sys
|
2021-01-02 20:47:51 -08:00
|
|
|
import yaml
|
2018-12-22 14:27:22 -08:00
|
|
|
|
2022-04-12 19:19:59 +08:00
|
|
|
from manimlib.logger import log
|
2021-01-18 10:58:33 -08:00
|
|
|
from manimlib.utils.config_ops import merge_dicts_recursively
|
2021-02-07 17:45:18 +08:00
|
|
|
from manimlib.utils.init_config import init_customization
|
2021-01-18 10:58:33 -08:00
|
|
|
|
2018-12-22 14:27:22 -08:00
|
|
|
|
2021-11-14 12:31:56 -08:00
|
|
|
__config_file__ = "custom_config.yml"
|
|
|
|
|
|
|
|
|
2018-12-22 14:27:22 -08:00
|
|
|
def parse_cli():
|
|
|
|
try:
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
module_location = parser.add_mutually_exclusive_group()
|
|
|
|
module_location.add_argument(
|
|
|
|
"file",
|
|
|
|
nargs="?",
|
2022-02-14 19:50:30 +08:00
|
|
|
help="Path to file holding the python code for the scene",
|
2018-12-22 14:27:22 -08:00
|
|
|
)
|
|
|
|
parser.add_argument(
|
2019-01-12 12:31:29 -08:00
|
|
|
"scene_names",
|
2019-01-12 14:42:42 -08:00
|
|
|
nargs="*",
|
2018-12-22 14:27:22 -08:00
|
|
|
help="Name of the Scene class you want to see",
|
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
2020-02-13 10:49:25 -08:00
|
|
|
"-w", "--write_file",
|
2019-01-12 14:42:42 -08:00
|
|
|
action="store_true",
|
|
|
|
help="Render the scene as a movie file",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
2020-02-13 10:49:25 -08:00
|
|
|
"-s", "--skip_animations",
|
2019-01-12 14:42:42 -08:00
|
|
|
action="store_true",
|
2019-01-24 22:24:01 -08:00
|
|
|
help="Save the last frame",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-l", "--low_quality",
|
|
|
|
action="store_true",
|
|
|
|
help="Render at a low quality (for faster rendering)",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-m", "--medium_quality",
|
|
|
|
action="store_true",
|
|
|
|
help="Render at a medium quality",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-06-02 18:58:33 -07:00
|
|
|
parser.add_argument(
|
2021-01-02 20:47:51 -08:00
|
|
|
"--hd",
|
2019-06-02 18:58:33 -07:00
|
|
|
action="store_true",
|
2021-01-02 20:47:51 -08:00
|
|
|
help="Render at a 1080p",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--uhd",
|
|
|
|
action="store_true",
|
|
|
|
help="Render at a 4k",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-f", "--full_screen",
|
|
|
|
action="store_true",
|
|
|
|
help="Show window in full screen",
|
|
|
|
)
|
2022-02-13 15:16:16 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-p", "--presenter_mode",
|
|
|
|
action="store_true",
|
2022-02-14 19:50:30 +08:00
|
|
|
help="Scene will stay paused during wait calls until "
|
2022-02-13 15:16:16 -08:00
|
|
|
"space bar or right arrow is hit, like a slide show"
|
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-g", "--save_pngs",
|
|
|
|
action="store_true",
|
|
|
|
help="Save each frame as a png",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-06-02 21:13:22 +02:00
|
|
|
parser.add_argument(
|
2021-01-23 16:08:39 -08:00
|
|
|
"-i", "--gif",
|
2019-06-02 21:13:22 +02:00
|
|
|
action="store_true",
|
|
|
|
help="Save the video as gif",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-t", "--transparent",
|
|
|
|
action="store_true",
|
|
|
|
help="Render to a movie file with an alpha channel",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-q", "--quiet",
|
|
|
|
action="store_true",
|
|
|
|
help="",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-a", "--write_all",
|
|
|
|
action="store_true",
|
|
|
|
help="Write all the scenes from a file",
|
2021-01-02 20:47:51 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
2020-02-11 19:52:14 -08:00
|
|
|
"-o", "--open",
|
|
|
|
action="store_true",
|
|
|
|
help="Automatically open the saved file once its done",
|
|
|
|
)
|
2021-01-02 20:47:51 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"--finder",
|
|
|
|
action="store_true",
|
|
|
|
help="Show the output file in finder",
|
|
|
|
)
|
2021-02-07 17:45:18 +08:00
|
|
|
parser.add_argument(
|
|
|
|
"--config",
|
|
|
|
action="store_true",
|
|
|
|
help="Guide for automatic configuration",
|
|
|
|
)
|
2020-02-11 19:52:14 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"--file_name",
|
|
|
|
help="Name for the movie or image file",
|
2019-01-12 14:42:42 -08:00
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-n", "--start_at_animation_number",
|
2022-04-22 10:17:15 -07:00
|
|
|
help="Start rendering not from the first animation, but "
|
|
|
|
"from another, specified by its index. If you pass "
|
|
|
|
"in two comma separated values, e.g. \"3,6\", it will end "
|
2019-01-12 14:42:42 -08:00
|
|
|
"the rendering at the second value",
|
|
|
|
)
|
2021-11-14 12:31:56 -08:00
|
|
|
parser.add_argument(
|
2022-04-22 10:17:15 -07:00
|
|
|
"-e", "--embed",
|
2022-04-22 15:41:23 -07:00
|
|
|
nargs="?",
|
|
|
|
const="",
|
2022-04-22 10:17:15 -07:00
|
|
|
help="Creates a new file where the line `self.embed` is inserted "
|
|
|
|
"into the Scenes construct method. "
|
|
|
|
"If a string is passed in, the line will be inserted below the "
|
|
|
|
"last line of code including that string."
|
2021-11-14 12:31:56 -08:00
|
|
|
)
|
2019-01-12 14:42:42 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"-r", "--resolution",
|
2021-01-02 20:47:51 -08:00
|
|
|
help="Resolution, passed as \"WxH\", e.g. \"1920x1080\"",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
2022-05-14 17:47:31 -07:00
|
|
|
"--fps",
|
2021-01-02 20:47:51 -08:00
|
|
|
help="Frame rate, as an integer",
|
2019-01-12 14:42:42 -08:00
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-c", "--color",
|
|
|
|
help="Background color",
|
|
|
|
)
|
2019-01-16 11:08:14 -08:00
|
|
|
parser.add_argument(
|
|
|
|
"--leave_progress_bars",
|
|
|
|
action="store_true",
|
|
|
|
help="Leave progress bars displayed in terminal",
|
|
|
|
)
|
2022-04-27 11:19:20 -07:00
|
|
|
parser.add_argument(
|
|
|
|
"--show_animation_progress",
|
|
|
|
action="store_true",
|
|
|
|
help="Show progress bar for each animation",
|
|
|
|
)
|
2021-01-02 20:47:51 -08:00
|
|
|
parser.add_argument(
|
2019-06-04 20:51:18 -07:00
|
|
|
"--video_dir",
|
2021-04-09 21:32:52 +08:00
|
|
|
help="Directory to write video",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--config_file",
|
|
|
|
help="Path to the custom configuration file",
|
2019-06-04 20:51:18 -07:00
|
|
|
)
|
2021-10-06 17:54:28 +08:00
|
|
|
parser.add_argument(
|
|
|
|
"-v", "--version",
|
|
|
|
action="store_true",
|
|
|
|
help="Display the version of manimgl"
|
|
|
|
)
|
2021-10-16 21:01:39 +08:00
|
|
|
parser.add_argument(
|
|
|
|
"--log-level",
|
|
|
|
help="Level of messages to Display, can be DEBUG / INFO / WARNING / ERROR / CRITICAL"
|
|
|
|
)
|
2018-12-22 14:27:22 -08:00
|
|
|
args = parser.parse_args()
|
2018-12-22 18:25:35 -08:00
|
|
|
return args
|
2018-12-22 14:27:22 -08:00
|
|
|
except argparse.ArgumentError as err:
|
2021-10-07 17:37:10 +08:00
|
|
|
log.error(str(err))
|
2018-12-22 14:27:22 -08:00
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
|
2021-01-02 20:47:51 -08:00
|
|
|
def get_manim_dir():
|
2021-02-02 21:00:36 +08:00
|
|
|
manimlib_module = importlib.import_module("manimlib")
|
|
|
|
manimlib_dir = os.path.dirname(inspect.getabsfile(manimlib_module))
|
|
|
|
return os.path.abspath(os.path.join(manimlib_dir, ".."))
|
2021-01-02 20:47:51 -08:00
|
|
|
|
|
|
|
|
2018-12-24 12:49:10 -08:00
|
|
|
def get_module(file_name):
|
2021-01-02 22:03:00 -08:00
|
|
|
if file_name is None:
|
|
|
|
return None
|
2021-11-14 12:31:56 -08:00
|
|
|
module_name = file_name.replace(os.sep, ".").replace(".py", "")
|
|
|
|
spec = importlib.util.spec_from_file_location(module_name, file_name)
|
|
|
|
module = importlib.util.module_from_spec(spec)
|
|
|
|
spec.loader.exec_module(module)
|
|
|
|
return module
|
|
|
|
|
|
|
|
|
2022-04-22 15:41:23 -07:00
|
|
|
def get_indent(line: str):
|
|
|
|
return len(line) - len(line.lstrip())
|
|
|
|
|
|
|
|
|
2021-11-14 12:31:56 -08:00
|
|
|
@contextmanager
|
2022-04-22 15:41:23 -07:00
|
|
|
def insert_embed_line(file_name: str, scene_name: str, line_marker: str):
|
2022-04-22 10:17:15 -07:00
|
|
|
"""
|
|
|
|
This is hacky, but convenient. When user includes the argument "-e", it will try
|
|
|
|
to recreate a file that inserts the line `self.embed()` into the end of the scene's
|
|
|
|
construct method. If there is an argument passed in, it will insert the line after
|
|
|
|
the last line in the sourcefile which includes that string.
|
|
|
|
"""
|
2021-11-14 12:31:56 -08:00
|
|
|
with open(file_name, 'r') as fp:
|
|
|
|
lines = fp.readlines()
|
2022-04-22 10:17:15 -07:00
|
|
|
|
2022-04-22 15:41:23 -07:00
|
|
|
try:
|
|
|
|
scene_line_number = next(
|
|
|
|
i for i, line in enumerate(lines)
|
|
|
|
if line.startswith(f"class {scene_name}")
|
|
|
|
)
|
|
|
|
except StopIteration:
|
|
|
|
log.error(f"No scene {scene_name}")
|
|
|
|
|
|
|
|
prev_line_num = None
|
|
|
|
n_spaces = None
|
|
|
|
if len(line_marker) == 0:
|
|
|
|
# Find the end of the construct method
|
2022-04-22 10:17:15 -07:00
|
|
|
in_construct = False
|
2022-04-22 15:41:23 -07:00
|
|
|
for index in range(scene_line_number, len(lines) - 1):
|
|
|
|
line = lines[index]
|
|
|
|
if line.lstrip().startswith("def construct"):
|
2022-04-22 10:17:15 -07:00
|
|
|
in_construct = True
|
2022-04-22 15:41:23 -07:00
|
|
|
n_spaces = get_indent(line) + 4
|
2022-04-22 10:17:15 -07:00
|
|
|
elif in_construct:
|
2022-04-22 15:41:23 -07:00
|
|
|
if len(line.strip()) > 0 and get_indent(line) < n_spaces:
|
|
|
|
prev_line_num = index - 2
|
2022-04-22 10:17:15 -07:00
|
|
|
break
|
2022-05-01 15:31:31 -04:00
|
|
|
if prev_line_num is None:
|
|
|
|
prev_line_num = len(lines) - 2
|
2022-04-22 15:41:23 -07:00
|
|
|
elif line_marker.isdigit():
|
|
|
|
# Treat the argument as a line number
|
|
|
|
prev_line_num = int(line_marker) - 1
|
|
|
|
elif len(line_marker) > 0:
|
|
|
|
# Treat the argument as a string
|
|
|
|
try:
|
|
|
|
prev_line_num = next(
|
|
|
|
i
|
2022-05-01 15:31:31 -04:00
|
|
|
for i in range(scene_line_number, len(lines) - 1)
|
2022-04-22 15:41:23 -07:00
|
|
|
if line_marker in lines[i]
|
|
|
|
)
|
|
|
|
except StopIteration:
|
|
|
|
log.error(f"No lines matching {line_marker}")
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
# Insert and write new file
|
|
|
|
if n_spaces is None:
|
|
|
|
n_spaces = get_indent(lines[prev_line_num])
|
2022-04-23 10:16:11 -07:00
|
|
|
new_lines = list(lines)
|
|
|
|
new_lines.insert(prev_line_num + 1, " " * n_spaces + "self.embed()\n")
|
2022-04-24 10:28:53 -07:00
|
|
|
alt_file = file_name.replace(".py", "_insert_embed.py")
|
|
|
|
with open(alt_file, 'w') as fp:
|
2022-04-23 10:16:11 -07:00
|
|
|
fp.writelines(new_lines)
|
2021-11-14 12:31:56 -08:00
|
|
|
try:
|
2022-04-24 10:28:53 -07:00
|
|
|
yield alt_file
|
2021-11-14 12:31:56 -08:00
|
|
|
finally:
|
2022-04-24 10:28:53 -07:00
|
|
|
os.remove(alt_file)
|
2018-12-24 12:49:10 -08:00
|
|
|
|
|
|
|
|
2021-02-07 21:38:19 +08:00
|
|
|
def get_custom_config():
|
2021-04-09 21:32:52 +08:00
|
|
|
global __config_file__
|
|
|
|
|
2021-02-07 21:38:19 +08:00
|
|
|
global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml")
|
2021-01-18 10:58:33 -08:00
|
|
|
|
2021-02-07 17:45:18 +08:00
|
|
|
if os.path.exists(global_defaults_file):
|
|
|
|
with open(global_defaults_file, "r") as file:
|
2021-02-07 21:38:19 +08:00
|
|
|
config = yaml.safe_load(file)
|
2021-01-18 10:58:33 -08:00
|
|
|
|
2021-04-09 21:32:52 +08:00
|
|
|
if os.path.exists(__config_file__):
|
|
|
|
with open(__config_file__, "r") as file:
|
2021-02-07 21:38:19 +08:00
|
|
|
local_defaults = yaml.safe_load(file)
|
|
|
|
if local_defaults:
|
|
|
|
config = merge_dicts_recursively(
|
|
|
|
config,
|
|
|
|
local_defaults,
|
|
|
|
)
|
2021-02-07 17:45:18 +08:00
|
|
|
else:
|
2021-04-09 21:32:52 +08:00
|
|
|
with open(__config_file__, "r") as file:
|
2021-02-07 21:38:19 +08:00
|
|
|
config = yaml.safe_load(file)
|
2021-04-09 21:32:52 +08:00
|
|
|
|
2021-02-07 21:38:19 +08:00
|
|
|
return config
|
2020-02-13 10:49:25 -08:00
|
|
|
|
2021-01-02 20:47:51 -08:00
|
|
|
|
2021-10-06 17:21:56 +08:00
|
|
|
def check_temporary_storage(config):
|
|
|
|
if config["directories"]["temporary_storage"] == "" and sys.platform == "win32":
|
2021-11-14 12:31:56 -08:00
|
|
|
log.warning(
|
|
|
|
"You may be using Windows platform and have not specified the path of"
|
2021-10-16 13:04:52 +08:00
|
|
|
" `temporary_storage`, which may cause OSError. So it is recommended"
|
2021-11-14 12:31:56 -08:00
|
|
|
" to specify the `temporary_storage` in the config file (.yml)"
|
|
|
|
)
|
2021-10-06 17:21:56 +08:00
|
|
|
|
|
|
|
|
2021-01-02 20:47:51 -08:00
|
|
|
def get_configuration(args):
|
2021-04-09 21:32:52 +08:00
|
|
|
global __config_file__
|
|
|
|
|
|
|
|
# ensure __config_file__ always exists
|
|
|
|
if args.config_file is not None:
|
|
|
|
if not os.path.exists(args.config_file):
|
2021-10-07 17:37:10 +08:00
|
|
|
log.error(f"Can't find {args.config_file}.")
|
2021-04-09 21:32:52 +08:00
|
|
|
if sys.platform == 'win32':
|
2021-10-07 17:37:10 +08:00
|
|
|
log.info(f"Copying default configuration file to {args.config_file}...")
|
2021-04-09 21:32:52 +08:00
|
|
|
os.system(f"copy default_config.yml {args.config_file}")
|
2021-06-14 16:21:38 +08:00
|
|
|
elif sys.platform in ["linux2", "darwin"]:
|
2021-10-07 17:37:10 +08:00
|
|
|
log.info(f"Copying default configuration file to {args.config_file}...")
|
2021-04-09 21:32:52 +08:00
|
|
|
os.system(f"cp default_config.yml {args.config_file}")
|
|
|
|
else:
|
2021-10-07 17:37:10 +08:00
|
|
|
log.info("Please create the configuration file manually.")
|
|
|
|
log.info("Read configuration from default_config.yml.")
|
2021-04-09 21:32:52 +08:00
|
|
|
else:
|
|
|
|
__config_file__ = args.config_file
|
|
|
|
|
2021-02-08 10:29:18 +08:00
|
|
|
global_defaults_file = os.path.join(get_manim_dir(), "manimlib", "default_config.yml")
|
2021-04-09 21:32:52 +08:00
|
|
|
|
|
|
|
if not (os.path.exists(global_defaults_file) or os.path.exists(__config_file__)):
|
2021-10-16 13:04:52 +08:00
|
|
|
log.info("There is no configuration file detected. Switch to the config file initializer:")
|
2021-02-08 10:29:18 +08:00
|
|
|
init_customization()
|
2021-04-09 21:32:52 +08:00
|
|
|
|
|
|
|
elif not os.path.exists(__config_file__):
|
2021-10-07 17:37:10 +08:00
|
|
|
log.info(f"Using the default configuration file, which you can modify in `{global_defaults_file}`")
|
2021-11-14 12:31:56 -08:00
|
|
|
log.info(
|
|
|
|
"If you want to create a local configuration file, you can create a file named"
|
|
|
|
f" `{__config_file__}`, or run `manimgl --config`"
|
|
|
|
)
|
2021-04-09 21:32:52 +08:00
|
|
|
|
2021-02-07 21:38:19 +08:00
|
|
|
custom_config = get_custom_config()
|
2021-10-06 17:21:56 +08:00
|
|
|
check_temporary_storage(custom_config)
|
2021-01-02 20:47:51 -08:00
|
|
|
|
|
|
|
write_file = any([args.write_file, args.open, args.finder])
|
2021-01-23 16:08:39 -08:00
|
|
|
if args.transparent:
|
|
|
|
file_ext = ".mov"
|
|
|
|
elif args.gif:
|
|
|
|
file_ext = ".gif"
|
|
|
|
else:
|
|
|
|
file_ext = ".mp4"
|
|
|
|
|
2022-05-04 21:21:49 -07:00
|
|
|
dir_config = custom_config["directories"]
|
|
|
|
output_directory = args.video_dir or dir_config["output"]
|
2022-05-11 12:44:51 -07:00
|
|
|
if dir_config["mirror_module_path"] and args.file:
|
2022-05-04 21:21:49 -07:00
|
|
|
to_cut = dir_config["removed_mirror_prefix"]
|
2022-05-11 12:44:51 -07:00
|
|
|
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)
|
2022-05-04 21:21:49 -07:00
|
|
|
|
2019-01-24 21:47:40 -08:00
|
|
|
file_writer_config = {
|
2020-02-13 10:49:25 -08:00
|
|
|
"write_to_movie": not args.skip_animations and write_file,
|
2021-02-07 21:38:19 +08:00
|
|
|
"break_into_partial_movies": custom_config["break_into_partial_movies"],
|
2020-02-13 10:49:25 -08:00
|
|
|
"save_last_frame": args.skip_animations and write_file,
|
2019-01-24 21:47:40 -08:00
|
|
|
"save_pngs": args.save_pngs,
|
|
|
|
# If -t is passed in (for transparent), this will be RGBA
|
|
|
|
"png_mode": "RGBA" if args.transparent else "RGB",
|
2021-01-23 16:08:39 -08:00
|
|
|
"movie_file_extension": file_ext,
|
2022-05-04 21:21:49 -07:00
|
|
|
"output_directory": output_directory,
|
2019-01-24 21:47:40 -08:00
|
|
|
"file_name": args.file_name,
|
2021-01-02 22:03:00 -08:00
|
|
|
"input_file_path": args.file or "",
|
2020-02-11 19:52:14 -08:00
|
|
|
"open_file_upon_completion": args.open,
|
2021-01-02 20:47:51 -08:00
|
|
|
"show_file_location_upon_completion": args.finder,
|
2020-02-11 19:52:14 -08:00
|
|
|
"quiet": args.quiet,
|
2019-01-24 21:47:40 -08:00
|
|
|
}
|
2020-02-13 10:49:25 -08:00
|
|
|
|
2022-04-22 10:17:15 -07:00
|
|
|
module = get_module(args.file)
|
|
|
|
|
|
|
|
if args.embed is not None:
|
2022-04-22 15:41:23 -07:00
|
|
|
with insert_embed_line(args.file, args.scene_names[0], args.embed) as alt_file:
|
2021-11-14 12:31:56 -08:00
|
|
|
module = get_module(alt_file)
|
|
|
|
|
2018-12-22 14:27:22 -08:00
|
|
|
config = {
|
2019-01-25 11:03:14 -08:00
|
|
|
"module": module,
|
2019-01-12 12:31:29 -08:00
|
|
|
"scene_names": args.scene_names,
|
2019-01-24 21:47:40 -08:00
|
|
|
"file_writer_config": file_writer_config,
|
2018-12-22 14:27:22 -08:00
|
|
|
"quiet": args.quiet or args.write_all,
|
|
|
|
"write_all": args.write_all,
|
2021-12-07 10:03:10 -08:00
|
|
|
"skip_animations": args.skip_animations,
|
2018-12-22 14:27:22 -08:00
|
|
|
"start_at_animation_number": args.start_at_animation_number,
|
|
|
|
"end_at_animation_number": None,
|
2021-12-07 10:03:10 -08:00
|
|
|
"preview": not write_file,
|
2022-02-13 15:16:16 -08:00
|
|
|
"presenter_mode": args.presenter_mode,
|
2019-06-04 20:51:18 -07:00
|
|
|
"leave_progress_bars": args.leave_progress_bars,
|
2022-04-27 11:19:20 -07:00
|
|
|
"show_animation_progress": args.show_animation_progress,
|
2018-12-22 14:27:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
# Camera configuration
|
2021-02-07 21:38:19 +08:00
|
|
|
config["camera_config"] = get_camera_configuration(args, custom_config)
|
2021-01-02 20:47:51 -08:00
|
|
|
|
2021-02-09 10:53:26 -08:00
|
|
|
# Default to making window half the screen size
|
2021-01-02 20:47:51 -08:00
|
|
|
# but make it full screen if -f is passed in
|
2021-03-18 17:32:45 -07:00
|
|
|
monitors = get_monitors()
|
|
|
|
mon_index = custom_config["window_monitor"]
|
|
|
|
monitor = monitors[min(mon_index, len(monitors) - 1)]
|
2021-01-19 11:35:25 -08:00
|
|
|
window_width = monitor.width
|
2021-11-08 21:47:02 -08:00
|
|
|
if not (args.full_screen or custom_config["full_screen"]):
|
2021-01-19 11:35:25 -08:00
|
|
|
window_width //= 2
|
|
|
|
window_height = window_width * 9 // 16
|
2020-02-11 19:52:14 -08:00
|
|
|
config["window_config"] = {
|
2021-01-02 20:47:51 -08:00
|
|
|
"size": (window_width, window_height),
|
2020-02-11 19:52:14 -08:00
|
|
|
}
|
2019-01-25 10:13:17 -08:00
|
|
|
|
|
|
|
# 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
|
|
|
|
|
|
|
|
|
2021-02-07 21:38:19 +08:00
|
|
|
def get_camera_configuration(args, custom_config):
|
2019-01-25 10:13:17 -08:00
|
|
|
camera_config = {}
|
2022-05-14 17:29:07 -07:00
|
|
|
camera_resolutions = get_custom_config()["camera_resolutions"]
|
2018-12-22 14:27:22 -08:00
|
|
|
if args.low_quality:
|
2022-05-14 17:29:07 -07:00
|
|
|
resolution = camera_resolutions["low"]
|
2018-12-22 14:27:22 -08:00
|
|
|
elif args.medium_quality:
|
2022-05-14 17:29:07 -07:00
|
|
|
resolution = camera_resolutions["med"]
|
2021-01-02 20:47:51 -08:00
|
|
|
elif args.hd:
|
2022-05-14 17:29:07 -07:00
|
|
|
resolution = camera_resolutions["high"]
|
2021-01-02 20:47:51 -08:00
|
|
|
elif args.uhd:
|
2022-05-14 17:29:07 -07:00
|
|
|
resolution = camera_resolutions["4k"]
|
2021-01-02 23:02:39 -08:00
|
|
|
else:
|
2022-05-14 17:29:07 -07:00
|
|
|
resolution = camera_resolutions[camera_resolutions["default_resolution"]]
|
2021-01-02 23:02:39 -08:00
|
|
|
|
2022-05-14 17:47:31 -07:00
|
|
|
if args.fps:
|
|
|
|
fps = int(args.fps)
|
2022-05-14 17:29:07 -07:00
|
|
|
else:
|
2022-05-14 17:47:31 -07:00
|
|
|
fps = get_custom_config()["fps"]
|
2021-01-02 23:02:39 -08:00
|
|
|
|
2022-05-14 17:29:07 -07:00
|
|
|
width_str, height_str = resolution.split("x")
|
2021-01-02 23:02:39 -08:00
|
|
|
width = int(width_str)
|
|
|
|
height = int(height_str)
|
|
|
|
|
|
|
|
camera_config.update({
|
|
|
|
"pixel_width": width,
|
|
|
|
"pixel_height": height,
|
2022-05-14 17:47:31 -07:00
|
|
|
"fps": fps,
|
2021-01-02 23:02:39 -08:00
|
|
|
})
|
2018-12-22 14:27:22 -08:00
|
|
|
|
2021-01-02 20:47:51 -08:00
|
|
|
try:
|
2021-02-07 21:38:19 +08:00
|
|
|
bg_color = args.color or custom_config["style"]["background_color"]
|
2021-01-02 20:47:51 -08:00
|
|
|
camera_config["background_color"] = colour.Color(bg_color)
|
2021-10-07 17:37:10 +08:00
|
|
|
except ValueError as err:
|
|
|
|
log.error("Please use a valid color")
|
|
|
|
log.error(err)
|
2021-01-02 20:47:51 -08:00
|
|
|
sys.exit(2)
|
2018-12-22 14:27:22 -08:00
|
|
|
|
|
|
|
# If rendering a transparent image/move, make sure the
|
|
|
|
# scene has a background opacity of 0
|
|
|
|
if args.transparent:
|
2019-01-25 10:13:17 -08:00
|
|
|
camera_config["background_opacity"] = 0
|
2018-12-22 14:27:22 -08:00
|
|
|
|
2019-01-25 10:13:17 -08:00
|
|
|
return camera_config
|