26
26
import itertools as it
27
27
import operator as op
28
28
import re
29
- from collections .abc import Iterable , Sequence
29
+ from collections .abc import Iterable
30
30
from functools import reduce
31
31
from textwrap import dedent
32
32
from typing import Any
33
33
34
- from typing_extensions import Self
35
-
36
34
from manim import config , logger
37
35
from manim .constants import *
38
36
from manim .mobject .geometry .line import Line
41
39
from manim .utils .tex import TexTemplate
42
40
from manim .utils .tex_file_writing import tex_to_svg_file
43
41
42
+ tex_string_to_mob_map = {}
43
+
44
44
45
45
class SingleStringMathTex (SVGMobject ):
46
46
"""Elementary building block for rendering text with LaTeX.
@@ -74,8 +74,9 @@ def __init__(
74
74
self .tex_environment = tex_environment
75
75
if tex_template is None :
76
76
tex_template = config ["tex_template" ]
77
- self .tex_template : TexTemplate = tex_template
77
+ self .tex_template = tex_template
78
78
79
+ assert isinstance (tex_string , str )
79
80
self .tex_string = tex_string
80
81
file_name = tex_to_svg_file (
81
82
self ._get_modified_expression (tex_string ),
@@ -105,7 +106,7 @@ def __init__(
105
106
if self .organize_left_to_right :
106
107
self ._organize_submobjects_left_to_right ()
107
108
108
- def __repr__ (self ) -> str :
109
+ def __repr__ (self ):
109
110
return f"{ type (self ).__name__ } ({ repr (self .tex_string )} )"
110
111
111
112
@property
@@ -114,7 +115,7 @@ def font_size(self) -> float:
114
115
return self .height / self .initial_height / SCALE_FACTOR_PER_FONT_POINT
115
116
116
117
@font_size .setter
117
- def font_size (self , font_val : float ) -> None :
118
+ def font_size (self , font_val : float ):
118
119
if font_val <= 0 :
119
120
raise ValueError ("font_size must be greater than 0." )
120
121
elif self .height > 0 :
@@ -125,13 +126,13 @@ def font_size(self, font_val: float) -> None:
125
126
# font_size does not depend on current size.
126
127
self .scale (font_val / self .font_size )
127
128
128
- def _get_modified_expression (self , tex_string : str ) -> str :
129
+ def _get_modified_expression (self , tex_string ) :
129
130
result = tex_string
130
131
result = result .strip ()
131
132
result = self ._modify_special_strings (result )
132
133
return result
133
134
134
- def _modify_special_strings (self , tex : str ) -> str :
135
+ def _modify_special_strings (self , tex ) :
135
136
tex = tex .strip ()
136
137
should_add_filler = reduce (
137
138
op .or_ ,
@@ -184,7 +185,7 @@ def _modify_special_strings(self, tex: str) -> str:
184
185
tex = ""
185
186
return tex
186
187
187
- def _remove_stray_braces (self , tex : str ) -> str :
188
+ def _remove_stray_braces (self , tex ) :
188
189
r"""
189
190
Makes :class:`~.MathTex` resilient to unmatched braces.
190
191
@@ -202,14 +203,14 @@ def _remove_stray_braces(self, tex: str) -> str:
202
203
num_rights += 1
203
204
return tex
204
205
205
- def _organize_submobjects_left_to_right (self ) -> Self :
206
+ def _organize_submobjects_left_to_right (self ):
206
207
self .sort (lambda p : p [0 ])
207
208
return self
208
209
209
- def get_tex_string (self ) -> str :
210
+ def get_tex_string (self ):
210
211
return self .tex_string
211
212
212
- def init_colors (self , propagate_colors : bool = True ) -> Self :
213
+ def init_colors (self , propagate_colors = True ):
213
214
for submobject in self .submobjects :
214
215
# needed to preserve original (non-black)
215
216
# TeX colors of individual submobjects
@@ -220,7 +221,6 @@ def init_colors(self, propagate_colors: bool = True) -> Self:
220
221
submobject .init_colors ()
221
222
elif config .renderer == RendererType .CAIRO :
222
223
submobject .init_colors (propagate_colors = propagate_colors )
223
- return self
224
224
225
225
226
226
class MathTex (SingleStringMathTex ):
@@ -256,22 +256,21 @@ def construct(self):
256
256
257
257
def __init__ (
258
258
self ,
259
- * tex_strings : str ,
259
+ * tex_strings ,
260
260
arg_separator : str = " " ,
261
261
substrings_to_isolate : Iterable [str ] | None = None ,
262
- tex_to_color_map : dict [str , ManimColor ] | None = None ,
262
+ tex_to_color_map : dict [str , ManimColor ] = None ,
263
263
tex_environment : str = "align*" ,
264
- ** kwargs : Any ,
264
+ ** kwargs ,
265
265
):
266
266
self .tex_template = kwargs .pop ("tex_template" , config ["tex_template" ])
267
267
self .arg_separator = arg_separator
268
268
self .substrings_to_isolate = (
269
269
[] if substrings_to_isolate is None else substrings_to_isolate
270
270
)
271
- if tex_to_color_map is None :
272
- self .tex_to_color_map : dict [str , ManimColor ] = {}
273
- else :
274
- self .tex_to_color_map = tex_to_color_map
271
+ self .tex_to_color_map = tex_to_color_map
272
+ if self .tex_to_color_map is None :
273
+ self .tex_to_color_map = {}
275
274
self .tex_environment = tex_environment
276
275
self .brace_notation_split_occurred = False
277
276
self .tex_strings = self ._break_up_tex_strings (tex_strings )
@@ -303,14 +302,12 @@ def __init__(
303
302
if self .organize_left_to_right :
304
303
self ._organize_submobjects_left_to_right ()
305
304
306
- def _break_up_tex_strings (self , tex_strings : Sequence [ str ]) -> list [ str ] :
305
+ def _break_up_tex_strings (self , tex_strings ) :
307
306
# Separate out anything surrounded in double braces
308
307
pre_split_length = len (tex_strings )
309
- tex_strings_brace_splitted = [
310
- re .split ("{{(.*?)}}" , str (t )) for t in tex_strings
311
- ]
312
- tex_strings_combined = sum (tex_strings_brace_splitted , [])
313
- if len (tex_strings_combined ) > pre_split_length :
308
+ tex_strings = [re .split ("{{(.*?)}}" , str (t )) for t in tex_strings ]
309
+ tex_strings = sum (tex_strings , [])
310
+ if len (tex_strings ) > pre_split_length :
314
311
self .brace_notation_split_occurred = True
315
312
316
313
# Separate out any strings specified in the isolate
@@ -328,19 +325,19 @@ def _break_up_tex_strings(self, tex_strings: Sequence[str]) -> list[str]:
328
325
pattern = "|" .join (patterns )
329
326
if pattern :
330
327
pieces = []
331
- for s in tex_strings_combined :
328
+ for s in tex_strings :
332
329
pieces .extend (re .split (pattern , s ))
333
330
else :
334
- pieces = tex_strings_combined
331
+ pieces = tex_strings
335
332
return [p for p in pieces if p ]
336
333
337
- def _break_up_by_substrings (self ) -> Self :
334
+ def _break_up_by_substrings (self ):
338
335
"""
339
336
Reorganize existing submobjects one layer
340
337
deeper based on the structure of tex_strings (as a list
341
338
of tex_strings)
342
339
"""
343
- new_submobjects : list [ VMobject ] = []
340
+ new_submobjects = []
344
341
curr_index = 0
345
342
for tex_string in self .tex_strings :
346
343
sub_tex_mob = SingleStringMathTex (
@@ -362,10 +359,8 @@ def _break_up_by_substrings(self) -> Self:
362
359
self .submobjects = new_submobjects
363
360
return self
364
361
365
- def get_parts_by_tex (
366
- self , tex : str , substring : bool = True , case_sensitive : bool = True
367
- ) -> VGroup :
368
- def test (tex1 : str , tex2 : str ) -> bool :
362
+ def get_parts_by_tex (self , tex , substring = True , case_sensitive = True ):
363
+ def test (tex1 , tex2 ):
369
364
if not case_sensitive :
370
365
tex1 = tex1 .lower ()
371
366
tex2 = tex2 .lower ()
@@ -376,25 +371,19 @@ def test(tex1: str, tex2: str) -> bool:
376
371
377
372
return VGroup (* (m for m in self .submobjects if test (tex , m .get_tex_string ())))
378
373
379
- def get_part_by_tex (self , tex : str , ** kwargs : Any ) -> MathTex | None :
374
+ def get_part_by_tex (self , tex , ** kwargs ) :
380
375
all_parts = self .get_parts_by_tex (tex , ** kwargs )
381
376
return all_parts [0 ] if all_parts else None
382
377
383
- def set_color_by_tex (
384
- self , tex : str , color : ParsableManimColor , ** kwargs : Any
385
- ) -> Self :
378
+ def set_color_by_tex (self , tex , color , ** kwargs ):
386
379
parts_to_color = self .get_parts_by_tex (tex , ** kwargs )
387
380
for part in parts_to_color :
388
381
part .set_color (color )
389
382
return self
390
383
391
384
def set_opacity_by_tex (
392
- self ,
393
- tex : str ,
394
- opacity : float = 0.5 ,
395
- remaining_opacity : float | None = None ,
396
- ** kwargs : Any ,
397
- ) -> Self :
385
+ self , tex : str , opacity : float = 0.5 , remaining_opacity : float = None , ** kwargs
386
+ ):
398
387
"""
399
388
Sets the opacity of the tex specified. If 'remaining_opacity' is specified,
400
389
then the remaining tex will be set to that opacity.
@@ -415,9 +404,7 @@ def set_opacity_by_tex(
415
404
part .set_opacity (opacity )
416
405
return self
417
406
418
- def set_color_by_tex_to_color_map (
419
- self , texs_to_color_map : dict [str , ManimColor ], ** kwargs : Any
420
- ) -> Self :
407
+ def set_color_by_tex_to_color_map (self , texs_to_color_map , ** kwargs ):
421
408
for texs , color in list (texs_to_color_map .items ()):
422
409
try :
423
410
# If the given key behaves like tex_strings
@@ -429,19 +416,17 @@ def set_color_by_tex_to_color_map(
429
416
self .set_color_by_tex (tex , color , ** kwargs )
430
417
return self
431
418
432
- def index_of_part (self , part : MathTex ) -> int :
419
+ def index_of_part (self , part ) :
433
420
split_self = self .split ()
434
421
if part not in split_self :
435
422
raise ValueError ("Trying to get index of part not in MathTex" )
436
423
return split_self .index (part )
437
424
438
- def index_of_part_by_tex (self , tex : str , ** kwargs : Any ) -> int :
425
+ def index_of_part_by_tex (self , tex , ** kwargs ) :
439
426
part = self .get_part_by_tex (tex , ** kwargs )
440
- if part is None :
441
- return - 1
442
427
return self .index_of_part (part )
443
428
444
- def sort_alphabetically (self ) -> None :
429
+ def sort_alphabetically (self ):
445
430
self .submobjects .sort (key = lambda m : m .get_tex_string ())
446
431
447
432
@@ -497,11 +482,11 @@ def construct(self):
497
482
498
483
def __init__ (
499
484
self ,
500
- * items : str ,
501
- buff : float = MED_LARGE_BUFF ,
502
- dot_scale_factor : float = 2 ,
503
- tex_environment : str = "" ,
504
- ** kwargs : Any ,
485
+ * items ,
486
+ buff = MED_LARGE_BUFF ,
487
+ dot_scale_factor = 2 ,
488
+ tex_environment = None ,
489
+ ** kwargs ,
505
490
):
506
491
self .buff = buff
507
492
self .dot_scale_factor = dot_scale_factor
@@ -516,12 +501,12 @@ def __init__(
516
501
part .add_to_back (dot )
517
502
self .arrange (DOWN , aligned_edge = LEFT , buff = self .buff )
518
503
519
- def fade_all_but (self , index_or_string : int | str , opacity : float = 0.5 ) -> None :
504
+ def fade_all_but (self , index_or_string , opacity = 0.5 ):
520
505
arg = index_or_string
521
506
if isinstance (arg , str ):
522
507
part = self .get_part_by_tex (arg )
523
508
elif isinstance (arg , int ):
524
- part = self .submobjects [arg ] # type: ignore[assignment]
509
+ part = self .submobjects [arg ]
525
510
else :
526
511
raise TypeError (f"Expected int or string, got { arg } " )
527
512
for other_part in self .submobjects :
@@ -551,11 +536,11 @@ def construct(self):
551
536
552
537
def __init__ (
553
538
self ,
554
- * text_parts : str ,
555
- include_underline : bool = True ,
556
- match_underline_width_to_text : bool = False ,
557
- underline_buff : float = MED_SMALL_BUFF ,
558
- ** kwargs : Any ,
539
+ * text_parts ,
540
+ include_underline = True ,
541
+ match_underline_width_to_text = False ,
542
+ underline_buff = MED_SMALL_BUFF ,
543
+ ** kwargs ,
559
544
):
560
545
self .include_underline = include_underline
561
546
self .match_underline_width_to_text = match_underline_width_to_text
0 commit comments