manim 0.18.0.post0__py3-none-any.whl → 0.19.0__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 (146) hide show
  1. manim/__init__.py +3 -6
  2. manim/__main__.py +61 -20
  3. manim/_config/__init__.py +6 -3
  4. manim/_config/cli_colors.py +16 -8
  5. manim/_config/default.cfg +1 -3
  6. manim/_config/logger_utils.py +14 -8
  7. manim/_config/utils.py +651 -472
  8. manim/animation/animation.py +152 -5
  9. manim/animation/composition.py +80 -39
  10. manim/animation/creation.py +196 -14
  11. manim/animation/fading.py +5 -9
  12. manim/animation/indication.py +103 -47
  13. manim/animation/movement.py +22 -5
  14. manim/animation/rotation.py +3 -2
  15. manim/animation/specialized.py +4 -6
  16. manim/animation/speedmodifier.py +10 -5
  17. manim/animation/transform.py +4 -5
  18. manim/animation/transform_matching_parts.py +1 -1
  19. manim/animation/updaters/mobject_update_utils.py +17 -14
  20. manim/camera/camera.py +15 -6
  21. manim/cli/__init__.py +17 -0
  22. manim/cli/cfg/group.py +70 -44
  23. manim/cli/checkhealth/checks.py +93 -75
  24. manim/cli/checkhealth/commands.py +14 -5
  25. manim/cli/default_group.py +157 -25
  26. manim/cli/init/commands.py +32 -24
  27. manim/cli/plugins/commands.py +16 -3
  28. manim/cli/render/commands.py +72 -60
  29. manim/cli/render/ease_of_access_options.py +4 -3
  30. manim/cli/render/global_options.py +51 -15
  31. manim/cli/render/output_options.py +6 -5
  32. manim/cli/render/render_options.py +97 -32
  33. manim/constants.py +65 -19
  34. manim/gui/gui.py +2 -0
  35. manim/mobject/frame.py +0 -1
  36. manim/mobject/geometry/arc.py +112 -78
  37. manim/mobject/geometry/boolean_ops.py +32 -25
  38. manim/mobject/geometry/labeled.py +300 -77
  39. manim/mobject/geometry/line.py +132 -64
  40. manim/mobject/geometry/polygram.py +126 -30
  41. manim/mobject/geometry/shape_matchers.py +35 -15
  42. manim/mobject/geometry/tips.py +38 -29
  43. manim/mobject/graph.py +414 -133
  44. manim/mobject/graphing/coordinate_systems.py +126 -64
  45. manim/mobject/graphing/functions.py +25 -15
  46. manim/mobject/graphing/number_line.py +24 -10
  47. manim/mobject/graphing/probability.py +2 -10
  48. manim/mobject/graphing/scale.py +6 -5
  49. manim/mobject/matrix.py +17 -19
  50. manim/mobject/mobject.py +314 -165
  51. manim/mobject/opengl/opengl_compatibility.py +2 -0
  52. manim/mobject/opengl/opengl_geometry.py +30 -9
  53. manim/mobject/opengl/opengl_image_mobject.py +2 -0
  54. manim/mobject/opengl/opengl_mobject.py +509 -343
  55. manim/mobject/opengl/opengl_point_cloud_mobject.py +5 -7
  56. manim/mobject/opengl/opengl_surface.py +3 -2
  57. manim/mobject/opengl/opengl_three_dimensions.py +2 -0
  58. manim/mobject/opengl/opengl_vectorized_mobject.py +46 -79
  59. manim/mobject/svg/brace.py +63 -13
  60. manim/mobject/svg/svg_mobject.py +4 -3
  61. manim/mobject/table.py +11 -13
  62. manim/mobject/text/code_mobject.py +186 -548
  63. manim/mobject/text/numbers.py +9 -7
  64. manim/mobject/text/tex_mobject.py +23 -14
  65. manim/mobject/text/text_mobject.py +70 -24
  66. manim/mobject/three_d/polyhedra.py +98 -1
  67. manim/mobject/three_d/three_d_utils.py +4 -4
  68. manim/mobject/three_d/three_dimensions.py +62 -34
  69. manim/mobject/types/image_mobject.py +42 -24
  70. manim/mobject/types/point_cloud_mobject.py +105 -67
  71. manim/mobject/types/vectorized_mobject.py +496 -228
  72. manim/mobject/value_tracker.py +5 -4
  73. manim/mobject/vector_field.py +5 -5
  74. manim/opengl/__init__.py +3 -3
  75. manim/plugins/__init__.py +14 -1
  76. manim/plugins/plugins_flags.py +14 -8
  77. manim/renderer/cairo_renderer.py +20 -10
  78. manim/renderer/opengl_renderer.py +21 -23
  79. manim/renderer/opengl_renderer_window.py +2 -0
  80. manim/renderer/shader.py +2 -3
  81. manim/renderer/shader_wrapper.py +5 -2
  82. manim/renderer/vectorized_mobject_rendering.py +5 -0
  83. manim/scene/moving_camera_scene.py +23 -0
  84. manim/scene/scene.py +90 -43
  85. manim/scene/scene_file_writer.py +316 -165
  86. manim/scene/section.py +17 -15
  87. manim/scene/three_d_scene.py +13 -21
  88. manim/scene/vector_space_scene.py +22 -9
  89. manim/typing.py +830 -70
  90. manim/utils/bezier.py +1667 -399
  91. manim/utils/caching.py +13 -5
  92. manim/utils/color/AS2700.py +2 -0
  93. manim/utils/color/BS381.py +3 -0
  94. manim/utils/color/DVIPSNAMES.py +96 -0
  95. manim/utils/color/SVGNAMES.py +179 -0
  96. manim/utils/color/X11.py +3 -0
  97. manim/utils/color/XKCD.py +3 -0
  98. manim/utils/color/__init__.py +8 -5
  99. manim/utils/color/core.py +844 -309
  100. manim/utils/color/manim_colors.py +7 -9
  101. manim/utils/commands.py +48 -20
  102. manim/utils/config_ops.py +18 -13
  103. manim/utils/debug.py +8 -7
  104. manim/utils/deprecation.py +90 -40
  105. manim/utils/docbuild/__init__.py +17 -0
  106. manim/utils/docbuild/autoaliasattr_directive.py +234 -0
  107. manim/utils/docbuild/autocolor_directive.py +21 -17
  108. manim/utils/docbuild/manim_directive.py +50 -35
  109. manim/utils/docbuild/module_parsing.py +245 -0
  110. manim/utils/exceptions.py +6 -0
  111. manim/utils/family.py +5 -3
  112. manim/utils/family_ops.py +17 -4
  113. manim/utils/file_ops.py +26 -16
  114. manim/utils/hashing.py +9 -7
  115. manim/utils/images.py +10 -4
  116. manim/utils/ipython_magic.py +14 -8
  117. manim/utils/iterables.py +161 -119
  118. manim/utils/module_ops.py +57 -19
  119. manim/utils/opengl.py +83 -24
  120. manim/utils/parameter_parsing.py +32 -0
  121. manim/utils/paths.py +21 -23
  122. manim/utils/polylabel.py +168 -0
  123. manim/utils/qhull.py +218 -0
  124. manim/utils/rate_functions.py +74 -39
  125. manim/utils/simple_functions.py +24 -15
  126. manim/utils/sounds.py +7 -1
  127. manim/utils/space_ops.py +125 -69
  128. manim/utils/testing/__init__.py +17 -0
  129. manim/utils/testing/_frames_testers.py +13 -8
  130. manim/utils/testing/_show_diff.py +5 -3
  131. manim/utils/testing/_test_class_makers.py +33 -18
  132. manim/utils/testing/frames_comparison.py +27 -19
  133. manim/utils/tex.py +127 -197
  134. manim/utils/tex_file_writing.py +47 -45
  135. manim/utils/tex_templates.py +2 -1
  136. manim/utils/unit.py +6 -5
  137. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE.community +1 -1
  138. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/METADATA +40 -39
  139. manim-0.19.0.dist-info/RECORD +221 -0
  140. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
  141. manim/cli/new/__init__.py +0 -0
  142. manim/cli/new/group.py +0 -189
  143. manim/plugins/import_plugins.py +0 -43
  144. manim-0.18.0.post0.dist-info/RECORD +0 -217
  145. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
  146. {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from manim.typing import Point3D, Vector3
5
+ from manim.typing import Point3DLike, Vector3D
6
6
  from manim.utils.color import BLUE, BLUE_D, BLUE_E, LIGHT_GREY, WHITE, interpolate_color
7
7
 
8
8
  __all__ = [
@@ -19,7 +19,8 @@ __all__ = [
19
19
  "Torus",
20
20
  ]
21
21
 
22
- from typing import Any, Callable, Iterable, Sequence
22
+ from collections.abc import Iterable, Sequence
23
+ from typing import Any, Callable
23
24
 
24
25
  import numpy as np
25
26
  from typing_extensions import Self
@@ -31,16 +32,10 @@ from manim.mobject.geometry.polygram import Square
31
32
  from manim.mobject.mobject import *
32
33
  from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
33
34
  from manim.mobject.opengl.opengl_mobject import OpenGLMobject
34
- from manim.mobject.types.vectorized_mobject import VGroup, VMobject
35
+ from manim.mobject.types.vectorized_mobject import VectorizedPoint, VGroup, VMobject
35
36
  from manim.utils.color import (
36
- BLUE,
37
- BLUE_D,
38
- BLUE_E,
39
- LIGHT_GREY,
40
- WHITE,
41
37
  ManimColor,
42
38
  ParsableManimColor,
43
- interpolate_color,
44
39
  )
45
40
  from manim.utils.iterables import tuplify
46
41
  from manim.utils.space_ops import normalize, perpendicular_bisector, z_to_vector
@@ -378,7 +373,7 @@ class Sphere(Surface):
378
373
 
379
374
  def __init__(
380
375
  self,
381
- center: Point3D = ORIGIN,
376
+ center: Point3DLike = ORIGIN,
382
377
  radius: float = 1,
383
378
  resolution: Sequence[int] | None = None,
384
379
  u_range: Sequence[float] = (0, TAU),
@@ -621,17 +616,18 @@ class Cone(Surface):
621
616
  **kwargs,
622
617
  )
623
618
  # used for rotations
619
+ self.new_height = height
624
620
  self._current_theta = 0
625
621
  self._current_phi = 0
626
-
622
+ self.base_circle = Circle(
623
+ radius=base_radius,
624
+ color=self.fill_color,
625
+ fill_opacity=self.fill_opacity,
626
+ stroke_width=0,
627
+ )
628
+ self.base_circle.shift(height * IN)
629
+ self._set_start_and_end_attributes(direction)
627
630
  if show_base:
628
- self.base_circle = Circle(
629
- radius=base_radius,
630
- color=self.fill_color,
631
- fill_opacity=self.fill_opacity,
632
- stroke_width=0,
633
- )
634
- self.base_circle.shift(height * IN)
635
631
  self.add(self.base_circle)
636
632
 
637
633
  self._rotate_to_direction()
@@ -661,14 +657,17 @@ class Cone(Surface):
661
657
  ],
662
658
  )
