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,13 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import copy
4
+ import logging
4
5
  import re
6
+ from collections.abc import Mapping, Sequence
5
7
  from pathlib import Path
8
+ from typing import TYPE_CHECKING
6
9
 
7
10
  import moderngl
8
11
  import numpy as np
12
+ import numpy.typing as npt
13
+ from typing_extensions import Self, TypeAlias
9
14
 
10
- from .. import logger
15
+ if TYPE_CHECKING:
16
+ from manim.typing import FloatRGBLike_Array
11
17
 
12
18
  # Mobjects that should be rendered with
13
19
  # the same shader will be organized and
@@ -15,6 +21,10 @@ from .. import logger
15
21
  # of a dict holding all the relevant information
16
22
  # to that shader
17
23
 
24
+ __all__ = ["ShaderWrapper"]
25
+
26
+ logger = logging.getLogger("manim")
27
+
18
28
 
19
29
  def get_shader_dir():
20
30
  return Path(__file__).parent / "shaders"
@@ -33,25 +43,31 @@ def find_file(file_name: Path, directories: list[Path]) -> Path:
33
43
  raise OSError(f"{file_name} not Found")
34
44
 
35
45
 
46
+ _ShaderDType: TypeAlias = np.void
47
+ _ShaderData: TypeAlias = npt.NDArray[_ShaderDType]
48
+
49
+
36
50
  class ShaderWrapper:
37
51
  def __init__(
38
52
  self,
39
- vert_data=None,
40
- vert_indices=None,
41
- shader_folder=None,
42
- uniforms=None, # A dictionary mapping names of uniform variables
43
- texture_paths=None, # A dictionary mapping names to filepaths for textures.
44
- depth_test=False,
45
- render_primitive=moderngl.TRIANGLE_STRIP,
53
+ vert_data: _ShaderData = None,
54
+ vert_indices: Sequence[int] | None = None,
55
+ shader_folder: Path | str | None = None,
56
+ # A dictionary mapping names of uniform variables
57
+ uniforms: dict[str, float | tuple[float, ...]] | None = None,
58
+ # A dictionary mapping names to filepaths for textures.
59
+ texture_paths: Mapping[str, Path | str] | None = None,
60
+ depth_test: bool = False,
61
+ render_primitive: int | str = moderngl.TRIANGLE_STRIP,
46
62
  ):
47
- self.vert_data = vert_data
48
- self.vert_indices = vert_indices
49
- self.vert_attributes = vert_data.dtype.names
50
- self.shader_folder = Path(shader_folder or "")
51
- self.uniforms = uniforms or {}
52
- self.texture_paths = texture_paths or {}
53
- self.depth_test = depth_test
54
- self.render_primitive = str(render_primitive)
63
+ self.vert_data: _ShaderData = vert_data
64
+ self.vert_indices: Sequence[int] | None = vert_indices
65
+ self.vert_attributes: tuple[str, ...] | None = vert_data.dtype.names
66
+ self.shader_folder: Path = Path(shader_folder or "")
67
+ self.uniforms: dict[str, float | tuple[float, ...]] = uniforms or {}
68
+ self.texture_paths: Mapping[str, str | Path] = texture_paths or {}
69
+ self.depth_test: bool = depth_test
70
+ self.render_primitive: str = str(render_primitive)
55
71
  self.init_program_code()
56
72
  self.refresh_id()
57
73
 
@@ -66,7 +82,7 @@ class ShaderWrapper:
66
82
  result.texture_paths = dict(self.texture_paths)
67
83
  return result
68
84
 
69
- def is_valid(self):
85
+ def is_valid(self) -> bool:
70
86
  return all(
71
87
  [
72
88
  self.vert_data is not None,
@@ -75,10 +91,10 @@ class ShaderWrapper:
75
91
  ],
76
92
  )
77
93
 
78
- def get_id(self):
94
+ def get_id(self) -> str:
79
95
  return self.id
80
96
 
81
- def get_program_id(self):
97
+ def get_program_id(self) -> int:
82
98
  return self.program_id
83
99
 
84
100
  def create_id(self):
@@ -96,9 +112,9 @@ class ShaderWrapper:
96
112
  ),
97
113
  )
98
114
 
99
- def refresh_id(self):
100
- self.program_id = self.create_program_id()
101
- self.id = self.create_id()
115
+ def refresh_id(self) -> None:
116
+ self.program_id: int = self.create_program_id()
117
+ self.id: str = self.create_id()
102
118
 
103
119
  def create_program_id(self):
104
120
  return hash(
@@ -114,7 +130,7 @@ class ShaderWrapper:
114
130
  self.shader_folder / f"{name}.glsl",
115
131
  )
116
132
 
