Skip to content

Commit 06405d5

Browse files
committed
Merge branch 'master' of github.com:3b1b/manim into video-work
2 parents 46e356e + 97ca42d commit 06405d5

File tree

11 files changed

+281
-232
lines changed

11 files changed

+281
-232
lines changed

docs/source/development/changelog.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,45 @@
11
Changelog
22
=========
33

4+
Unreleased
5+
----------
6+
7+
Fixed bugs
8+
^^^^^^^^^^
9+
- `#1740 <https://github.com/3b1b/manim/pull/1740>`__: Bug fix for the case of calling ``Write`` on a null object
10+
11+
12+
New Features
13+
^^^^^^^^^^^^
14+
- `#1725 <https://github.com/3b1b/manim/pull/1725>`__: Added ``TransformMatchingMTex``
15+
- `#1727 <https://github.com/3b1b/manim/pull/1727>`__: Added ``ImplicitFunction``
16+
- `#1731 <https://github.com/3b1b/manim/pull/1731>`__: Added ``Polyline``
17+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/a64259158538eae6043566aaf3d3329ff4ac394b>`__: Allowed ``Mobject.set_points`` to take in an empty list, and added ``Mobject.add_point``
18+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/33d2894c167c577a15fdadbaf26488ff1f5bff87>`__: Added ``Scene.refresh_locked_data``
19+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/9a9cc8bdacb7541b7cd4a52ad705abc21f3e27fe>`__: Added presenter mode to scenes with ``-p`` option
20+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/9df12fcb7d8360e51cd7021d6877ca1a5c31835e>`__: Allowed for an embed by hitting ``e`` during interaction
21+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/2798d15591a0375ae6bb9135473e6f5328267323>`__: Added ``Mobject.set_min_width/height/depth``
22+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/29a4d3e82ba94c007c996b2d1d0f923941452698>`__: Allowed ``Mobject.match_coord/x/y/z`` to take in a point
23+
24+
25+
Refactor
26+
^^^^^^^^
27+
- `#1725 <https://github.com/3b1b/manim/pull/1725>`__: Refactored ``MTex``
28+
- `#1731 <https://github.com/3b1b/manim/pull/1731>`__: Refactored ``SVGMobject`` with svgelements
29+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/2488b9e866fb1ecb842a27dd9f4956ec167e3dee>`__: Made sure ``ParametricCurve`` has at least one point
30+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/6c6d387a210756c38feca7d34838aa9ac99bb58a>`__: Set default to no tips on ``Axes``
31+
- `#1739 <https://github.com/3b1b/manim/pull/1739/commits/58e06e8f6b7c5059ff315d51fd0018fec5cfbb05>`__: Stopped displaying when writing tex string is happening
32+
33+
34+
Dependencies
35+
^^^^^^^^^^^^
36+
- `#1727 <https://github.com/3b1b/manim/pull/1727>`__: Added dependency on ``isosurfaces``
37+
- `#1728 <https://github.com/3b1b/manim/pull/1728>`__: Removed dependency on ``argparse`` since it's a built-in module
38+
- `#1728 <https://github.com/3b1b/manim/pull/1728>`__: Removed dependency on ``pyreadline``
39+
- `#1731 <https://github.com/3b1b/manim/pull/1731>`__: Removed dependency on ``cssselect2``
40+
- `#1731 <https://github.com/3b1b/manim/pull/1731>`__: Added dependency on ``svgelements``
41+
42+
443
v1.4.1
544
------
645

docs/source/getting_started/configuration.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ flag abbr function
4343
``--hd`` Render at a 1080p quality
4444
``--uhd`` Render at a 4k quality
4545
``--full_screen`` ``-f`` Show window in full screen
46+
``--presenter_mode`` ``-p`` Scene will stay paused during wait calls until space bar or right arrow is hit, like a slide show
4647
``--save_pngs`` ``-g`` Save each frame as a png
4748
``--save_as_gif`` ``-i`` Save the video as gif
4849
``--transparent`` ``-t`` Render to a movie file with an alpha channel
@@ -58,7 +59,7 @@ flag abbr function
5859
``--frame_rate FRAME_RATE`` Frame rate, as an integer
5960
``--color COLOR`` ``-c`` Background color
6061
``--leave_progress_bars`` Leave progress bars displayed in terminal
61-
``--video_dir VIDEO_DIR`` directory to write video
62+
``--video_dir VIDEO_DIR`` Directory to write video
6263
``--config_file CONFIG_FILE`` Path to the custom configuration file
6364
========================================================== ====== =================================================================================================================================================================================================
6465

manimlib/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def parse_cli():
2323
module_location.add_argument(
2424
"file",
2525
nargs="?",
26-
help="path to file holding the python code for the scene",
26+
help="Path to file holding the python code for the scene",
2727
)
2828
parser.add_argument(
2929
"scene_names",
@@ -68,7 +68,7 @@ def parse_cli():
6868
parser.add_argument(
6969
"-p", "--presenter_mode",
7070
action="store_true",
71-
help="scene will stay paused during wait calls until "
71+
help="Scene will stay paused during wait calls until "
7272
"space bar or right arrow is hit, like a slide show"
7373
)
7474
parser.add_argument(

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)