663
659
 
660
+ def get_start(self) -> np.ndarray:
661
+ return self.start_point.get_center()
662
+
663
+ def get_end(self) -> np.ndarray:
664
+ return self.end_point.get_center()
665
+
664
666
  def _rotate_to_direction(self) -> None:
665
667
  x, y, z = self.direction
666
668
 
667
669
  r = np.sqrt(x**2 + y**2 + z**2)
668
- if r > 0:
669
- theta = np.arccos(z / r)
670
- else:
671
- theta = 0
670
+ theta = np.arccos(z / r) if r > 0 else 0
672
671
 
673
672
  if x == 0:
674
673
  if y == 0: # along the z axis
@@ -715,6 +714,15 @@ class Cone(Surface):
715
714
  """
716
715
  return self.direction
717
716
 
717
+ def _set_start_and_end_attributes(self, direction):
718
+ normalized_direction = direction * np.linalg.norm(direction)
719
+
720
+ start = self.base_circle.get_center()
721
+ end = start + normalized_direction * self.new_height
722
+ self.start_point = VectorizedPoint(start)
723
+ self.end_point = VectorizedPoint(end)
724
+ self.add(self.start_point, self.end_point)
725
+
718
726
 
719
727
  class Cylinder(Surface):
720
728
  """A cylinder, defined by its height, radius and direction,