117
- self.program_code = {
133
+ self.program_code: dict[str, str | None] = {
118
134
  "vertex_shader": get_code("vert"),
119
135
  "geometry_shader": get_code("geom"),
120
136
  "fragment_shader": get_code("frag"),
@@ -123,18 +139,18 @@ class ShaderWrapper:
123
139
  def get_program_code(self):
124
140
  return self.program_code
125
141
 
126
- def replace_code(self, old, new):
142
+ def replace_code(self, old: str, new: str) -> None:
127
143
  code_map = self.program_code
128
- for (name, _code) in code_map.items():
144
+ for name, _code in code_map.items():
129
145
  if code_map[name] is None:
130
146
  continue
131
147
  code_map[name] = re.sub(old, new, code_map[name])
132
148
  self.refresh_id()
133
149
 
134
- def combine_with(self, *shader_wrappers):
150
+ def combine_with(self, *shader_wrappers: "ShaderWrapper") -> Self: # noqa: UP037
135
151
  # Assume they are of the same type
136
152
  if len(shader_wrappers) == 0:
137
- return
153
+ return self
138
154
  if self.vert_indices is not None:
139
155
  num_verts = len(self.vert_data)
140
156
  indices_list = [self.vert_indices]
@@ -190,6 +206,6 @@ def get_shader_code_from_file(filename: Path) -> str | None:
190
206
  return result
191
207
 
192
208
 
193
- def get_colormap_code(rgb_list):
209
+ def get_colormap_code(rgb_list: FloatRGBLike_Array) -> str:
194
210
  data = ",".join("vec3({}, {}, {})".format(*rgb) for rgb in rgb_list)
195
211
  return f"vec3[{len(rgb_list)}]({data})"
@@ -1,17 +1,33 @@
1
1
  from __future__ import annotations
2
2
 
3
- import collections
3
+ from collections import defaultdict
4
+ from collections.abc import Iterable, Sequence
5
+ from typing import TYPE_CHECKING
4
6
 
5
7
  import numpy as np
6
8
 
9
+ if TYPE_CHECKING:
10
+ from manim.renderer.opengl_renderer import (
11
+ OpenGLRenderer,
12
+ OpenGLVMobject,
13
+ )
14
+ from manim.typing import MatrixMN
15
+
7
16
  from ..utils import opengl
8
17
  from ..utils.space_ops import cross2d, earclip_triangulation
9
18
  from .shader import Shader
10
19
 
20
+ __all__ = [
21
+ "render_opengl_vectorized_mobject_fill",
22
+ "render_opengl_vectorized_mobject_stroke",
23
+ ]
24
+
11
25
 
12
- def build_matrix_lists(mob):
26
+ def build_matrix_lists(
27
+ mob: OpenGLVMobject,
28
+ ) -> defaultdict[tuple[float, ...], list[OpenGLVMobject]]:
13
29
  root_hierarchical_matrix = mob.hierarchical_model_matrix()
14
- matrix_to_mobject_list = collections.defaultdict(list)
30
+ matrix_to_mobject_list = defaultdict(list)
15
31
  if mob.has_points():
16
32
  matrix_to_mobject_list[tuple(root_hierarchical_matrix.ravel())].append(mob)
17
33
  mobject_to_hierarchical_matrix = {mob: root_hierarchical_matrix}
@@ -31,7 +47,9 @@ def build_matrix_lists(mob):
31
47
  return matrix_to_mobject_list
32
48
 
33
49
 
34
- def render_opengl_vectorized_mobject_fill(renderer, mobject):
50
+ def render_opengl_vectorized_mobject_fill(
51
+ renderer: OpenGLRenderer, mobject: OpenGLVMobject
52
+ ) -> None:
35
53
  matrix_to_mobject_list = build_matrix_lists(mobject)
36
54
 
37
55
  for matrix_tuple, mobject_list in matrix_to_mobject_list.items():
@@ -39,7 +57,11 @@ def render_opengl_vectorized_mobject_fill(renderer, mobject):
39
57
  render_mobject_fills_with_matrix(renderer, model_matrix, mobject_list)
40
58
 
41
59
 
42
- def render_mobject_fills_with_matrix(renderer, model_matrix, mobjects):
60
+ def render_mobject_fills_with_matrix(
61
+ renderer: OpenGLRenderer,
62
+ model_matrix: MatrixMN,
63
+ mobjects: Iterable[OpenGLVMobject],
64
+ ) -> None:
43
65
  # Precompute the total number of vertices for which to reserve space.
44
66
  # Note that triangulate_mobject() will cache its results.
45
67
  total_size = 0
@@ -79,7 +101,7 @@ def render_mobject_fills_with_matrix(renderer, model_matrix, mobjects):
79
101
  )
80
102
  fill_shader.set_uniform(
81
103
  "u_projection_matrix",
82
- renderer.scene.camera.projection_matrix,
104
+ renderer.camera.projection_matrix,
83
105
  )
84
106
 
85
107
  vbo = renderer.context.buffer(attributes.tobytes())
@@ -93,7 +115,7 @@ def render_mobject_fills_with_matrix(renderer, model_matrix, mobjects):
93
115
  vbo.release()
94
116
 
95
117
 
96
- def triangulate_mobject(mob):
118
+ def triangulate_mobject(mob: OpenGLVMobject) -> np.ndarray:
97
119
  if not mob.needs_new_triangulation:
98
120
  return mob.triangulation
99
121
 
@@ -187,14 +209,20 @@ def triangulate_mobject(mob):
187
209
  return attributes
188
210
 
189
211
 
190
- def render_opengl_vectorized_mobject_stroke(renderer, mobject):
212
+ def render_opengl_vectorized_mobject_stroke(
213
+ renderer: OpenGLRenderer, mobject: OpenGLVMobject
214
+ ) -> None:
191
215
  matrix_to_mobject_list = build_matrix_lists(mobject)
192
216
  for matrix_tuple, mobject_list in matrix_to_mobject_list.items():
193
217
  model_matrix = np.array(matrix_tuple).reshape((4, 4))
194
218
  render_mobject_strokes_with_matrix(renderer, model_matrix, mobject_list)
195
219
 
196
220
 
197
- def render_mobject_strokes_with_matrix(renderer, model_matrix, mobjects):
221
+ def render_mobject_strokes_with_matrix(
222
+ renderer: OpenGLRenderer,
223
+ model_matrix: MatrixMN,
224
+ mobjects: Sequence[OpenGLVMobject],
225
+ ) -> None:
198
226
  # Precompute the total number of vertices for which to reserve space.
199
227
  total_size = 0
200
228
  for submob in mobjects:
@@ -274,7 +302,7 @@ def render_mobject_strokes_with_matrix(renderer, model_matrix, mobjects):
274
302
  renderer.camera.unformatted_view_matrix @ model_matrix,
275
303
  ),
