manim 0.17.3__py3-none-any.whl → 0.18.0.post0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of manim might be problematic. Click here for more details.

Files changed (84) hide show
  1. manim/__init__.py +1 -0
  2. manim/__main__.py +2 -0
  3. manim/_config/__init__.py +0 -1
  4. manim/_config/logger_utils.py +1 -0
  5. manim/_config/utils.py +14 -5
  6. manim/animation/changing.py +9 -5
  7. manim/animation/creation.py +8 -3
  8. manim/animation/indication.py +4 -4
  9. manim/animation/speedmodifier.py +2 -4
  10. manim/animation/updaters/mobject_update_utils.py +134 -16
  11. manim/camera/camera.py +31 -17
  12. manim/cli/checkhealth/__init__.py +0 -0
  13. manim/cli/checkhealth/checks.py +173 -0
  14. manim/cli/checkhealth/commands.py +81 -0
  15. manim/cli/render/global_options.py +6 -0
  16. manim/constants.py +58 -54
  17. manim/mobject/geometry/__init__.py +1 -0
  18. manim/mobject/geometry/arc.py +126 -91
  19. manim/mobject/geometry/boolean_ops.py +6 -10
  20. manim/mobject/geometry/labeled.py +155 -0
  21. manim/mobject/geometry/line.py +66 -50
  22. manim/mobject/geometry/polygram.py +23 -15
  23. manim/mobject/geometry/shape_matchers.py +24 -15
  24. manim/mobject/geometry/tips.py +62 -40
  25. manim/mobject/graph.py +3 -4
  26. manim/mobject/graphing/coordinate_systems.py +190 -139
  27. manim/mobject/graphing/number_line.py +5 -2
  28. manim/mobject/graphing/probability.py +4 -3
  29. manim/mobject/graphing/scale.py +7 -7
  30. manim/mobject/logo.py +108 -22
  31. manim/mobject/matrix.py +33 -37
  32. manim/mobject/mobject.py +327 -260
  33. manim/mobject/opengl/opengl_image_mobject.py +1 -1
  34. manim/mobject/opengl/opengl_mobject.py +18 -12
  35. manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
  36. manim/mobject/opengl/opengl_surface.py +1 -1
  37. manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
  38. manim/mobject/svg/brace.py +3 -1
  39. manim/mobject/svg/svg_mobject.py +9 -11
  40. manim/mobject/table.py +50 -54
  41. manim/mobject/text/numbers.py +48 -6
  42. manim/mobject/text/tex_mobject.py +8 -12
  43. manim/mobject/text/text_mobject.py +32 -24
  44. manim/mobject/three_d/three_d_utils.py +13 -8
  45. manim/mobject/three_d/three_dimensions.py +61 -43
  46. manim/mobject/types/image_mobject.py +5 -4
  47. manim/mobject/types/point_cloud_mobject.py +8 -6
  48. manim/mobject/types/vectorized_mobject.py +385 -258
  49. manim/mobject/vector_field.py +19 -11
  50. manim/plugins/import_plugins.py +1 -1
  51. manim/plugins/plugins_flags.py +1 -6
  52. manim/renderer/shader.py +2 -2
  53. manim/scene/scene.py +15 -7
  54. manim/scene/scene_file_writer.py +1 -2
  55. manim/scene/three_d_scene.py +1 -1
  56. manim/scene/vector_space_scene.py +17 -7
  57. manim/typing.py +133 -0
  58. manim/utils/bezier.py +267 -83
  59. manim/utils/color/AS2700.py +234 -0
  60. manim/utils/color/BS381.py +315 -0
  61. manim/utils/color/X11.py +530 -0
  62. manim/utils/color/XKCD.py +949 -0
  63. manim/utils/color/__init__.py +58 -0
  64. manim/utils/color/core.py +1036 -0
  65. manim/utils/color/manim_colors.py +220 -0
  66. manim/utils/docbuild/autocolor_directive.py +92 -0
  67. manim/utils/docbuild/manim_directive.py +40 -6
  68. manim/utils/file_ops.py +1 -1
  69. manim/utils/hashing.py +1 -1
  70. manim/utils/iterables.py +1 -1
  71. manim/utils/rate_functions.py +33 -0
  72. manim/utils/simple_functions.py +0 -18
  73. manim/utils/space_ops.py +55 -42
  74. manim/utils/testing/frames_comparison.py +9 -0
  75. manim/utils/tex.py +2 -0
  76. manim/utils/tex_file_writing.py +29 -2
  77. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
  78. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
  79. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
  80. manim/communitycolors.py +0 -9
  81. manim/utils/color.py +0 -552
  82. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
  83. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
  84. {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/entry_points.txt +0 -0
@@ -29,7 +29,7 @@ class OpenGLImageMobject(OpenGLTexturedSurface):
29
29
  ):