@@ -824,10 +832,7 @@ class Cylinder(Surface):
824
832
  x, y, z = self.direction
825
833
 
826
834
  r = np.sqrt(x**2 + y**2 + z**2)
827
- if r > 0:
828
- theta = np.arccos(z / r)
829
- else:
830
- theta = 0
835
+ theta = np.arccos(z / r) if r > 0 else 0
831
836
 
832
837
  if x == 0:
833
838
  if y == 0: # along the z axis
@@ -890,6 +895,12 @@ class Line3D(Cylinder):
890
895
  The thickness of the line.
891
896
  color
892
897
  The color of the line.
898
+ resolution
899
+ The resolution of the line.
900
+ By default this value is the number of points the line will sampled at.
901
+ If you want the line to also come out checkered, use a tuple.
902
+ For example, for a line made of 24 points with 4 checker points on each
903
+ cylinder, pass the tuple (4, 24).
893
904
 
894
905
  Examples
895
906
  --------
@@ -910,9 +921,11 @@ class Line3D(Cylinder):
910
921
  end: np.ndarray = RIGHT,
911
922
  thickness: float = 0.02,
912
923
  color: ParsableManimColor | None = None,
924
+ resolution: int | Sequence[int] = 24,
913
925
  **kwargs,
914
926
  ):