276
304
  )
277
- shader.set_uniform("u_projection_matrix", renderer.scene.camera.projection_matrix)
305
+ shader.set_uniform("u_projection_matrix", renderer.camera.projection_matrix)
278
306
  shader.set_uniform("manim_unit_normal", tuple(-mobjects[0].unit_normal[0]))
279
307
 
280
308
  vbo = renderer.context.buffer(stroke_data.tobytes())
@@ -64,14 +64,37 @@ Examples
64
64
  self.play(Restore(self.camera.frame))
65
65
  self.wait()
66
66
 
67
+ .. manim:: SlidingMultipleScenes
68
+
69
+ class SlidingMultipleScenes(MovingCameraScene):
70
+ def construct(self):
71
+ def create_scene(number):
72
+ frame = Rectangle(width=16,height=9)
73
+ circ = Circle().shift(LEFT)
74
+ text = Tex(f"This is Scene {str(number)}").next_to(circ, RIGHT)
75
+ frame.add(circ,text)
76
+ return frame
77
+
78
+ group = VGroup(*(create_scene(i) for i in range(4))).arrange_in_grid(buff=4)
79
+ self.add(group)
80
+ self.camera.auto_zoom(group[0], animate=False)
81
+ for scene in group:
82
+ self.play(self.camera.auto_zoom(scene))
83
+ self.wait()
84
+
85
+ self.play(self.camera.auto_zoom(group, margin=2))
67
86
  """
68
87
 
69
88
  from __future__ import annotations
70
89
 
71
90
  __all__ = ["MovingCameraScene"]
72
91
 
92
+ from typing import Any
93
+
73
94
  from manim.animation.animation import Animation
95
+ from manim.mobject.mobject import Mobject
74
96
 
97
+ from ..camera.camera import Camera
75
98
  from ..camera.moving_camera import MovingCamera
76
99
  from ..scene.scene import Scene
77
100
  from ..utils.family import extract_mobject_family_members
@@ -83,15 +106,21 @@ class MovingCameraScene(Scene):
83
106
  This is a Scene, with special configurations and properties that
84
107
  make it suitable for cases where the camera must be moved around.
85
108
 
109
+ Note: Examples are included in the moving_camera_scene module
110
+ documentation, see below in the 'see also' section.
111
+
86
112
  .. SEEALSO::
87
113
 
114
+ :mod:`.moving_camera_scene`
88
115
  :class:`.MovingCamera`
89
116
  """
90
117
 
91
- def __init__(self, camera_class=MovingCamera, **kwargs):
118
+ def __init__(
119
+ self, camera_class: type[Camera] = MovingCamera, **kwargs: Any
120
+ ) -> None:
92
121
  super().__init__(camera_class=camera_class, **kwargs)
93
122
 
94
- def get_moving_mobjects(self, *animations: Animation):
123
+ def get_moving_mobjects(self, *animations: Animation) -> list[Mobject]:
95
124
  """
96
125
  This method returns a list of all of the Mobjects in the Scene that
97
126
  are moving, that are also in the animations passed.
@@ -103,7 +132,7 @@ class MovingCameraScene(Scene):
103
132
  """
104
133
  moving_mobjects = super().get_moving_mobjects(*animations)
105
134
  all_moving_mobjects = extract_mobject_family_members(moving_mobjects)
106
- movement_indicators = self.renderer.camera.get_mobjects_indicating_movement()
135
+ movement_indicators = self.renderer.camera.get_mobjects_indicating_movement() # type: ignore[union-attr]
107
136
  for movement_indicator in movement_indicators:
108
137
  if movement_indicator in all_moving_mobjects:
109
138
  # When one of these is moving, the camera should