30
30
  self.image = filename_or_array
31
31
  self.resampling_algorithm = resampling_algorithm
32
- if type(filename_or_array) == np.ndarray:
32
+ if isinstance(filename_or_array, np.ndarray):
33
33
  self.size = self.image.shape[1::-1]
34
34
  elif isinstance(filename_or_array, (str, Path)):
35
35
  path = get_full_raster_image_path(filename_or_array)
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import copy
4
+ import inspect
4
5
  import itertools as it
5
6
  import random
6
7
  import sys
@@ -10,13 +11,19 @@ from typing import Iterable, Sequence
10
11
 
11
12
  import moderngl
12
13
  import numpy as np
13
- from colour import Color
14
14
 
15
15
  from manim import config, logger
16
16
  from manim.constants import *
17
+ from manim.renderer.shader_wrapper import get_colormap_code
17
18
  from manim.utils.bezier import integer_interpolate, interpolate
18
- from manim.utils.color import *
19
- from manim.utils.color import Colors
19
+ from manim.utils.color import (
20
+ WHITE,
21
+ ManimColor,
22
+ ParsableManimColor,
23
+ color_gradient,
24
+ color_to_rgb,
25
+ rgb_to_hex,
26
+ )
20
27
  from manim.utils.config_ops import _Data, _Uniforms
21
28
 
22
29
  # from ..utils.iterables import batch_by_property
@@ -31,7 +38,6 @@ from manim.utils.iterables import (
31
38
  uniq_chain,
32
39
  )
33
40
  from manim.utils.paths import straight_path