915
927
  self.thickness = thickness
928
+ self.resolution = (2, resolution) if isinstance(resolution, int) else resolution
916
929
  self.set_start_and_end_attrs(start, end, **kwargs)
917
930
  if color is not None:
918
931
  self.set_color(color)
@@ -946,14 +959,15 @@ class Line3D(Cylinder):
946
959
  height=np.linalg.norm(self.vect),
947
960
  radius=self.thickness,
948
961
  direction=self.direction,
962
+ resolution=self.resolution,
949
963
  **kwargs,
950
964
  )
951
965
  self.shift((self.start + self.end) / 2)
952
966
 
953
967
  def pointify(
954
968
  self,
955
- mob_or_point: Mobject | Point3D,
956
- direction: Vector3 = None,
969
+ mob_or_point: Mobject | Point3DLike,
970
+ direction: Vector3D = None,
957
971
  ) -> np.ndarray:
958
972
  """Gets a point representing the center of the :class:`Mobjects <.Mobject>`.
959
973
 
@@ -1001,7 +1015,7 @@ class Line3D(Cylinder):
1001
1015
  def parallel_to(
1002
1016
  cls,
1003
1017
  line: Line3D,
1004
- point: Vector3 = ORIGIN,
1018
+ point: Vector3D = ORIGIN,
1005
1019
  length: float = 5,
1006
1020
  **kwargs,
1007
1021
  ) -> Line3D:
@@ -1049,7 +1063,7 @@ class Line3D(Cylinder):
1049
1063
  def perpendicular_to(
1050
1064
  cls,
1051
1065
  line: Line3D,
1052
- point: Vector3 = ORIGIN,
1066
+ point: Vector3D = ORIGIN,
1053
1067
  length: float = 5,
1054
1068
  **kwargs,
1055
1069
  ) -> Line3D:
@@ -1117,6 +1131,8 @@ class Arrow3D(Line3D):
1117
1131
  The base radius of the conical tip.
1118
1132
  color
1119
1133
  The color of the arrow.
1134
+ resolution
1135
+ The resolution of the arrow line.
1120
1136
 
1121
1137
  Examples
1122
1138
  --------
@@ -1143,10 +1159,16 @@ class Arrow3D(Line3D):
1143
1159
  height: float = 0.3,
1144
1160
  base_radius: float = 0.08,
1145
1161
  color: ParsableManimColor = WHITE,
1162
+ resolution: int | Sequence[int] = 24,
1146
1163
  **kwargs,
1147
1164
  ) -> None:
1148
1165
  super().__init__(
1149
- start=start, end=end, thickness=thickness, color=color, **kwargs
1166
+ start=start,
1167
+ end=end,
1168
+ thickness=thickness,
1169
+ color=color,
1170
+ resolution=resolution,
1171
+ **kwargs,
1150
1172
  )
1151
1173
 
1152
1174
  self.length = np.linalg.norm(self.vect)
@@ -1155,14 +1177,20 @@ class Arrow3D(Line3D):
1155
1177
  self.end - height * self.direction,
1156
1178
  **kwargs,
1157
1179
  )
1158
-
1159
1180
  self.cone = Cone(
1160
- direction=self.direction, base_radius=base_radius, height=height, **kwargs
1181
+ direction=self.direction,
1182
+ base_radius=base_radius,
1183
+ height=height,
1184
+ **kwargs,
1161
1185
  )
1162
1186
  self.cone.shift(end)
1163
- self.add(self.cone)
1187
+ self.end_point = VectorizedPoint(end)
1188
+ self.add(self.end_point, self.cone)
1164
1189
  self.set_color(color)
1165
1190
 
1191
+ def get_end(self) -> np.ndarray:
1192
+ return self.end_point.get_center()
1193
+
1166
1194
 
1167
1195
  class Torus(Surface):
1168
1196
  """A torus.
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  __all__ = ["AbstractImageMobject", "ImageMobject", "ImageMobjectFromCamera"]
6
6
 
