Skip to content

Commit 8ef42fa

Browse files
committed
Merge branch 'master' of https://github.com/3b1b/manim
2 parents 6be6bd3 + 9d6a28b commit 8ef42fa

File tree

9 files changed

+241
-232
lines changed

9 files changed

+241
-232
lines changed

manimlib/mobject/numbers.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from manimlib.mobject.svg.tex_mobject import SingleStringTex
33
from manimlib.mobject.svg.text_mobject import Text
44
from manimlib.mobject.types.vectorized_mobject import VMobject
5+
from manimlib.utils.iterables import hash_obj
56

67

78
string_to_mob_map = {}
@@ -20,23 +21,23 @@ class DecimalNumber(VMobject):
2021
"include_background_rectangle": False,
2122
"edge_to_fix": LEFT,
2223
"font_size": 48,
24+
"text_config": {} # Do not pass in font_size here
2325
}
2426

2527
def __init__(self, number=0, **kwargs):
2628
super().__init__(**kwargs)
2729
self.set_submobjects_from_number(number)
28-
self.init_colors()
2930

3031
def set_submobjects_from_number(self, number):
3132
self.number = number
3233
self.set_submobjects([])
33-
34+
string_to_mob_ = lambda s: self.string_to_mob(s, **self.text_config)
3435
num_string = self.get_num_string(number)
35-
self.add(*map(self.string_to_mob, num_string))
36+
self.add(*map(string_to_mob_, num_string))
3637

3738
# Add non-numerical bits
3839
if self.show_ellipsis:
39-
dots = self.string_to_mob("...")
40+
dots = string_to_mob_("...")
4041
dots.arrange(RIGHT, buff=2 * dots[0].get_width())
4142
self.add(dots)
4243
if self.unit is not None:
@@ -85,10 +86,10 @@ def init_data(self):
8586
def get_font_size(self):
8687
return self.data["font_size"][0]
8788

88-
def string_to_mob(self, string, mob_class=Text):
89-
if string not in string_to_mob_map:
90-
string_to_mob_map[string] = mob_class(string, font_size=1)
91-
mob = string_to_mob_map[string].copy()
89+
def string_to_mob(self, string, mob_class=Text, **kwargs):
90+
if (string, hash_obj(kwargs)) not in string_to_mob_map:
91+
string_to_mob_map[(string, hash_obj(kwargs))] = mob_class(string, font_size=1, **kwargs)
92+
mob = string_to_mob_map[(string, hash_obj(kwargs))].copy()
9293
mob.scale(self.get_font_size())
9394
return mob
9495

manimlib/mobject/svg/drawings.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,6 @@ def __init__(self, **kwargs):
318318
self.content = Mobject()
319319
self.refresh_triangulation()
320320

321-
def init_colors(self):
322-
VMobject.init_colors(self)
323-
324321
def get_tip(self):
325322
# TODO, find a better way
326323
return self.get_corner(DOWN + self.direction) - 0.6 * self.direction

manimlib/mobject/svg/mtex_mobject.py

Lines changed: 76 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
import re
33
from types import MethodType
44

5-
from manimlib.constants import BLACK
5+
from manimlib.constants import WHITE
66
from manimlib.mobject.svg.svg_mobject import SVGMobject
7-
from manimlib.mobject.types.vectorized_mobject import VMobject
87
from manimlib.mobject.types.vectorized_mobject import VGroup
98
from manimlib.utils.color import color_to_int_rgb
9+
from manimlib.utils.config_ops import digest_config
1010
from manimlib.utils.iterables import adjacent_pairs
1111
from manimlib.utils.iterables import remove_list_redundancies
1212
from manimlib.utils.tex_file_writing import tex_to_svg_file
@@ -18,25 +18,10 @@
1818
SCALE_FACTOR_PER_FONT_POINT = 0.001
1919

2020

21-
TEX_HASH_TO_MOB_MAP = {}
22-
23-
2421
def _get_neighbouring_pairs(iterable):
2522
return list(adjacent_pairs(iterable))[:-1]
2623

2724

