Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions example_scenes/customtex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from manim import *

class ExampleFileScene(Scene):
def construct(self):
text=TexMobject(r"\vv{vb}")
#text=TextMobject(r"$\vv{vb}$")
self.play(Write(text))

class ExampleScene(Scene):
def construct(self):
tpl=TexTemplate()
tpl.append_package(["esvect",["f"]])
config.register_tex_template(tpl)

#text=TextMobject(r"$\vv{vb}$")
text=TexMobject(r"\vv{vb}")
self.play(Write(text))
1 change: 1 addition & 0 deletions manim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@
from .utils.sounds import *
from .utils.space_ops import *
from .utils.strings import *
from .utils.tex import *
1 change: 1 addition & 0 deletions manim/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def main():
args = config.parse_cli()
cfg = config.get_configuration(args)
config.initialize_directories(cfg)
config.initialize_tex(cfg)
extract_scene.main(cfg)


Expand Down
46 changes: 45 additions & 1 deletion manim/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import os
import sys
import types
import manim.constants as consts

from .utils.tex import *
from . import constants
from . import dirs
from .logger import logger

__all__ = ["parse_cli", "get_configuration", "initialize_directories"]
__all__ = ["parse_cli", "get_configuration", "initialize_directories","register_tex_template","initialize_tex"]


def parse_cli():
Expand Down Expand Up @@ -140,7 +142,12 @@ def parse_cli():
"--text_dir",
help="Directory to write text",
)
parser.add_argument(
"--tex_template",
help="Specify a custom TeX template file",
)
return parser.parse_args()

except argparse.ArgumentError as err:
logger.error(str(err))
sys.exit(2)
Expand Down Expand Up @@ -176,6 +183,7 @@ def get_configuration(args):
"video_dir": args.video_dir,
"tex_dir": args.tex_dir,
"text_dir": args.text_dir,
"tex_template": args.tex_template,
}

# Camera configuration
Expand Down Expand Up @@ -281,3 +289,39 @@ def initialize_directories(config):
dirs.VIDEO_DIR = dir_config["video_dir"]
dirs.TEX_DIR = dir_config["tex_dir"]
dirs.TEXT_DIR = dir_config["text_dir"]

def register_tex_template(tpl):
"""Register the given LaTeX template for later use.

Parameters
----------
tpl : :class:`~.TexTemplate`
The LaTeX template to register.
"""
consts.TEX_TEMPLATE = tpl

def initialize_tex(config):
"""Safely create a LaTeX template object from a file.
If file is not readable, the default template file is used.

Parameters
----------
filename : :class:`str`
The name of the file with the LaTeX template.
"""
filename=""
if config["tex_template"]:
filename = os.path.expanduser(config["tex_template"])
if filename and not os.access(filename, os.R_OK):
# custom template not available, fallback to default
logger.warning(
f"Custom TeX template {filename} not found or not readable. "
"Falling back to the default template."
)
filename = ""
if filename:
# still having a filename -> use the file
consts.TEX_TEMPLATE = TexTemplateFromFile(filename=filename)
else:
# use the default template
consts.TEX_TEMPLATE = TexTemplate()
82 changes: 69 additions & 13 deletions manim/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,58 @@
import os
from .logger import logger

MEDIA_DIR = ""
VIDEO_DIR = ""
VIDEO_OUTPUT_DIR = ""
TEX_DIR = ""
TEXT_DIR = ""
TEX_TEMPLATE = None

def initialize_directories(config):
global MEDIA_DIR
global VIDEO_DIR
global VIDEO_OUTPUT_DIR
global TEX_DIR
global TEXT_DIR

video_path_specified = config["video_dir"] or config["video_output_dir"]

if not (video_path_specified and config["tex_dir"]):
if config["media_dir"]:
MEDIA_DIR = config["media_dir"]
else:
MEDIA_DIR = os.path.join(
os.path.expanduser('~'),
"Dropbox (3Blue1Brown)/3Blue1Brown Team Folder"
)
if not os.path.isdir(MEDIA_DIR):
MEDIA_DIR = "./media"
print(
f"Media will be written to {MEDIA_DIR + os.sep}. You can change "
"this behavior with the --media_dir flag."
)
else:
if config["media_dir"]:
print(
"Ignoring --media_dir, since both --tex_dir and a video "
"directory were both passed"
)