34
- from manim.utils.simple_functions import get_parameters
35
41
  from manim.utils.space_ops import (
36
42
  angle_between_vectors,
37
43
  normalize,
@@ -146,7 +152,7 @@ class OpenGLMobject:
146
152
  self.init_updaters()
147
153
  # self.init_event_listners()
148
154
  self.init_points()
149
- self.color = Color(color) if color else None
155
+ self.color = ManimColor.parse(color)
150
156
  self.init_colors()
151
157
 
152
158
  self.shader_indices = None
@@ -203,10 +209,10 @@ class OpenGLMobject:
203
209
  >>> from manim import Square, GREEN
204
210
  >>> Square.set_default(color=GREEN, fill_opacity=0.25)
205
211
  >>> s = Square(); s.color, s.fill_opacity
206
- (<Color #83c167>, 0.25)
212
+ (ManimColor('#83C167'), 0.25)
207
213
  >>> Square.set_default()
208
214
  >>> s = Square(); s.color, s.fill_opacity
209
- (<Color white>, 0.0)
215
+ (ManimColor('#FFFFFF'), 0.0)
210
216
 
211
217
  .. manim:: ChangedDefaultTextcolor
212
218
  :save_last_frame:
@@ -1377,7 +1383,7 @@ class OpenGLMobject:
1377
1383
  return list(it.chain(*(sm.get_updaters() for sm in self.get_family())))
1378
1384
 
1379
1385
  def add_updater(self, update_function, index=None, call_updater=False):
1380
- if "dt" in get_parameters(update_function):
1386
+ if "dt" in inspect.signature(update_function).parameters:
1381
1387
  updater_list = self.time_based_updaters
1382
1388
  else:
1383
1389
  updater_list = self.non_time_updaters
@@ -1971,12 +1977,12 @@ class OpenGLMobject:
1971
1977
  for mob in self.get_family(recurse):
1972
1978
  mob.data[name] = rgbas.copy()
1973
1979
 
1974
- def set_color(self, color, opacity=None, recurse=True):
1980
+ def set_color(self, color: ParsableManimColor | None, opacity=None, recurse=True):
1975
1981
  self.set_rgba_array(color, opacity, recurse=False)
1976
1982
  # Recurse to submobjects differently from how set_rgba_array
1977
1983
  # in case they implement set_color differently
1978
1984
  if color is not None:
1979
- self.color = Color(color)
1985
+ self.color: ManimColor = ManimColor.parse(color)
1980
1986
  if opacity is not None:
1981
1987
  self.opacity = opacity
1982
1988
  if recurse:
@@ -2037,7 +2043,7 @@ class OpenGLMobject:
2037
2043
  # Background rectangle
2038
2044
 
2039
2045
  def add_background_rectangle(
2040
- self, color: Colors | None = None, opacity: float = 0.75, **kwargs
2046
+ self, color: ParsableManimColor | None = None, opacity: float = 0.75, **kwargs
2041
2047
  ):
2042
2048
  # TODO, this does not behave well when the mobject has points,
2043
2049
  # since it gets displayed on top
@@ -2725,7 +2731,7 @@ class OpenGLMobject:
2725
2731
 
2726
2732
  class OpenGLGroup(OpenGLMobject):
2727
2733
  def __init__(self, *mobjects, **kwargs):
2728
- if not all([isinstance(m, OpenGLMobject) for m in mobjects]):
2734
+ if not all(isinstance(m, OpenGLMobject) for m in mobjects):
2729
2735
  raise Exception("All submobjects must be of type OpenGLMobject")
2730
2736
  super().__init__(**kwargs)
2731
2737
  self.add(*mobjects)
@@ -162,7 +162,7 @@ class OpenGLPMobject(OpenGLMobject):
162
162
 
163
163
  class OpenGLPGroup(OpenGLPMobject):
164
164
  def __init__(self, *pmobs, **kwargs):
165
- if not all([isinstance(m, OpenGLPMobject) for m in pmobs]):
165
+ if not all(isinstance(m, OpenGLPMobject) for m in pmobs):
166
166
  raise Exception("All submobjects must be of type OpenglPMObject")
167
167
  super().__init__(**kwargs)
168
168
  self.add(*pmobs)
@@ -380,7 +380,7 @@ class OpenGLTexturedSurface(OpenGLSurface):
380
380
 
381
381
  if not isinstance(uv_surface, OpenGLSurface):
382
382
  raise Exception("uv_surface must be of type OpenGLSurface")
383
- if type(image_file) == np.ndarray:
383
+ if isinstance(image_file, np.ndarray):
384
384
  image_file = change_to_rgba_array(image_file)
385
385
 
386
386
  # Set texture information
@@ -3,11 +3,10 @@ from __future__ import annotations
3
3
  import itertools as it
4
4
  import operator as op
5
5
  from functools import reduce, wraps
6
- from typing import Callable, Iterable, Optional, Sequence
6
+ from typing import Callable, Iterable, Sequence
7
7
 
8
8
  import moderngl
9
9
  import numpy as np
10
- from colour import Color
11
10
 
12
11
  from manim import config
13
12
  from manim.constants import *
@@ -23,7 +22,7 @@ from manim.utils.bezier import (
23
22
  proportions_along_bezier_curve_for_point,
24
23
  quadratic_bezier_remap,
25
24
  )
26
- from manim.utils.color import *
25
+ from manim.utils.color import BLACK, WHITE, ManimColor, ParsableManimColor
27
26
  from manim.utils.config_ops import _Data
28
27
  from manim.utils.iterables import listify, make_even, resize_with_interpolation
29
28
  from manim.utils.space_ops import (
@@ -81,9 +80,9 @@ class OpenGLVMobject(OpenGLMobject):
81
80
 
82
81
  def __init__(
83
82
  self,
84
- fill_color: Color | None = None,
83
+ fill_color: ParsableManimColor | None = None,
85
84
  fill_opacity: float = 0.0,
86
- stroke_color: Color | None = None,
85
+ stroke_color: ParsableManimColor | None = None,
87
86
  stroke_opacity: float = 1.0,
88
87
  stroke_width: float = DEFAULT_STROKE_WIDTH,
89
88
  draw_stroke_behind_fill: bool = False,
@@ -137,6 +136,7 @@ class OpenGLVMobject(OpenGLMobject):
137
136
  self.needs_new_triangulation = True
138
137
  self.triangulation = np.zeros(0, dtype="i4")
139
138
  self.orientation = 1
139
+
140
140
  self.fill_data = None
141
141
  self.stroke_data = None
142
142
  self.fill_shader_wrapper = None
@@ -146,10 +146,10 @@ class OpenGLVMobject(OpenGLMobject):
146
146
  super().__init__(**kwargs)
147
147
  self.refresh_unit_normal()
148
148
 
149
- if fill_color:
150
- self.fill_color = Color(fill_color)
151
- if stroke_color:
152
- self.stroke_color = Color(stroke_color)
149
+ if fill_color is not None:
150
+ self.fill_color = ManimColor.parse(fill_color)
151
+ if stroke_color is not None:
152
+ self.stroke_color = ManimColor.parse(stroke_color)
153
153
 
154
154
  def get_group_class(self):
155
155
  return OpenGLVGroup
@@ -184,7 +184,7 @@ class OpenGLVMobject(OpenGLMobject):
184
184
 
185
185
  def set_fill(
186
186
  self,
187
- color: Color | None = None,
187
+ color: ParsableManimColor | None = None,
188
188
  opacity: float | None = None,
189
189
  recurse: bool = True,
190
190
  ) -> OpenGLVMobject:
@@ -350,14 +350,15 @@ class OpenGLVMobject(OpenGLMobject):
350
350
  super().fade(darkness, recurse)
351
351
  return self
352
352
 
353
+ # Todo im not quite sure why we are doing this
353
354
  def get_fill_colors(self):
354
- return [Color(rgb_to_hex(rgba[:3])) for rgba in self.fill_rgba]
355
+ return [ManimColor.from_rgb(rgba[:3]) for rgba in self.fill_rgba]
355
356
 
356
357
  def get_fill_opacities(self):
357
358
  return self.fill_rgba[:, 3]
358
359
 
359
360
  def get_stroke_colors(self):
360
- return [Color(rgb_to_hex(rgba[:3])) for rgba in self.stroke_rgba]
361
+ return [ManimColor.from_rgb(rgba[:3]) for rgba in self.stroke_rgba]
361
362
 
362
363
  def get_stroke_opacities(self):
363
364
  return self.stroke_rgba[:, 3]
@@ -1283,14 +1284,17 @@ class OpenGLVMobject(OpenGLMobject):
1283
1284
  for _ in range(-diff):
1284
1285
  ipc[np.argmax(ipc)] -= 1
1285
1286
 
1286
- new_points = []
1287
+ new_length = sum(x + 1 for x in ipc)
1288
+ new_points = np.empty((new_length, nppc, 3))
1289
+ i = 0
1287
1290
  for group, n_inserts in zip(bezier_groups, ipc):
1288
1291
  # What was once a single quadratic curve defined
1289
1292
  # by "group" will now be broken into n_inserts + 1
1290
1293
  # smaller quadratic curves
1291
1294
  alphas = np.linspace(0, 1, n_inserts + 2)
1292
1295
  for a1, a2 in zip(alphas, alphas[1:]):
1293
- new_points += partial_quadratic_bezier_points(group, a1, a2)
1296
+ new_points[i] = partial_quadratic_bezier_points(group, a1, a2)
1297
+ i = i + 1
1294
1298
  return np.vstack(new_points)
1295
1299
 
1296
1300
  def interpolate(self, mobject1, mobject2, alpha, *args, **kwargs):
@@ -1301,7 +1305,7 @@ class OpenGLVMobject(OpenGLMobject):
1301
1305
  if self.has_fill():
1302
1306
  tri1 = mobject1.get_triangulation()
1303
1307
  tri2 = mobject2.get_triangulation()
1304
- if len(tri1) != len(tri1) or not np.all(tri1 == tri2):
1308
+ if len(tri1) != len(tri2) or not np.all(tri1 == tri2):
1305
1309
  self.refresh_triangulation()
1306
1310
  return self
1307
1311
 
@@ -1676,7 +1680,7 @@ class OpenGLVGroup(OpenGLVMobject):
1676
1680
  """
1677
1681
 
1678
1682
  def __init__(self, *vmobjects, **kwargs):
1679
- if not all([isinstance(m, OpenGLVMobject) for m in vmobjects]):
1683
+ if not all(isinstance(m, OpenGLVMobject) for m in vmobjects):
1680
1684
  raise Exception("All submobjects must be of type OpenGLVMobject")
1681
1685
  super().__init__(**kwargs)
1682
1686
  self.add(*vmobjects)
@@ -1881,7 +1885,7 @@ class OpenGLDashedVMobject(OpenGLVMobject):
1881
1885
  vmobject: OpenGLVMobject,
1882
1886
  num_dashes: int = 15,
1883
1887
  dashed_ratio: float = 0.5,
1884
- color: Color = WHITE,
1888
+ color: ParsableManimColor = WHITE,
1885
1889
  **kwargs,
1886
1890
  ):
1887
1891
  self.dashed_ratio = dashed_ratio
@@ -335,10 +335,12 @@ class ArcBrace(Brace):
335
335
 
336
336
  def __init__(
337
337
  self,
338
- arc: Arc = Arc(start_angle=-1, angle=2, radius=1),
338
+ arc: Arc | None = None,
339
339
  direction: Sequence[float] = RIGHT,
340
340
  **kwargs,
341
341
  ):
342
+ if arc is None:
343
+ arc = Arc(start_angle=-1, angle=2, radius=1)
342
344
  arc_end_angle = arc.start_angle + arc.angle
343
345
  line = Line(UP * arc.start_angle, UP * arc_end_angle)
344
346
  scale_shift = RIGHT * np.log(arc.radius)
@@ -280,7 +280,7 @@ class SVGMobject(VMobject, metaclass=ConvertToOpenGL):
280
280
  mob = self.polyline_to_mobject(shape)
281
281
  elif isinstance(shape, se.Text):
282
282
  mob = self.text_to_mobject(shape)
283
- elif isinstance(shape, se.Use) or type(shape) == se.SVGElement:
283
+ elif isinstance(shape, se.Use) or type(shape) is se.SVGElement:
284
284
  continue
285
285
  else:
286
286
  logger.warning(f"Unsupported element type: {type(shape)}")
@@ -510,17 +510,15 @@ class VMobjectFromSVGPath(VMobject, metaclass=ConvertToOpenGL):
510
510
  all_points: list[np.ndarray] = []
511
511
  last_move = None
512
512
  curve_start = None
513
+ last_true_move = None
513
514
 
514
- # These lambdas behave the same as similar functions in
515
- # vectorized_mobject, except they add to a list of points instead
516
- # of updating this Mobject's numpy array of points. This way,
517
- # we don't observe O(n^2) behavior for complex paths due to
518
- # numpy's need to re-allocate memory on every append.
519
- def move_pen(pt):
520
- nonlocal last_move, curve_start
515
+ def move_pen(pt, *, true_move: bool = False):
516
+ nonlocal last_move, curve_start, last_true_move
521
517
  last_move = pt
522
518
  if curve_start is None:
523
519
  curve_start = last_move
520
+ if true_move:
521
+ last_true_move = last_move
524
522
 
525
523
  if self.n_points_per_curve == 4:
526
524
 
@@ -568,7 +566,7 @@ class VMobjectFromSVGPath(VMobject, metaclass=ConvertToOpenGL):
568
566
  for segment in self.path_obj:
569
567
  segment_class = segment.__class__
570
568
  if segment_class == se.Move:
571
- move_pen(_convert_point_to_3d(*segment.end))
569
+ move_pen(_convert_point_to_3d(*segment.end), true_move=True)
572
570
  elif segment_class == se.Line:
573
571
  add_line(last_move, _convert_point_to_3d(*segment.end))
574
572
  elif segment_class == se.QuadraticBezier:
@@ -588,8 +586,8 @@ class VMobjectFromSVGPath(VMobject, metaclass=ConvertToOpenGL):
588
586
  # If the SVG path naturally ends at the beginning of the curve,
589
587
  # we do *not* need to draw a closing line. To account for floating
590
588
  # point precision, we use a small value to compare the two points.
591
- if abs(np.linalg.norm(last_move - curve_start)) > 0.0001:
592
- add_line(last_move, curve_start)
589
+ if abs(np.linalg.norm(last_move - last_true_move)) > 0.0001:
590
+ add_line(last_move, last_true_move)
593
591
  curve_start = None
594
592
  else:
595
593
  raise AssertionError(f"Not implemented: {segment_class}")
manim/mobject/table.py CHANGED
@@ -67,8 +67,6 @@ __all__ = [
67
67
  import itertools as it
68
68
  from typing import Callable, Iterable, Sequence
69
69
 
70
- from colour import Color
71
-
72
70
  from manim.mobject.geometry.line import Line
73
71
  from manim.mobject.geometry.polygram import Polygon
74
72
  from manim.mobject.geometry.shape_matchers import BackgroundRectangle
@@ -82,13 +80,50 @@ from ..animation.composition import AnimationGroup
82
80
  from ..animation.creation import Create, Write
83
81
  from ..animation.fading import FadeIn
84
82
  from ..mobject.types.vectorized_mobject import VGroup, VMobject
85
- from ..utils.color import BLACK, YELLOW
83
+ from ..utils.color import BLACK, YELLOW, ManimColor, ParsableManimColor
86
84
  from .utils import get_vectorized_mobject_class
87
85
 
88
86
 
89
87
  class Table(VGroup):
90
88
  """A mobject that displays a table on the screen.
91
89
 
90
+ Parameters
91
+ ----------
92
+ table
93
+ A 2D array or list of lists. Content of the table has to be a valid input
94
+ for the callable set in ``element_to_mobject``.
95
+ row_labels
96
+ List of :class:`~.VMobject` representing the labels of each row.
97
+ col_labels
98
+ List of :class:`~.VMobject` representing the labels of each column.
99
+ top_left_entry
100
+ The top-left entry of the table, can only be specified if row and
101
+ column labels are given.
102
+ v_buff
103
+ Vertical buffer passed to :meth:`~.Mobject.arrange_in_grid`, by default 0.8.
104
+ h_buff
105
+ Horizontal buffer passed to :meth:`~.Mobject.arrange_in_grid`, by default 1.3.
106
+ include_outer_lines
107
+ ``True`` if the table should include outer lines, by default False.
108
+ add_background_rectangles_to_entries
109
+ ``True`` if background rectangles should be added to entries, by default ``False``.
110
+ entries_background_color
111
+ Background color of entries if ``add_background_rectangles_to_entries`` is ``True``.
112
+ include_background_rectangle
113
+ ``True`` if the table should have a background rectangle, by default ``False``.
114
+ background_rectangle_color
115
+ Background color of table if ``include_background_rectangle`` is ``True``.
116
+ element_to_mobject
117
+ The :class:`~.Mobject` class applied to the table entries. by default :class:`~.Paragraph`. For common choices, see :mod:`~.text_mobject`/:mod:`~.tex_mobject`.
118
+ element_to_mobject_config
119
+ Custom configuration passed to :attr:`element_to_mobject`, by default {}.
120
+ arrange_in_grid_config
121
+ Dict passed to :meth:`~.Mobject.arrange_in_grid`, customizes the arrangement of the table.
122
+ line_config
123
+ Dict passed to :class:`~.Line`, customizes the lines of the table.
124
+ kwargs
125
+ Additional arguments to be passed to :class:`~.VGroup`.
126
+
92
127
  Examples
93
128
  --------
94
129
 
@@ -160,9 +195,9 @@ class Table(VGroup):
160
195
  h_buff: float = 1.3,
161
196
  include_outer_lines: bool = False,
162
197
  add_background_rectangles_to_entries: bool = False,
163
- entries_background_color: Color = BLACK,
198
+ entries_background_color: ParsableManimColor = BLACK,
164
199
  include_background_rectangle: bool = False,
165
- background_rectangle_color: Color = BLACK,
200
+ background_rectangle_color: ParsableManimColor = BLACK,
166
201
  element_to_mobject: Callable[
167
202
  [float | str | VMobject],
168
203
  VMobject,
@@ -172,45 +207,6 @@ class Table(VGroup):
172
207
  line_config: dict = {},
173
208
  **kwargs,
174
209
  ):
175
- """
176
- Parameters
177
- ----------
178
- table
179
- A 2D array or list of lists. Content of the table has to be a valid input
180
- for the callable set in ``element_to_mobject``.
181
- row_labels
182
- List of :class:`~.VMobject` representing the labels of each row.
183
- col_labels
184
- List of :class:`~.VMobject` representing the labels of each column.
185
- top_left_entry
186
- The top-left entry of the table, can only be specified if row and
187
- column labels are given.
188
- v_buff
189
- Vertical buffer passed to :meth:`~.Mobject.arrange_in_grid`, by default 0.8.
190
- h_buff
191
- Horizontal buffer passed to :meth:`~.Mobject.arrange_in_grid`, by default 1.3.
192
- include_outer_lines
193
- ``True`` if the table should include outer lines, by default False.
194
- add_background_rectangles_to_entries
195
- ``True`` if background rectangles should be added to entries, by default ``False``.
196
- entries_background_color
197
- Background color of entries if ``add_background_rectangles_to_entries`` is ``True``.
198
- include_background_rectangle
199
- ``True`` if the table should have a background rectangle, by default ``False``.
200
- background_rectangle_color
201
- Background color of table if ``include_background_rectangle`` is ``True``.
202
- element_to_mobject
203
- The :class:`~.Mobject` class applied to the table entries. by default :class:`~.Paragraph`. For common choices, see :mod:`~.text_mobject`/:mod:`~.tex_mobject`.
204
- element_to_mobject_config
205
- Custom configuration passed to :attr:`element_to_mobject`, by default {}.
206
- arrange_in_grid_config
207
- Dict passed to :meth:`~.Mobject.arrange_in_grid`, customizes the arrangement of the table.
208
- line_config
209
- Dict passed to :class:`~.Line`, customizes the lines of the table.
210
- kwargs
211
- Additional arguments to be passed to :class:`~.VGroup`.
212
- """
213
-
214
210
  self.row_labels = row_labels
215
211
  self.col_labels = col_labels
216
212
  self.top_left_entry = top_left_entry
@@ -220,9 +216,9 @@ class Table(VGroup):
220
216
  self.h_buff = h_buff
221
217
  self.include_outer_lines = include_outer_lines
222
218
  self.add_background_rectangles_to_entries = add_background_rectangles_to_entries
223
- self.entries_background_color = entries_background_color
219
+ self.entries_background_color = ManimColor(entries_background_color)
224
220
  self.include_background_rectangle = include_background_rectangle
225
- self.background_rectangle_color = background_rectangle_color
221
+ self.background_rectangle_color = ManimColor(background_rectangle_color)
226
222
  self.element_to_mobject = element_to_mobject
227
223
  self.element_to_mobject_config = element_to_mobject_config
228
224
  self.arrange_in_grid_config = arrange_in_grid_config
@@ -506,7 +502,7 @@ class Table(VGroup):
506
502
  """
507
503
  return VGroup(*(VGroup(*row) for row in self.mob_table))
508
504
 
509
- def set_column_colors(self, *colors: Iterable[Color]) -> Table:
505
+ def set_column_colors(self, *colors: Iterable[ParsableManimColor]) -> Table:
510
506
  """Set individual colors for each column of the table.
511
507
 
512
508
  Parameters
@@ -535,7 +531,7 @@ class Table(VGroup):
535
531
  column.set_color(color)
536
532
  return self
537
533
 
538
- def set_row_colors(self, *colors: Iterable[Color]) -> Table:
534
+ def set_row_colors(self, *colors: Iterable[ParsableManimColor]) -> Table:
539
535
  """Set individual colors for each row of the table.
540
536
 
541
537
  Parameters
@@ -754,10 +750,10 @@ class Table(VGroup):
754
750
  label_group.add(*label)
755
751
  return label_group
756
752
 
757
- def add_background_to_entries(self, color: Color = BLACK) -> Table:
753
+ def add_background_to_entries(self, color: ParsableManimColor = BLACK) -> Table:
758
754
  """Adds a black :class:`~.BackgroundRectangle` to each entry of the table."""
759
755
  for mob in self.get_entries():
760
- mob.add_background_rectangle(color=color)
756
+ mob.add_background_rectangle(color=ManimColor(color))
761
757
  return self
762
758
 
763
759
  def get_cell(self, pos: Sequence[int] = (1, 1), **kwargs) -> Polygon:
@@ -818,7 +814,7 @@ class Table(VGroup):
818
814
  return rec
819
815
 
820
816
  def get_highlighted_cell(
821
- self, pos: Sequence[int] = (1, 1), color: Color = YELLOW, **kwargs
817
+ self, pos: Sequence[int] = (1, 1), color: ParsableManimColor = YELLOW, **kwargs
822
818
  ) -> BackgroundRectangle:
823
819
  """Returns a :class:`~.BackgroundRectangle` of the cell at the given position.
824
820
 
@@ -850,11 +846,11 @@ class Table(VGroup):
850
846
  self.add(table)
851
847
  """
852
848
  cell = self.get_cell(pos)
853
- bg_cell = BackgroundRectangle(cell, color=color, **kwargs)
849
+ bg_cell = BackgroundRectangle(cell, color=ManimColor(color), **kwargs)
854
850
  return bg_cell
855
851
 
856
852
  def add_highlighted_cell(
857
- self, pos: Sequence[int] = (1, 1), color: Color = YELLOW, **kwargs
853
+ self, pos: Sequence[int] = (1, 1), color: ParsableManimColor = YELLOW, **kwargs
858
854
  ) -> Table:
859
855
  """Highlights one cell at a specific position on the table by adding a :class:`~.BackgroundRectangle`.
860
856
 
@@ -884,7 +880,7 @@ class Table(VGroup):
884
880
  table.add_highlighted_cell((2,2), color=GREEN)
885
881
  self.add(table)
886
882
  """
887
- bg_cell = self.get_highlighted_cell(pos, color=color, **kwargs)
883
+ bg_cell = self.get_highlighted_cell(pos, color=ManimColor(color), **kwargs)
888
884
  self.add_to_back(bg_cell)
889
885
  entry = self.get_entries(pos)
890
886
  entry.background_rectangle = bg_cell
@@ -22,6 +22,34 @@ string_to_mob_map = {}
22
22
  class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
23
23
  """An mobject representing a decimal number.
24
24
 
25
+ Parameters
26
+ ----------
27
+ number
28
+ The numeric value to be displayed. It can later be modified using :meth:`.set_value`.
29
+ num_decimal_places
30
+ The number of decimal places after the decimal separator. Values are automatically rounded.
31
+ mob_class
32
+ The class for rendering digits and units, by default :class:`.MathTex`.
33
+ include_sign
34
+ Set to ``True`` to include a sign for positive numbers and zero.
35
+ group_with_commas
36
+ When ``True`` thousands groups are separated by commas for readability.
37
+ digit_buff_per_font_unit
38
+ Additional spacing between digits. Scales with font size.
39
+ show_ellipsis
40
+ When a number has been truncated by rounding, indicate with an ellipsis (``...``).
41
+ unit
42
+ A unit string which can be placed to the right of the numerical values.
43
+ unit_buff_per_font_unit
44
+ An additional spacing between the numerical values and the unit. A value
45
+ of ``unit_buff_per_font_unit=0.003`` gives a decent spacing. Scales with font size.
46
+ include_background_rectangle
47
+ Adds a background rectangle to increase contrast on busy scenes.
48
+ edge_to_fix
49
+ Assuring right- or left-alignment of the full object.
50
+ font_size
51
+ Size of the font.
52
+
25
53
  Examples
26
54
  --------
27
55
 
@@ -34,6 +62,8 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
34
62
  show_ellipsis=True,
35
63
  num_decimal_places=3,
36
64
  include_sign=True,
65
+ unit=r"\text{M-Units}",
66
+ unit_buff_per_font_unit=0.003
37
67
  )
38
68
  square = Square().to_edge(UP)
39
69
 
@@ -59,6 +89,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
59
89
  digit_buff_per_font_unit: float = 0.001,
60
90
  show_ellipsis: bool = False,
61
91
  unit: str | None = None, # Aligned to bottom unless it starts with "^"
92
+ unit_buff_per_font_unit: float = 0,
62
93
  include_background_rectangle: bool = False,
63
94
  edge_to_fix: Sequence[float] = LEFT,
64
95
  font_size: float = DEFAULT_FONT_SIZE,
@@ -66,7 +97,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
66
97
  fill_opacity: float = 1.0,
67
98
  **kwargs,
68
99
  ):
69
- super().__init__(**kwargs)
100
+ super().__init__(**kwargs, stroke_width=stroke_width)
70
101
  self.number = number
71
102
  self.num_decimal_places = num_decimal_places
72
103
  self.include_sign = include_sign
@@ -75,10 +106,10 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
75
106
  self.digit_buff_per_font_unit = digit_buff_per_font_unit
76
107
  self.show_ellipsis = show_ellipsis
77
108
  self.unit = unit
109
+ self.unit_buff_per_font_unit = unit_buff_per_font_unit
78
110
  self.include_background_rectangle = include_background_rectangle
79
111
  self.edge_to_fix = edge_to_fix
80
112
  self._font_size = font_size
81
- self.stroke_width = stroke_width
82
113
  self.fill_opacity = fill_opacity
83
114
 
84
115
  self.initial_config = kwargs.copy()
@@ -90,6 +121,7 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
90
121
  "digit_buff_per_font_unit": digit_buff_per_font_unit,
91
122
  "show_ellipsis": show_ellipsis,
92
123
  "unit": unit,
124
+ "unit_buff_per_font_unit": unit_buff_per_font_unit,
93
125
  "include_background_rectangle": include_background_rectangle,
94
126
  "edge_to_fix": edge_to_fix,
95
127
  "font_size": font_size,
@@ -131,15 +163,25 @@ class DecimalNumber(VMobject, metaclass=ConvertToOpenGL):
131
163
  self._string_to_mob("\\dots", SingleStringMathTex, color=self.color),
132
164
  )
133
165
 
134
- if self.unit is not None:
135
- self.unit_sign = self._string_to_mob(self.unit, SingleStringMathTex)
136
- self.add(self.unit_sign)
137
-
138
166
  self.arrange(
139
167
  buff=self.digit_buff_per_font_unit * self._font_size,
140
168
  aligned_edge=DOWN,
141
169
  )
142
170
 
171
+ if self.unit is not None:
172
+ self.unit_sign = self._string_to_mob(self.unit, SingleStringMathTex)
173
+ self.add(
174
+ self.unit_sign.next_to(
175
+ self,
176
+ direction=RIGHT,
177
+ buff=(self.unit_buff_per_font_unit + self.digit_buff_per_font_unit)
178
+ * self._font_size,
179
+ aligned_edge=DOWN,
180
+ )
181
+ )
182
+
183
+ self.move_to(ORIGIN)
184
+
143
185
  # Handle alignment of parts that should be aligned
144
186
  # to the bottom
145
187
  for i, c in enumerate(num_string):