manim 0.17.0__py3-none-any.whl → 0.19.1__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.
Files changed (163) hide show
  1. manim/__init__.py +11 -6
  2. manim/__main__.py +62 -19
  3. manim/_config/__init__.py +10 -9
  4. manim/_config/cli_colors.py +26 -9
  5. manim/_config/default.cfg +1 -3
  6. manim/_config/logger_utils.py +23 -13
  7. manim/_config/utils.py +662 -468
  8. manim/animation/animation.py +164 -18
  9. manim/animation/changing.py +34 -23
  10. manim/animation/composition.py +265 -67
  11. manim/animation/creation.py +208 -26
  12. manim/animation/fading.py +16 -18
  13. manim/animation/growing.py +35 -15
  14. manim/animation/indication.py +150 -76
  15. manim/animation/movement.py +56 -22
  16. manim/animation/numbers.py +64 -6
  17. manim/animation/rotation.py +78 -7
  18. manim/animation/specialized.py +6 -7
  19. manim/animation/speedmodifier.py +13 -10
  20. manim/animation/transform.py +14 -11
  21. manim/animation/transform_matching_parts.py +3 -4
  22. manim/animation/updaters/mobject_update_utils.py +152 -30
  23. manim/animation/updaters/update.py +10 -7
  24. manim/camera/camera.py +182 -118
  25. manim/camera/mapping_camera.py +34 -3
  26. manim/camera/moving_camera.py +95 -74
  27. manim/camera/multi_camera.py +23 -15
  28. manim/camera/three_d_camera.py +70 -52
  29. manim/cli/__init__.py +17 -0
  30. manim/cli/cfg/group.py +76 -44
  31. manim/cli/checkhealth/checks.py +192 -0
  32. manim/cli/checkhealth/commands.py +90 -0
  33. manim/cli/default_group.py +158 -25
  34. manim/cli/init/commands.py +33 -25
  35. manim/cli/plugins/commands.py +16 -3
  36. manim/cli/render/commands.py +72 -60
  37. manim/cli/render/ease_of_access_options.py +4 -3
  38. manim/cli/render/global_options.py +59 -17
  39. manim/cli/render/output_options.py +6 -5
  40. manim/cli/render/render_options.py +98 -33
  41. manim/constants.py +109 -59
  42. manim/data_structures.py +31 -0
  43. manim/mobject/frame.py +8 -5
  44. manim/mobject/geometry/__init__.py +1 -0
  45. manim/mobject/geometry/arc.py +277 -135
  46. manim/mobject/geometry/boolean_ops.py +32 -31
  47. manim/mobject/geometry/labeled.py +376 -0
  48. manim/mobject/geometry/line.py +192 -87
  49. manim/mobject/geometry/polygram.py +224 -58
  50. manim/mobject/geometry/shape_matchers.py +61 -25
  51. manim/mobject/geometry/tips.py +122 -48
  52. manim/mobject/graph.py +1027 -419
  53. manim/mobject/graphing/coordinate_systems.py +533 -278
  54. manim/mobject/graphing/functions.py +53 -32
  55. manim/mobject/graphing/number_line.py +123 -65
  56. manim/mobject/graphing/probability.py +88 -62
  57. manim/mobject/graphing/scale.py +33 -19
  58. manim/mobject/logo.py +118 -28
  59. manim/mobject/matrix.py +87 -83
  60. manim/mobject/mobject.py +912 -442
  61. manim/mobject/opengl/dot_cloud.py +16 -5
  62. manim/mobject/opengl/opengl_compatibility.py +4 -2
  63. manim/mobject/opengl/opengl_geometry.py +254 -153
  64. manim/mobject/opengl/opengl_image_mobject.py +3 -1
  65. manim/mobject/opengl/opengl_mobject.py +779 -482
  66. manim/mobject/opengl/opengl_point_cloud_mobject.py +41 -14
  67. manim/mobject/opengl/opengl_surface.py +14 -92
  68. manim/mobject/opengl/opengl_three_dimensions.py +12 -8
  69. manim/mobject/opengl/opengl_vectorized_mobject.py +98 -100
  70. manim/mobject/svg/brace.py +173 -41
  71. manim/mobject/svg/svg_mobject.py +139 -53
  72. manim/mobject/table.py +61 -68
  73. manim/mobject/text/code_mobject.py +193 -539
  74. manim/mobject/text/numbers.py +81 -34
  75. manim/mobject/text/tex_mobject.py +130 -78
  76. manim/mobject/text/text_mobject.py +288 -164
  77. manim/mobject/three_d/polyhedra.py +111 -13
  78. manim/mobject/three_d/three_d_utils.py +17 -8
  79. manim/mobject/three_d/three_dimensions.py +239 -106
  80. manim/mobject/types/image_mobject.py +50 -30
  81. manim/mobject/types/point_cloud_mobject.py +120 -75
  82. manim/mobject/types/vectorized_mobject.py +841 -408
  83. manim/mobject/value_tracker.py +105 -38
  84. manim/mobject/vector_field.py +50 -31
  85. manim/opengl/__init__.py +3 -3
  86. manim/plugins/__init__.py +14 -1
  87. manim/plugins/plugins_flags.py +10 -14
  88. manim/renderer/cairo_renderer.py +65 -50
  89. manim/renderer/opengl_renderer.py +89 -69
  90. manim/renderer/opengl_renderer_window.py +39 -18
  91. manim/renderer/shader.py +123 -87
  92. manim/renderer/shader_wrapper.py +44 -28
  93. manim/renderer/vectorized_mobject_rendering.py +38 -10
  94. manim/scene/moving_camera_scene.py +32 -3
  95. manim/scene/scene.py +507 -242
  96. manim/scene/scene_file_writer.py +371 -220
  97. manim/scene/section.py +20 -16
  98. manim/scene/three_d_scene.py +14 -22
  99. manim/scene/vector_space_scene.py +223 -129
  100. manim/scene/zoomed_scene.py +46 -41
  101. manim/typing.py +990 -0
  102. manim/utils/bezier.py +1823 -371
  103. manim/utils/caching.py +12 -5
  104. manim/utils/color/AS2700.py +236 -0
  105. manim/utils/color/BS381.py +318 -0
  106. manim/utils/color/DVIPSNAMES.py +96 -0
  107. manim/utils/color/SVGNAMES.py +179 -0
  108. manim/utils/color/X11.py +533 -0
  109. manim/utils/color/XKCD.py +952 -0
  110. manim/utils/color/__init__.py +61 -0
  111. manim/utils/color/core.py +1667 -0
  112. manim/utils/color/manim_colors.py +218 -0
  113. manim/utils/commands.py +48 -20
  114. manim/utils/config_ops.py +39 -19
  115. manim/utils/debug.py +8 -7
  116. manim/utils/deprecation.py +86 -39
  117. manim/utils/docbuild/__init__.py +17 -0
  118. manim/utils/docbuild/autoaliasattr_directive.py +236 -0
  119. manim/utils/docbuild/autocolor_directive.py +99 -0
  120. manim/utils/docbuild/manim_directive.py +94 -41
  121. manim/utils/docbuild/module_parsing.py +245 -0
  122. manim/utils/exceptions.py +6 -0
  123. manim/utils/family.py +5 -3
  124. manim/utils/family_ops.py +17 -4
  125. manim/utils/file_ops.py +27 -17
  126. manim/utils/hashing.py +55 -45
  127. manim/utils/images.py +13 -7
  128. manim/utils/ipython_magic.py +13 -7
  129. manim/utils/iterables.py +163 -120
  130. manim/utils/module_ops.py +66 -24
  131. manim/utils/opengl.py +77 -24
  132. manim/utils/parameter_parsing.py +32 -0
  133. manim/utils/paths.py +30 -33
  134. manim/utils/polylabel.py +235 -0
  135. manim/utils/qhull.py +218 -0
  136. manim/utils/rate_functions.py +98 -32
  137. manim/utils/simple_functions.py +25 -33
  138. manim/utils/sounds.py +7 -1
  139. manim/utils/space_ops.py +188 -115
  140. manim/utils/testing/__init__.py +17 -0
  141. manim/utils/testing/_frames_testers.py +13 -8
  142. manim/utils/testing/_show_diff.py +5 -3
  143. manim/utils/testing/_test_class_makers.py +34 -18
  144. manim/utils/testing/frames_comparison.py +37 -19
  145. manim/utils/tex.py +130 -198
  146. manim/utils/tex_file_writing.py +77 -47
  147. manim/utils/tex_templates.py +2 -1
  148. manim/utils/unit.py +6 -5
  149. {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/METADATA +64 -65
  150. manim-0.19.1.dist-info/RECORD +220 -0
  151. {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/WHEEL +1 -1
  152. manim-0.19.1.dist-info/entry_points.txt +3 -0
  153. {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE.community +1 -1
  154. manim/cli/new/group.py +0 -189
  155. manim/communitycolors.py +0 -9
  156. manim/gui/__init__.py +0 -0
  157. manim/gui/gui.py +0 -82
  158. manim/plugins/import_plugins.py +0 -43
  159. manim/utils/color.py +0 -552
  160. manim-0.17.0.dist-info/RECORD +0 -206
  161. manim-0.17.0.dist-info/entry_points.txt +0 -4
  162. /manim/cli/{new → checkhealth}/__init__.py +0 -0
  163. {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE +0 -0
@@ -1,4 +1,4 @@
1
- """A camera that allows mapping between objects."""
1
+ """A camera module that supports spatial mapping between objects for distortion effects."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -17,8 +17,16 @@ from ..utils.config_ops import DictAsObject
17
17
 
18
18
 
19
19
  class MappingCamera(Camera):
20
- """Camera object that allows mapping
21
- between objects.
20
+ """Parameters
21
+ ----------
22
+ mapping_func : callable
23
+ Function to map 3D points to new 3D points (identity by default).
24
+ min_num_curves : int
25
+ Minimum number of curves for VMobjects to avoid visual glitches.
26
+ allow_object_intrusion : bool
27
+ If True, modifies original mobjects; else works on copies.
28
+ kwargs : dict
29
+ Additional arguments passed to Camera base class.
22
30
  """
23
31
 
24
32
  def __init__(
@@ -34,12 +42,18 @@ class MappingCamera(Camera):
34
42
  super().__init__(**kwargs)
35
43
 
36
44
  def points_to_pixel_coords(self, mobject, points):
45
+ # Map points with custom function before converting to pixels
37
46
  return super().points_to_pixel_coords(
38
47
  mobject,
39
48
  np.apply_along_axis(self.mapping_func, 1, points),
40
49
  )
41
50
 
42
51
  def capture_mobjects(self, mobjects, **kwargs):
52
+ """Capture mobjects for rendering after applying the spatial mapping.
53
+
54
+ Copies mobjects unless intrusion is allowed, and ensures
55
+ vector objects have enough curves for smooth distortion.
56
+ """
43
57
  mobjects = self.get_mobjects_to_display(mobjects, **kwargs)
44
58
  if self.allow_object_intrusion:
45
59
  mobject_copies = mobjects
@@ -64,8 +78,16 @@ class MappingCamera(Camera):
64
78
  # TODO: Add optional separator borders between cameras (or perhaps peel this off into a
65
79
  # CameraPlusOverlay class)
66
80
 
81
+
67
82
  # TODO, the classes below should likely be deleted
68
83
  class OldMultiCamera(Camera):
84
+ """Parameters
85
+ ----------
86
+ cameras_with_start_positions : tuple
87
+ Tuples of (Camera, (start_y, start_x)) indicating camera and
88
+ its pixel offset on the final frame.
89
+ """
90
+
69
91
  def __init__(self, *cameras_with_start_positions, **kwargs):
70
92
  self.shifted_cameras = [
71
93
  DictAsObject(
@@ -124,6 +146,15 @@ class OldMultiCamera(Camera):
124
146
 
125
147
 
126
148
  class SplitScreenCamera(OldMultiCamera):
149
+ """Initializes a split screen camera setup with two side-by-side cameras.
150
+
151
+ Parameters
152
+ ----------
153
+ left_camera : Camera
154
+ right_camera : Camera
155
+ kwargs : dict
156
+ """
157
+
127
158
  def __init__(self, left_camera, right_camera, **kwargs):
128
159
  Camera.__init__(self, **kwargs) # to set attributes such as pixel_width
129
160
  self.left_camera = left_camera
@@ -1,45 +1,48 @@
1
- """A camera able to move through a scene.
1
+ """Defines the MovingCamera class, a camera that can pan and zoom through a scene.
2
2
 
3
3
  .. SEEALSO::
4
4
 
5
5
  :mod:`.moving_camera_scene`
6
-
7
6
  """
8
7
 
9
8
  from __future__ import annotations
10
9
 
11
10
  __all__ = ["MovingCamera"]
12
11
 
13
- import numpy as np
12
+ from collections.abc import Iterable
13
+ from typing import Any
14
+
15
+ from cairo import Context
16
+
17
+ from manim.typing import PixelArray, Point3D, Point3DLike
14
18
 
15
19
  from .. import config
16
20
  from ..camera.camera import Camera
17
21
  from ..constants import DOWN, LEFT, RIGHT, UP
18
22
  from ..mobject.frame import ScreenRectangle
19
23
  from ..mobject.mobject import Mobject
20
- from ..utils.color import WHITE
24
+ from ..utils.color import WHITE, ManimColor
21
25
 
22
26
 
23
27
  class MovingCamera(Camera):
24
- """
25
- Stays in line with the height, width and position of it's 'frame', which is a Rectangle
28
+ """A camera that follows and matches the size and position of its 'frame', a Rectangle (or similar Mobject).
29
+
30
+ The frame defines the region of space the camera displays and can move or resize dynamically.
26
31
 
27
32
  .. SEEALSO::
28
33
 
29
34
  :class:`.MovingCameraScene`
30
-
31
35
  """
32
36
 
33
37
  def __init__(
34
38
  self,
35
- frame=None,
36
- fixed_dimension=0, # width
37
- default_frame_stroke_color=WHITE,
38
- default_frame_stroke_width=0,
39
- **kwargs,
39
+ frame: Mobject | None = None,
40
+ fixed_dimension: int = 0, # width
41
+ default_frame_stroke_color: ManimColor = WHITE,
42
+ default_frame_stroke_width: int = 0,
43
+ **kwargs: Any,
40
44
  ):
41
- """
42
- Frame is a Mobject, (should almost certainly be a rectangle)
45
+ """Frame is a Mobject, (should almost certainly be a rectangle)
43
46
  determining which region of space the camera displays
44
47
  """
45
48
  self.fixed_dimension = fixed_dimension
@@ -56,7 +59,7 @@ class MovingCamera(Camera):
56
59
 
57
60
  # TODO, make these work for a rotated frame
58
61
  @property
59
- def frame_height(self):
62
+ def frame_height(self) -> float:
60
63
  """Returns the height of the frame.
61
64
 
62
65
  Returns
@@ -66,30 +69,8 @@ class MovingCamera(Camera):
66
69
  """
67
70
  return self.frame.height
68
71
 
69
- @property
70
- def frame_width(self):
71
- """Returns the width of the frame
72
-
73
- Returns
74
- -------
75
- float
76
- The width of the frame.
77
- """
78
- return self.frame.width
79
-
80
- @property
81
- def frame_center(self):
82
- """Returns the centerpoint of the frame in cartesian coordinates.
83
-
84
- Returns
85
- -------
86
- np.array
87
- The cartesian coordinates of the center of the frame.
88
- """
89
- return self.frame.get_center()
90
-
91
72
  @frame_height.setter
92
- def frame_height(self, frame_height: float):
73
+ def frame_height(self, frame_height: float) -> None:
93
74
  """Sets the height of the frame in MUnits.
94
75
 
95
76
  Parameters
@@ -99,8 +80,19 @@ class MovingCamera(Camera):
99
80
  """
100
81
  self.frame.stretch_to_fit_height(frame_height)
101
82
 
83
+ @property
84
+ def frame_width(self) -> float:
85
+ """Returns the width of the frame
86
+
87
+ Returns
88
+ -------
89
+ float
90
+ The width of the frame.
91
+ """
92
+ return self.frame.width
93
+
102
94
  @frame_width.setter
103
- def frame_width(self, frame_width: float):
95
+ def frame_width(self, frame_width: float) -> None:
104
96
  """Sets the width of the frame in MUnits.
105
97
 
106
98
  Parameters
@@ -110,8 +102,19 @@ class MovingCamera(Camera):
110
102
  """
111
103
  self.frame.stretch_to_fit_width(frame_width)
112
104
 
105
+ @property
106
+ def frame_center(self) -> Point3D:
107
+ """Returns the centerpoint of the frame in cartesian coordinates.
108
+
109
+ Returns
110
+ -------
111
+ np.array
112
+ The cartesian coordinates of the center of the frame.
113
+ """
114
+ return self.frame.get_center()
115
+
113
116
  @frame_center.setter
114
- def frame_center(self, frame_center: np.ndarray | list | tuple | Mobject):
117
+ def frame_center(self, frame_center: Point3DLike | Mobject) -> None:
115
118
  """Sets the centerpoint of the frame.
116
119
 
117
120
  Parameters
@@ -123,25 +126,20 @@ class MovingCamera(Camera):
123
126
  """
124
127
  self.frame.move_to(frame_center)
125
128
 
126
- def capture_mobjects(self, mobjects, **kwargs):
129
+ def capture_mobjects(self, mobjects: Iterable[Mobject], **kwargs: Any) -> None:
127
130
  # self.reset_frame_center()
128
131
  # self.realign_frame_shape()
129
132
  super().capture_mobjects(mobjects, **kwargs)
130
133
 
131
- # Since the frame can be moving around, the cairo
132
- # context used for updating should be regenerated
133
- # at each frame. So no caching.
134
- def get_cached_cairo_context(self, pixel_array):
135
- """
136
- Since the frame can be moving around, the cairo
134
+ def get_cached_cairo_context(self, pixel_array: PixelArray) -> None:
135
+ """Since the frame can be moving around, the cairo
137
136
  context used for updating should be regenerated
138
137
  at each frame. So no caching.
139
138
  """
140
139
  return None
141
140
 
142
- def cache_cairo_context(self, pixel_array, ctx):
143
- """
144
- Since the frame can be moving around, the cairo
141
+ def cache_cairo_context(self, pixel_array: PixelArray, ctx: Context) -> None:
142
+ """Since the frame can be moving around, the cairo
145
143
  context used for updating should be regenerated
146
144
  at each frame. So no caching.
147
145
  """
@@ -158,24 +156,23 @@ class MovingCamera(Camera):
158
156
  # self.frame_shape = (self.frame.height, width)
159
157
  # self.resize_frame_shape(fixed_dimension=self.fixed_dimension)
160
158
 
161
- def get_mobjects_indicating_movement(self):
162
- """
163
- Returns all mobjects whose movement implies that the camera
159
+ def get_mobjects_indicating_movement(self) -> list[Mobject]:
160
+ """Returns all mobjects whose movement implies that the camera
164
161
  should think of all other mobjects on the screen as moving
165
162
 
166
163
  Returns
167
164
  -------
168
- list
165
+ list[Mobject]
169
166
  """
170
167
  return [self.frame]
171
168
 
172
169
  def auto_zoom(
173
170
  self,
174
- mobjects: list[Mobject],
171
+ mobjects: Iterable[Mobject],
175
172
  margin: float = 0,
176
173
  only_mobjects_in_frame: bool = False,
177
174
  animate: bool = True,
178
- ):
175
+ ) -> Mobject:
179
176
  """Zooms on to a given array of mobjects (or a singular mobject)
180
177
  and automatically resizes to frame all the mobjects.
181
178
 
@@ -205,10 +202,36 @@ class MovingCamera(Camera):
205
202
  or ScreenRectangle with position and size updated to zoomed position.
206
203
 
207
204
  """
208
- scene_critical_x_left = None
209
- scene_critical_x_right = None
210
- scene_critical_y_up = None
211
- scene_critical_y_down = None
205
+ (
206
+ scene_critical_x_left,
207
+ scene_critical_x_right,
208
+ scene_critical_y_up,
209
+ scene_critical_y_down,
210
+ ) = self._get_bounding_box(mobjects, only_mobjects_in_frame)
211
+
212
+ # calculate center x and y
213
+ x = (scene_critical_x_left + scene_critical_x_right) / 2
214
+ y = (scene_critical_y_up + scene_critical_y_down) / 2
215
+
216
+ # calculate proposed width and height of zoomed scene
217
+ new_width = abs(scene_critical_x_left - scene_critical_x_right)
218
+ new_height = abs(scene_critical_y_up - scene_critical_y_down)
219
+
220
+ m_target = self.frame.animate if animate else self.frame
221
+ # zoom to fit all mobjects along the side that has the largest size
222
+ if new_width / self.frame.width > new_height / self.frame.height:
223
+ return m_target.set_x(x).set_y(y).set(width=new_width + margin)
224
+ else:
225
+ return m_target.set_x(x).set_y(y).set(height=new_height + margin)
226
+
227
+ def _get_bounding_box(
228
+ self, mobjects: Iterable[Mobject], only_mobjects_in_frame: bool
229
+ ) -> tuple[float, float, float, float]:
230
+ bounding_box_located = False
231
+ scene_critical_x_left: float = 0
232
+ scene_critical_x_right: float = 1
233
+ scene_critical_y_up: float = 1
234
+ scene_critical_y_down: float = 0
212
235
 
213
236
  for m in mobjects:
214
237
  if (m == self.frame) or (
@@ -218,11 +241,12 @@ class MovingCamera(Camera):
218
241
  continue
219
242
 
220
243
  # initialize scene critical points with first mobjects critical points
221
- if scene_critical_x_left is None:
244
+ if not bounding_box_located:
222
245
  scene_critical_x_left = m.get_critical_point(LEFT)[0]
223
246
  scene_critical_x_right = m.get_critical_point(RIGHT)[0]
224
247
  scene_critical_y_up = m.get_critical_point(UP)[1]
225
248
  scene_critical_y_down = m.get_critical_point(DOWN)[1]
249
+ bounding_box_located = True
226
250
 
227
251
  else:
228
252
  if m.get_critical_point(LEFT)[0] < scene_critical_x_left:
@@ -237,17 +261,14 @@ class MovingCamera(Camera):
237
261
  if m.get_critical_point(DOWN)[1] < scene_critical_y_down:
238
262
  scene_critical_y_down = m.get_critical_point(DOWN)[1]
239
263
 
240
- # calculate center x and y
241
- x = (scene_critical_x_left + scene_critical_x_right) / 2
242
- y = (scene_critical_y_up + scene_critical_y_down) / 2
243
-
244
- # calculate proposed width and height of zoomed scene
245
- new_width = abs(scene_critical_x_left - scene_critical_x_right)
246
- new_height = abs(scene_critical_y_up - scene_critical_y_down)
264
+ if not bounding_box_located:
265
+ raise Exception(
266
+ "Could not determine bounding box of the mobjects given to 'auto_zoom'."
267
+ )
247
268
 
248
- m_target = self.frame.animate if animate else self.frame
249
- # zoom to fit all mobjects along the side that has the largest size
250
- if new_width / self.frame.width > new_height / self.frame.height:
251
- return m_target.set_x(x).set_y(y).set(width=new_width + margin)
252
- else:
253
- return m_target.set_x(x).set_y(y).set(height=new_height + margin)
269
+ return (
270
+ scene_critical_x_left,
271
+ scene_critical_x_right,
272
+ scene_critical_y_up,
273
+ scene_critical_y_down,
274
+ )
@@ -5,7 +5,13 @@ from __future__ import annotations
5
5
  __all__ = ["MultiCamera"]
6
6
 
7
7
 
8
- from manim.mobject.types.image_mobject import ImageMobject
8
+ from collections.abc import Iterable
9
+ from typing import Any
10
+
11
+ from typing_extensions import Self
12
+
13
+ from manim.mobject.mobject import Mobject
14
+ from manim.mobject.types.image_mobject import ImageMobjectFromCamera
9
15
 
10
16
  from ..camera.moving_camera import MovingCamera
11
17
  from ..utils.iterables import list_difference_update
@@ -16,10 +22,10 @@ class MultiCamera(MovingCamera):
16
22
 
17
23
  def __init__(
18
24
  self,
19
- image_mobjects_from_cameras: ImageMobject | None = None,
20
- allow_cameras_to_capture_their_own_display=False,
21
- **kwargs,
22
- ):
25
+ image_mobjects_from_cameras: Iterable[ImageMobjectFromCamera] | None = None,
26
+ allow_cameras_to_capture_their_own_display: bool = False,
27
+ **kwargs: Any,
28
+ ) -> None:
23
29
  """Initialises the MultiCamera
24
30
 
25
31
  Parameters
@@ -29,7 +35,7 @@ class MultiCamera(MovingCamera):
29
35
  kwargs
30
36
  Any valid keyword arguments of MovingCamera.
31
37
  """
32
- self.image_mobjects_from_cameras = []
38
+ self.image_mobjects_from_cameras: list[ImageMobjectFromCamera] = []
33
39
  if image_mobjects_from_cameras is not None:
34
40
  for imfc in image_mobjects_from_cameras:
35
41
  self.add_image_mobject_from_camera(imfc)
@@ -38,7 +44,9 @@ class MultiCamera(MovingCamera):
38
44
  )
39
45
  super().__init__(**kwargs)
40
46
 
41
- def add_image_mobject_from_camera(self, image_mobject_from_camera: ImageMobject):
47
+ def add_image_mobject_from_camera(
48
+ self, image_mobject_from_camera: ImageMobjectFromCamera
49
+ ) -> None:
42
50
  """Adds an ImageMobject that's been obtained from the camera
43
51
  into the list ``self.image_mobject_from_cameras``
44
52
 
@@ -53,20 +61,20 @@ class MultiCamera(MovingCamera):
53
61
  assert isinstance(imfc.camera, MovingCamera)
54
62
  self.image_mobjects_from_cameras.append(imfc)
55
63
 
56
- def update_sub_cameras(self):
64
+ def update_sub_cameras(self) -> None:
57
65
  """Reshape sub_camera pixel_arrays"""
58
66
  for imfc in self.image_mobjects_from_cameras:
59
67
  pixel_height, pixel_width = self.pixel_array.shape[:2]
60
- imfc.camera.frame_shape = (
61
- imfc.camera.frame.height,
62
- imfc.camera.frame.width,
63
- )
68
+ # imfc.camera.frame_shape = (
69
+ # imfc.camera.frame.height,
70
+ # imfc.camera.frame.width,
71
+ # )
64
72
  imfc.camera.reset_pixel_shape(
65
73
  int(pixel_height * imfc.height / self.frame_height),
66
74
  int(pixel_width * imfc.width / self.frame_width),
67
75
  )
68
76
 
69
- def reset(self):
77
+ def reset(self) -> Self:
70
78
  """Resets the MultiCamera.
71
79
 
72
80
  Returns
@@ -79,7 +87,7 @@ class MultiCamera(MovingCamera):
79
87
  super().reset()
80
88
  return self
81
89
 
82
- def capture_mobjects(self, mobjects, **kwargs):
90
+ def capture_mobjects(self, mobjects: Iterable[Mobject], **kwargs: Any) -> None:
83
91
  self.update_sub_cameras()
84
92
  for imfc in self.image_mobjects_from_cameras:
85
93
  to_add = list(mobjects)
@@ -88,7 +96,7 @@ class MultiCamera(MovingCamera):
88
96
  imfc.camera.capture_mobjects(to_add, **kwargs)
89
97
  super().capture_mobjects(mobjects, **kwargs)
90
98
 
91
- def get_mobjects_indicating_movement(self):
99
+ def get_mobjects_indicating_movement(self) -> list[Mobject]:
92
100
  """Returns all mobjects whose movement implies that the camera
93
101
  should think of all other mobjects on the screen as moving
94
102