7
7
  import pathlib
8
+ from typing import TYPE_CHECKING
8
9
 
9
10
  import numpy as np
10
11
  from PIL import Image
@@ -19,6 +20,16 @@ from ...utils.bezier import interpolate
19
20
  from ...utils.color import WHITE, ManimColor, color_to_int_rgb
20
21
  from ...utils.images import change_to_rgba_array, get_full_raster_image_path
21
22
 
23
+ __all__ = ["ImageMobject", "ImageMobjectFromCamera"]
24
+
25
+ if TYPE_CHECKING:
26
+ from typing import Any
27
+
28
+ import numpy.typing as npt
29
+ from typing_extensions import Self
30
+
31
+ from manim.typing import StrPath
32
+
22
33
 
23
34
  class AbstractImageMobject(Mobject):
24
35
  """
@@ -37,23 +48,23 @@ class AbstractImageMobject(Mobject):
37
48
  def __init__(
38
49
  self,
39
50
  scale_to_resolution: int,
40
- pixel_array_dtype="uint8",
41
- resampling_algorithm=Resampling.BICUBIC,
42
- **kwargs,
43
- ):
51
+ pixel_array_dtype: str = "uint8",
52
+ resampling_algorithm: Resampling = Resampling.BICUBIC,
53
+ **kwargs: Any,
54
+ ) -> None:
44
55
  self.pixel_array_dtype = pixel_array_dtype
45
56
  self.scale_to_resolution = scale_to_resolution
46
57
  self.set_resampling_algorithm(resampling_algorithm)
47
58
  super().__init__(**kwargs)
48
59
 
49
- def get_pixel_array(self):
60
+ def get_pixel_array(self) -> None:
50
61
  raise NotImplementedError()
51
62
 
52
63
  def set_color(self, color, alpha=None, family=True):
53
64
  # Likely to be implemented in subclasses, but no obligation
54
65
  pass
55
66
 
56
- def set_resampling_algorithm(self, resampling_algorithm: int):
67
+ def set_resampling_algorithm(self, resampling_algorithm: int) -> Self:
57
68
  """
58
69
  Sets the interpolation method for upscaling the image. By default the image is
59
70
  interpolated using bicubic algorithm. This method lets you change it.
@@ -85,7 +96,7 @@ class AbstractImageMobject(Mobject):
85
96
  )
86
97
  return self
87
98
 
88
- def reset_points(self):
99
+ def reset_points(self) -> None:
89
100
  """Sets :attr:`points` to be the four image corners."""