28-
class _TexSVG(SVGMobject):
29-
CONFIG = {
30-
"color": BLACK,
31-
"stroke_width": 0,
32-
"height": None,
33-
"path_string_config": {
34-
"should_subdivide_sharp_curves": True,
35-
"should_remove_null_curves": True,
36-
},
37-
}
38-
39-
4025
class _TexParser(object):
4126
def __init__(self, tex_string, additional_substrings):
4227
self.tex_string = tex_string
@@ -400,10 +385,21 @@ def get_isolated_substrings(self):
400385
])
401386

402387

403-
class MTex(VMobject):
388+
class _TexSVG(SVGMobject):
404389
CONFIG = {
390+
"height": None,
405391
"fill_opacity": 1.0,
406392
"stroke_width": 0,
393+
"path_string_config": {
394+
"should_subdivide_sharp_curves": True,
395+
"should_remove_null_curves": True,
396+
},
397+
}
398+
399+
400+
class MTex(_TexSVG):
401+
CONFIG = {
402+
"color": WHITE,
407403
"font_size": 48,
408404
"alignment": "\\centering",
409405
"tex_environment": "align*",
@@ -413,65 +409,49 @@ class MTex(VMobject):
413409
}
414410

415411
def __init__(self, tex_string, **kwargs):
416-
super().__init__(**kwargs)
412+
digest_config(self, kwargs)
417413
tex_string = tex_string.strip()
418414
# Prevent from passing an empty string.
419415
if not tex_string:
420416
tex_string = "\\quad"
421417
self.tex_string = tex_string
422-
423-
self.__parser = _TexParser(
418+
self.parser = _TexParser(
424419
self.tex_string,
425420
[*self.tex_to_color_map.keys(), *self.isolate]
426421
)
427-
mob = self.generate_mobject()
428-
self.add(*mob.copy())
429-
self.init_colors()
422+
super().__init__(**kwargs)
423+
430424
self.set_color_by_tex_to_color_map(self.tex_to_color_map)
431425
self.scale(SCALE_FACTOR_PER_FONT_POINT * self.font_size)
432426

433-
@staticmethod
434-
def color_to_label(color):
435-
r, g, b = color_to_int_rgb(color)
436-
rg = r * 256 + g
437-
return rg * 256 + b
438-
439-
def generate_mobject(self):
440-
labelled_tex_string = self.__parser.get_labelled_tex_string()
441-
labelled_tex_content = self.get_tex_file_content(labelled_tex_string)
442-
hash_val = hash((labelled_tex_content, self.use_plain_tex))
427+
@property
428+
def hash_seed(self):
429+
return (
430+
self.__class__.__name__,
431+
self.svg_default,
432+
self.path_string_config,
433+
self.tex_string,
434+
self.parser.specified_substrings,
435+
self.alignment,
436+
self.tex_environment,
437+
self.use_plain_tex
438+
)
443439

444-
if hash_val in TEX_HASH_TO_MOB_MAP:
445-
return TEX_HASH_TO_MOB_MAP[hash_val]
440+
def get_file_path(self):
441+
return self._get_file_path(self.use_plain_tex)
446442

447-
if not self.use_plain_tex:
448-
with display_during_execution(f"Writing \"{self.tex_string}\""):
449-
labelled_svg_glyphs = self.tex_content_to_glyphs(
450-
labelled_tex_content
451-
)
452-
glyph_labels = [
453-
self.color_to_label(labelled_glyph.get_fill_color())
454-
for labelled_glyph in labelled_svg_glyphs
455-
]
456-
mob = self.build_mobject(labelled_svg_glyphs, glyph_labels)
457-
TEX_HASH_TO_MOB_MAP[hash_val] = mob
458-
return mob
443+
def _get_file_path(self, use_plain_tex):
444+
if use_plain_tex:
445+
tex_string = self.tex_string
446+
else:
447+
tex_string = self.parser.get_labelled_tex_string()
459448

449+
full_tex = self.get_tex_file_body(tex_string)
460450
with display_during_execution(f"Writing \"{self.tex_string}\""):
461-
labelled_svg_glyphs = self.tex_content_to_glyphs(
462-
labelled_tex_content
463-
)
464-
tex_content = self.get_tex_file_content(self.tex_string)
465-
svg_glyphs = self.tex_content_to_glyphs(tex_content)
466-
glyph_labels = [
467-
self.color_to_label(labelled_glyph.get_fill_color())
468-
for labelled_glyph in labelled_svg_glyphs
469-
]
470-
mob = self.build_mobject(svg_glyphs, glyph_labels)
471-
TEX_HASH_TO_MOB_MAP[hash_val] = mob
472-
return mob
451+
file_path = self.tex_to_svg_file_path(full_tex)
452+
return file_path
473453

474-
def get_tex_file_content(self, tex_string):
454+
def get_tex_file_body(self, tex_string):
475455
if self.tex_environment:
476456
tex_string = "\n".join([
477457
f"\\begin{{{self.tex_environment}}}",
@@ -480,17 +460,38 @@ def get_tex_file_content(self, tex_string):
480460
])
481461
if self.alignment:
482462
tex_string = "\n".join([self.alignment, tex_string])
483-
return tex_string
484-
485-
@staticmethod
486-
def tex_content_to_glyphs(tex_content):
463+
487464
tex_config = get_tex_config()
488-
full_tex = tex_config["tex_body"].replace(
465+
return tex_config["tex_body"].replace(
489466
tex_config["text_to_replace"],
490-
tex_content
467+
tex_string
491468
)
492-
filename = tex_to_svg_file(full_tex)
493-
return _TexSVG(filename)
469+
470+
@staticmethod
471+
def tex_to_svg_file_path(tex_file_content):
472+
return tex_to_svg_file(tex_file_content)
473+
474+
def generate_mobject(self):
475+
super().generate_mobject()
476+
477+
if not self.use_plain_tex:
478+
labelled_svg_glyphs = self
479+
else:
480+
file_path = self._get_file_path(use_plain_tex=False)
481+
labelled_svg_glyphs = _TexSVG(file_path)
482+
483+
glyph_labels = [
484+
self.color_to_label(labelled_glyph.get_fill_color())
485+
for labelled_glyph in labelled_svg_glyphs
486+
]
487+
mob = self.build_mobject(self, glyph_labels)
488+
self.set_submobjects(mob.submobjects)
489+
490+
@staticmethod
491+
def color_to_label(color):
492+
r, g, b = color_to_int_rgb(color)
493+
rg = r * 256 + g
494+
return rg * 256 + b
494495

495496
def build_mobject(self, svg_glyphs, glyph_labels):
496497
if not svg_glyphs:
@@ -514,11 +515,11 @@ def build_mobject(self, svg_glyphs, glyph_labels):
514515
submob_labels.append(current_glyph_label)
515516
submobjects.append(submobject)
516517

517-
indices = self.__parser.get_sorted_submob_indices(submob_labels)
518+
indices = self.parser.get_sorted_submob_indices(submob_labels)
518519
rearranged_submobjects = [submobjects[index] for index in indices]
519520
rearranged_labels = [submob_labels[index] for index in indices]
520521

521-
submob_tex_strings = self.__parser.get_submob_tex_strings(
522+
submob_tex_strings = self.parser.get_submob_tex_strings(
522523
rearranged_labels
523524
)
524525
for submob, label, submob_tex in zip(
@@ -531,14 +532,14 @@ def build_mobject(self, svg_glyphs, glyph_labels):
531532
return VGroup(*rearranged_submobjects)
532533

533534
def get_part_by_tex_spans(self, tex_spans):
534-
labels = self.__parser.get_containing_labels_by_tex_spans(tex_spans)
535+
labels = self.parser.get_containing_labels_by_tex_spans(tex_spans)
535536
return VGroup(*filter(
536537
lambda submob: submob.submob_label in labels,
537538
self.submobjects
538539
))
539540

540541
def get_part_by_custom_span(self, custom_span):
541-
tex_spans = self.__parser.find_span_components_of_custom_span(
542+
tex_spans = self.parser.find_span_components_of_custom_span(
542543
custom_span
543544
)
544545
if tex_spans is None:
@@ -590,10 +591,10 @@ def get_submob_tex(self):
590591
]
591592

592593
def get_specified_substrings(self):
593-
return self.__parser.get_specified_substrings()
594+
return self.parser.get_specified_substrings()
594595

595596
def get_isolated_substrings(self):
596-
return self.__parser.get_isolated_substrings()
597+
return self.parser.get_isolated_substrings()
597598

598599

599600
class MTexText(MTex):

0 commit comments

Comments
 (0)