TEX_DIR = config["tex_dir"] or os.path.join(MEDIA_DIR, "Tex")
TEXT_DIR = os.path.join(MEDIA_DIR, "texts")
if not video_path_specified:
VIDEO_DIR = os.path.join(MEDIA_DIR, "videos")
VIDEO_OUTPUT_DIR = os.path.join(MEDIA_DIR, "videos")
elif config["video_output_dir"]:
VIDEO_OUTPUT_DIR = config["video_output_dir"]
else:
VIDEO_DIR = config["video_dir"]

for folder in [VIDEO_DIR, VIDEO_OUTPUT_DIR, TEX_DIR, TEXT_DIR]:
if folder != "" and not os.path.exists(folder):
os.makedirs(folder)


NOT_SETTING_FONT_MSG='''
You haven't set font.
If you are not using English, this may cause text rendering problem.
Expand All @@ -20,19 +72,23 @@ class MyText(Text):
OBLIQUE = 'OBLIQUE'
BOLD = 'BOLD'

TEX_USE_CTEX = False
TEX_TEXT_TO_REPLACE = "YourTextHere"
TEMPLATE_TEX_FILE = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"tex_template.tex" if not TEX_USE_CTEX else "ctex_template.tex"
)
with open(TEMPLATE_TEX_FILE, "r") as infile:
TEMPLATE_TEXT_FILE_BODY = infile.read()
TEMPLATE_TEX_FILE_BODY = TEMPLATE_TEXT_FILE_BODY.replace(
TEX_TEXT_TO_REPLACE,
"\\begin{align*}\n" + TEX_TEXT_TO_REPLACE + "\n\\end{align*}",
)

HELP_MESSAGE = """
Usage:
python extract_scene.py <module> [<scene name>]
-p preview in low quality
-s show and save picture of last frame
-w write result to file [this is default if nothing else is stated]
-o <file_name> write to a different file_name
-l use low quality
-m use medium quality
-a run and save every scene in the script, or all args for the given scene
-q don't print progress
-f when writing to a movie file, export the frames in png sequence
-t use transperency when exporting images
-n specify the number of the animation to start from
-r specify a resolution
-c specify a background color
"""
SCENE_NOT_FOUND_MESSAGE = """
{} is not in the script
"""
Expand Down
11 changes: 4 additions & 7 deletions manim/mobject/svg/tex_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from ...utils.strings import split_string_list_to_isolate_substrings
from ...utils.tex_file_writing import tex_to_svg_file


TEX_MOB_SCALE_FACTOR = 0.05


Expand All @@ -21,10 +20,8 @@ class TexSymbol(VMobjectFromSVGPathstring):
"""
pass


class SingleStringTexMobject(SVGMobject):
CONFIG = {
"template_tex_file_body": TEMPLATE_TEX_FILE_BODY,
"stroke_width": 0,
"fill_opacity": 1.0,
"background_stroke_width": 1,
Expand All @@ -33,6 +30,7 @@ class SingleStringTexMobject(SVGMobject):
"height": None,
"organize_left_to_right": False,
"alignment": "",
"type": "tex",
}

def __init__(self, tex_string, **kwargs):
Expand All @@ -41,7 +39,7 @@ def __init__(self, tex_string, **kwargs):
self.tex_string = tex_string
file_name = tex_to_svg_file(
self.get_modified_expression(tex_string),
self.template_tex_file_body
self.type
)
SVGMobject.__init__(self, file_name=file_name, **kwargs)
if self.height is None:
Expand Down Expand Up @@ -247,9 +245,9 @@ def sort_alphabetically(self):

class TextMobject(TexMobject):
CONFIG = {
"template_tex_file_body": TEMPLATE_TEXT_FILE_BODY,
"alignment": "\\centering",
"arg_separator": "",
"type": "text",
}


Expand All @@ -258,7 +256,6 @@ class BulletedList(TextMobject):
"buff": MED_LARGE_BUFF,
"dot_scale_factor": 2,
# Have to include because of handle_multiple_args implementation
"template_tex_file_body": TEMPLATE_TEXT_FILE_BODY,
"alignment": "",
}

Expand Down Expand Up @@ -325,4 +322,4 @@ def __init__(self, *text_parts, **kwargs):
else:
underline.set_width(self.underline_width)
self.add(underline)
self.underline = underline
self.underline = underline
Loading