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
27 changes: 27 additions & 0 deletions example_scenes/custom_template.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
\documentclass[preview]{standalone}

\usepackage[english]{babel}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage[f]{esvect}
\usepackage{dsfont}
\usepackage{setspace}
\usepackage{tipa}
\usepackage{relsize}
\usepackage{textcomp}
\usepackage{mathrsfs}
\usepackage{calligra}
\usepackage{wasysym}
\usepackage{ragged2e}
\usepackage{physics}
\usepackage{xcolor}
\usepackage{microtype}
\DisableLigatures{encoding = *, family = * }
%\usepackage[UTF8]{ctex}
\linespread{1}

\begin{document}

YourTextHere

\end{document}
27 changes: 27 additions & 0 deletions example_scenes/customtex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from manim import *

# Test cases:
# 1. manim customtex.py ExampleFileScene -pl
# --> should fail, because \vv is not defined
#
# 2. manim customtex.py ExampleFileScene --tex_template custom_template.tex -pl
# --> should succeed as custom template includes package esvect (which defines \vv)
#
# 3. manim customtex.py ExampleClassScene -pl
# --> should succeed as the package esvect is included in template object

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

class ExampleClassScene(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
45 changes: 44 additions & 1 deletion manim/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import sys
import types

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 +141,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 +182,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 +288,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.
"""
constants.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
constants.TEX_TEMPLATE = TexTemplateFromFile(filename=filename)
else:
# use the default template
constants.TEX_TEMPLATE = TexTemplate()
13 changes: 1 addition & 12 deletions manim/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,7 @@ 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*}",
)
TEX_TEMPLATE = None

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