90
101
  self.points = np.array(
91
102
  [
@@ -169,15 +180,15 @@ class ImageMobject(AbstractImageMobject):
169
180
 
170
181
  def __init__(
171
182
  self,
172
- filename_or_array,
183
+ filename_or_array: StrPath | npt.NDArray,
173
184
  scale_to_resolution: int = QUALITIES[DEFAULT_QUALITY]["pixel_height"],
174
- invert=False,
175
- image_mode="RGBA",
176
- **kwargs,
177
- ):
178
- self.fill_opacity = 1
179
- self.stroke_opacity = 1
180
- self.invert = invert
185
+ invert: bool = False,
186
+ image_mode: str = "RGBA",
187
+ **kwargs: Any,
188
+ ) -> None:
189
+ self.fill_opacity: float = 1
190
+ self.stroke_opacity: float = 1
191
+ self.invert_image = invert
181
192
  self.image_mode = image_mode
182
193
  if isinstance(filename_or_array, (str, pathlib.PurePath)):
183
194
  path = get_full_raster_image_path(filename_or_array)
@@ -190,8 +201,10 @@ class ImageMobject(AbstractImageMobject):
190
201
  self.pixel_array = change_to_rgba_array(
191
202
  self.pixel_array, self.pixel_array_dtype
192
203
  )
193
- if self.invert:
194
- self.pixel_array[:, :, :3] = 255 - self.pixel_array[:, :, :3]
204
+ if self.invert_image:
205
+ self.pixel_array[:, :, :3] = (
206
+ np.iinfo(self.pixel_array_dtype).max - self.pixel_array[:, :, :3]
207
+ )
195
208
  super().__init__(scale_to_resolution, **kwargs)
196
209
 
197
210
  def get_pixel_array(self):
@@ -208,7 +221,7 @@ class ImageMobject(AbstractImageMobject):
208
221
  self.color = color
209
222
  return self
210
223
 
211
- def set_opacity(self, alpha: float):
224
+ def set_opacity(self, alpha: float) -> Self:
212
225
  """Sets the image's opacity.
213
226
 
214
227
  Parameters
@@ -222,7 +235,7 @@ class ImageMobject(AbstractImageMobject):
222
235
  self.stroke_opacity = alpha
223
236
  return self
224
237
 
225
- def fade(self, darkness: float = 0.5, family: bool = True):
238
+ def fade(self, darkness: float = 0.5, family: bool = True) -> Self:
226
239
  """Sets the image's opacity using a 1 - alpha relationship.
227
240
 
228
241
  Parameters
@@ -239,7 +252,7 @@ class ImageMobject(AbstractImageMobject):
239
252
 
240
253
  def interpolate_color(
241
254
  self, mobject1: ImageMobject, mobject2: ImageMobject, alpha: float
242
- ):
255
+ ) -> None:
243
256
  """Interpolates the array of pixel color values from one ImageMobject
244
257
  into an array of equal size in the target ImageMobject.
245
258
 
@@ -275,7 +288,7 @@ class ImageMobject(AbstractImageMobject):
275
288
  alpha,
276
289
  ).astype(self.pixel_array_dtype)
277
290
 
278
- def get_style(self):
291
+ def get_style(self) -> dict[str, Any]:
279
292
  return {
280
293
  "fill_color": ManimColor(self.color.get_rgb()).to_hex(),
281
294
  "fill_opacity": self.fill_opacity,
@@ -288,7 +301,12 @@ class ImageMobject(AbstractImageMobject):
288
301
 
289
302
 
290
303
  class ImageMobjectFromCamera(AbstractImageMobject):
291
- def __init__(self, camera, default_display_frame_config=None, **kwargs):
304
+ def __init__(
305
+ self,
306
+ camera,
307
+ default_display_frame_config: dict[str, Any] | None = None,
308
+ **kwargs: Any,
309
+ ) -> None:
292
310
  self.camera = camera
293
311
  if default_display_frame_config is None:
294
312
  default_display_frame_config = {
@@ -305,14 +323,14 @@ class ImageMobjectFromCamera(AbstractImageMobject):
305
323
  self.pixel_array = self.camera.pixel_array
306
324
  return self.pixel_array
307
325
 
308
- def add_display_frame(self, **kwargs):
326
+ def add_display_frame(self, **kwargs: Any) -> Self:
309
327
  config = dict(self.default_display_frame_config)
310
328
  config.update(kwargs)
311
329
  self.display_frame = SurroundingRectangle(self, **config)
312
330
  self.add(self.display_frame)
313
331
  return self
314
332
 
315
- def interpolate_color(self, mobject1, mobject2, alpha):
333
+ def interpolate_color(self, mobject1, mobject2, alpha) -> None:
316
334
  assert mobject1.pixel_array.shape == mobject2.pixel_array.shape, (
317
335
  f"Mobject pixel array shapes incompatible for interpolation.\n"
318
336
  f"Mobject 1 ({mobject1}) : {mobject1.pixel_array.shape}\n"