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
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  __all__ = ["ValueTracker", "ComplexValueTracker"]
6
6
 
7
+ from typing import TYPE_CHECKING, Any
7
8
 
8
9
  import numpy as np
9
10
 
@@ -11,6 +12,11 @@ from manim.mobject.mobject import Mobject
11
12
  from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
12
13
  from manim.utils.paths import straight_path
13
14
 
15
+ if TYPE_CHECKING:
16
+ from typing_extensions import Self
17
+
18
+ from manim.typing import PathFuncType
19
+
14
20
 
15
21
  class ValueTracker(Mobject, metaclass=ConvertToOpenGL):
16
22
  """A mobject that can be used for tracking (real-valued) parameters.
@@ -45,7 +51,7 @@ class ValueTracker(Mobject, metaclass=ConvertToOpenGL):
45
51
  self.wait(1)
46
52
  tracker -= 4
47
53
  self.wait(0.5)
48
- self.play(tracker.animate.set_value(5)),
54
+ self.play(tracker.animate.set_value(5))
49
55
  self.wait(0.5)
50
56
  self.play(tracker.animate.set_value(3))
51
57
  self.play(tracker.animate.increment_value(-2))
@@ -69,76 +75,140 @@ class ValueTracker(Mobject, metaclass=ConvertToOpenGL):
69
75
 
70
76
  """
71
77
 
72
- def __init__(self, value=0, **kwargs):
78
+ def __init__(self, value: float = 0, **kwargs: Any) -> None:
73
79
  super().__init__(**kwargs)
74
- self.set_points(np.zeros((1, 3)))
80
+ self.set(points=np.zeros((1, 3)))
75
81
  self.set_value(value)
76
82
 
77
83
  def get_value(self) -> float:
78
84
  """Get the current value of this ValueTracker."""
79
- return self.points[0, 0]
85
+ value: float = self.points[0, 0]
86
+ return value
80
87
 
81
- def set_value(self, value: float):
82
- """Sets a new scalar value to the ValueTracker"""
88
+ def set_value(self, value: float) -> Self:
89
+ """Sets a new scalar value to the ValueTracker."""
83
90
  self.points[0, 0] = value
84
91
  return self
85
92
 
86
- def increment_value(self, d_value: float):
87
- """Increments (adds) a scalar value to the ValueTracker"""
93
+ def increment_value(self, d_value: float) -> Self:
94
+ """Increments (adds) a scalar value to the ValueTracker."""
88
95
  self.set_value(self.get_value() + d_value)
89
96
  return self
90
97
 
91
- def __bool__(self):
92
- """Return whether the value of this value tracker evaluates as true."""
98
+ def __bool__(self) -> bool:
99
+ """Return whether the value of this ValueTracker evaluates as true."""
93
100
  return bool(self.get_value())
94
101
 
95
- def __iadd__(self, d_value: float):
96
- """adds ``+=`` syntax to increment the value of the ValueTracker"""
102
+ def __add__(self, d_value: float | Mobject) -> ValueTracker:
103
+ """Return a new :class:`ValueTracker` whose value is the current tracker's value plus
104
+ ``d_value``.
105
+ """
106
+ if isinstance(d_value, Mobject):
107
+ raise ValueError(
108
+ "Cannot increment ValueTracker by a Mobject. Please provide a scalar value."
109
+ )
110
+ return ValueTracker(self.get_value() + d_value)
111
+
112
+ def __iadd__(self, d_value: float | Mobject) -> Self:
113
+ """adds ``+=`` syntax to increment the value of the ValueTracker."""
114
+ if isinstance(d_value, Mobject):
115
+ raise ValueError(
116
+ "Cannot increment ValueTracker by a Mobject. Please provide a scalar value."
117
+ )
97
118
  self.increment_value(d_value)
98
119
  return self
99
120
 
100
- def __ifloordiv__(self, d_value: float):
101
- """Set the value of this value tracker to the floor division of the current value by ``d_value``."""
121
+ def __floordiv__(self, d_value: float) -> ValueTracker:
122
+ """Return a new :class:`ValueTracker` whose value is the floor division of the current
123
+ tracker's value by ``d_value``.
124
+ """
125
+ return ValueTracker(self.get_value() // d_value)
126
+
127
+ def __ifloordiv__(self, d_value: float) -> Self:
128
+ """Set the value of this ValueTracker to the floor division of the current value by ``d_value``."""
102
129
  self.set_value(self.get_value() // d_value)
103
130
  return self
104
131
 
105
- def __imod__(self, d_value: float):
106
- """Set the value of this value tracker to the current value modulo ``d_value``."""
132
+ def __mod__(self, d_value: float) -> ValueTracker:
133
+ """Return a new :class:`ValueTracker` whose value is the current tracker's value
134
+ modulo ``d_value``.
135
+ """
136
+ return ValueTracker(self.get_value() % d_value)
137
+
138
+ def __imod__(self, d_value: float) -> Self:
139
+ """Set the value of this ValueTracker to the current value modulo ``d_value``."""
107
140
  self.set_value(self.get_value() % d_value)
108
141
  return self
109
142
 
110
- def __imul__(self, d_value: float):
111
- """Set the value of this value tracker to the product of the current value and ``d_value``."""
143
+ def __mul__(self, d_value: float) -> ValueTracker:
144
+ """Return a new :class:`ValueTracker` whose value is the current tracker's value multiplied by
145
+ ``d_value``.
146
+ """
147
+ return ValueTracker(self.get_value() * d_value)
148
+
149
+ def __imul__(self, d_value: float) -> Self:
150
+ """Set the value of this ValueTracker to the product of the current value and ``d_value``."""
112
151
  self.set_value(self.get_value() * d_value)
113
152
  return self
114
153
 
115
- def __ipow__(self, d_value: float):
116
- """Set the value of this value tracker to the current value raised to the power of ``d_value``."""
154
+ def __pow__(self, d_value: float) -> ValueTracker:
155
+ """Return a new :class:`ValueTracker` whose value is the current tracker's value raised to the
156
+ power of ``d_value``.
157
+ """
158
+ return ValueTracker(self.get_value() ** d_value)
159
+
160
+ def __ipow__(self, d_value: float) -> Self:
161
+ """Set the value of this ValueTracker to the current value raised to the power of ``d_value``."""
117
162
  self.set_value(self.get_value() ** d_value)
118
163
  return self
119
164
 
120
- def __isub__(self, d_value: float):
121
- """adds ``-=`` syntax to decrement the value of the ValueTracker"""
165
+ def __sub__(self, d_value: float | Mobject) -> ValueTracker:
166
+ """Return a new :class:`ValueTracker` whose value is the current tracker's value minus
167
+ ``d_value``.
168
+ """
169
+ if isinstance(d_value, Mobject):
170
+ raise ValueError(
171
+ "Cannot decrement ValueTracker by a Mobject. Please provide a scalar value."
172
+ )
173
+ return ValueTracker(self.get_value() - d_value)
174
+
175
+ def __isub__(self, d_value: float | Mobject) -> Self:
176
+ """Adds ``-=`` syntax to decrement the value of the ValueTracker."""
177
+ if isinstance(d_value, Mobject):
178
+ raise ValueError(
179
+ "Cannot decrement ValueTracker by a Mobject. Please provide a scalar value."
180
+ )
122
181
  self.increment_value(-d_value)
123
182
  return self
124
183
 
125
- def __itruediv__(self, d_value: float):
126
- """Sets the value of this value tracker to the current value divided by ``d_value``."""
184
+ def __truediv__(self, d_value: float) -> ValueTracker:
185
+ """Return a new :class:`ValueTracker` whose value is the current tracker's value
186
+ divided by ``d_value``.
187
+ """
188
+ return ValueTracker(self.get_value() / d_value)
189
+
190
+ def __itruediv__(self, d_value: float) -> Self:
191
+ """Sets the value of this ValueTracker to the current value divided by ``d_value``."""
127
192
  self.set_value(self.get_value() / d_value)
128
193
  return self
129
194
 
130
- def interpolate(self, mobject1, mobject2, alpha, path_func=straight_path()):
131
- """
132
- Turns self into an interpolation between mobject1
133
- and mobject2.
134
- """
135
- self.set_points(path_func(mobject1.points, mobject2.points, alpha))
195
+ def interpolate(
196
+ self,
197
+ mobject1: Mobject,
198
+ mobject2: Mobject,
199
+ alpha: float,
200
+ path_func: PathFuncType = straight_path(),
201
+ ) -> Self:
202
+ """Turns ``self`` into an interpolation between ``mobject1`` and ``mobject2``."""
203
+ self.set(points=path_func(mobject1.points, mobject2.points, alpha))
136
204
  return self
137
205
 
138
206
 
139
207
  class ComplexValueTracker(ValueTracker):
140
208
  """Tracks a complex-valued parameter.
141
209
 
210
+ The value is internally stored as a points array [a, b, 0]. This can be accessed directly
211
+ to represent the value geometrically, see the usage example.
142
212
  When the value is set through :attr:`animate`, the value will take a straight path from the
143
213
  source point to the destination point.
144
214
 
@@ -161,15 +231,12 @@ class ComplexValueTracker(ValueTracker):
161
231
  self.play(tracker.animate.set_value(tracker.get_value() / (-2 + 3j)))
162
232
  """
163
233
 
164
- def get_value(self):
165
- """Get the current value of this value tracker as a complex number.
166
-
167
- The value is internally stored as a points array [a, b, 0]. This can be accessed directly
168
- to represent the value geometrically, see the usage example."""
234
+ def get_value(self) -> complex: # type: ignore [override]
235
+ """Get the current value of this ComplexValueTracker as a complex number."""
169
236
  return complex(*self.points[0, :2])
170
237
 
171
- def set_value(self, z):
172
- """Sets a new complex value to the ComplexValueTracker"""
173
- z = complex(z)
238
+ def set_value(self, value: complex | float) -> Self:
239
+ """Sets a new complex value to the ComplexValueTracker."""
240
+ z = complex(value)
174
241
  self.points[0, :2] = (z.real, z.imag)
175
242
  return self
@@ -10,11 +10,11 @@ __all__ = [
10
10
 
11
11
  import itertools as it
12
12
  import random
13
+ from collections.abc import Callable, Iterable, Sequence
13
14
  from math import ceil, floor
14
- from typing import Callable, Iterable, Sequence
15
+ from typing import TYPE_CHECKING
15
16
 
16
17
  import numpy as np
17
- from colour import Color
18
18
  from PIL import Image
19
19
 
20
20
  from manim.animation.updaters.update import UpdateFromAlphaFunc
@@ -30,10 +30,28 @@ from ..mobject.mobject import Mobject
30
30
  from ..mobject.types.vectorized_mobject import VGroup
31
31
  from ..mobject.utils import get_vectorized_mobject_class
32
32
  from ..utils.bezier import interpolate, inverse_interpolate
33
- from ..utils.color import BLUE_E, GREEN, RED, YELLOW, color_to_rgb, rgb_to_color
33
+ from ..utils.color import (
34
+ BLUE_E,
35
+ GREEN,
36
+ RED,
37
+ YELLOW,
38
+ ManimColor,
39
+ ParsableManimColor,
40
+ color_to_rgb,
41
+ rgb_to_color,
42
+ )
34
43
  from ..utils.rate_functions import ease_out_sine, linear
35
44
  from ..utils.simple_functions import sigmoid
36
45
 
46
+ if TYPE_CHECKING:
47
+ from manim.typing import (
48
+ FloatRGB,
49
+ FloatRGB_Array,
50
+ FloatRGBA_Array,
51
+ Point3D,
52
+ Vector3D,
53
+ )
54
+
37
55
  DEFAULT_SCALAR_FIELD_COLORS: list = [BLUE_E, GREEN, YELLOW, RED]
38
56
 
39
57
 
@@ -65,12 +83,12 @@ class VectorField(VGroup):
65
83
 
66
84
  def __init__(
67
85
  self,
68
- func: Callable[[np.ndarray], np.ndarray],
69
- color: Color | None = None,
70
- color_scheme: Callable[[np.ndarray], float] | None = None,
86
+ func: Callable[[Point3D], Vector3D],
87
+ color: ParsableManimColor | None = None,
88
+ color_scheme: Callable[[Vector3D], float] | None = None,
71
89
  min_color_scheme_value: float = 0,
72
90
  max_color_scheme_value: float = 2,
73
- colors: Sequence[Color] = DEFAULT_SCALAR_FIELD_COLORS,
91
+ colors: Sequence[ParsableManimColor] = DEFAULT_SCALAR_FIELD_COLORS,
74
92
  **kwargs,
75
93
  ):
76
94
  super().__init__(**kwargs)
@@ -79,13 +97,13 @@ class VectorField(VGroup):
79
97
  self.single_color = False
80
98
  if color_scheme is None:
81
99
 
82
- def color_scheme(p):
83
- return np.linalg.norm(p)
100
+ def color_scheme(vec: Vector3D) -> float:
101
+ return np.linalg.norm(vec)
84
102
 
85
103
  self.color_scheme = color_scheme # TODO maybe other default for direction?
86
- self.rgbs = np.array(list(map(color_to_rgb, colors)))
104
+ self.rgbs: FloatRGB_Array = np.array(list(map(color_to_rgb, colors)))
87
105
 
88
- def pos_to_rgb(pos: np.ndarray) -> tuple[float, float, float, float]:
106
+ def pos_to_rgb(pos: Point3D) -> FloatRGB:
89
107
  vec = self.func(pos)
90
108
  color_value = np.clip(
91
109
  self.color_scheme(vec),
@@ -98,8 +116,8 @@ class VectorField(VGroup):
98
116
  color_value,
99
117
  )
100
118
  alpha *= len(self.rgbs) - 1
101
- c1 = self.rgbs[int(alpha)]
102
- c2 = self.rgbs[min(int(alpha + 1), len(self.rgbs) - 1)]
119
+ c1: FloatRGB = self.rgbs[int(alpha)]
120
+ c2: FloatRGB = self.rgbs[min(int(alpha + 1), len(self.rgbs) - 1)]
103
121
  alpha %= 1
104
122
  return interpolate(c1, c2, alpha)
105
123
 
@@ -107,7 +125,7 @@ class VectorField(VGroup):
107
125
  self.pos_to_color = lambda pos: rgb_to_color(self.pos_to_rgb(pos))
108
126
  else:
109
127
  self.single_color = True
110
- self.color = color
128
+ self.color = ManimColor.parse(color)
111
129
  self.submob_movement_updater = None
112
130
 
113
131
  @staticmethod
@@ -344,7 +362,6 @@ class VectorField(VGroup):
344
362
  This vector field.
345
363
 
346
364
  """
347
-
348
365
  self.stop_submobject_movement()
349
366
  self.submob_movement_updater = lambda mob, dt: mob.nudge_submobjects(
350
367
  dt * speed,
@@ -409,8 +426,8 @@ class VectorField(VGroup):
409
426
  self,
410
427
  start: float,
411
428
  end: float,
412
- colors: Iterable,
413
- ):
429
+ colors: Iterable[ParsableManimColor],
430
+ ) -> Callable[[Sequence[float], float], FloatRGBA_Array]:
414
431
  """
415
432
  Generates a gradient of rgbas as a numpy array
416
433
 
@@ -427,9 +444,9 @@ class VectorField(VGroup):
427
444
  -------
428
445
  function to generate the gradients as numpy arrays representing rgba values
429
446
  """
430
- rgbs = np.array([color_to_rgb(c) for c in colors])
447
+ rgbs: FloatRGB_Array = np.array([color_to_rgb(c) for c in colors])
431
448
 
432
- def func(values, opacity=1):
449
+ def func(values: Sequence[float], opacity: float = 1.0) -> FloatRGBA_Array:
433
450
  alphas = inverse_interpolate(start, end, np.array(values))
434
451
  alphas = np.clip(alphas, 0, 1)
435
452
  scaled_alphas = alphas * (len(rgbs) - 1)
@@ -437,12 +454,14 @@ class VectorField(VGroup):
437
454
  next_indices = np.clip(indices + 1, 0, len(rgbs) - 1)
438
455
  inter_alphas = scaled_alphas % 1
439
456
  inter_alphas = inter_alphas.repeat(3).reshape((len(indices), 3))
440
- result = interpolate(rgbs[indices], rgbs[next_indices], inter_alphas)
441
- result = np.concatenate(
442
- (result, np.full([len(result), 1], opacity)),
457
+ new_rgbs: FloatRGB_Array = interpolate(
458
+ rgbs[indices], rgbs[next_indices], inter_alphas
459
+ )
460
+ new_rgbas: FloatRGBA_Array = np.concatenate(
461
+ (new_rgbs, np.full([len(new_rgbs), 1], opacity)),
443
462
  axis=1,
444
463
  )
445
- return result
464
+ return new_rgbas
446
465
 
447
466
  return func
448
467
 
@@ -533,11 +552,11 @@ class ArrowVectorField(VectorField):
533
552
  def __init__(
534
553
  self,
535
554
  func: Callable[[np.ndarray], np.ndarray],
536
- color: Color | None = None,
555
+ color: ParsableManimColor | None = None,
537
556
  color_scheme: Callable[[np.ndarray], float] | None = None,
538
557
  min_color_scheme_value: float = 0,
539
558
  max_color_scheme_value: float = 2,
540
- colors: Sequence[Color] = DEFAULT_SCALAR_FIELD_COLORS,
559
+ colors: Sequence[ParsableManimColor] = DEFAULT_SCALAR_FIELD_COLORS,
541
560
  # Determining Vector positions:
542
561
  x_range: Sequence[float] = None,
543
562
  y_range: Sequence[float] = None,
@@ -613,7 +632,7 @@ class ArrowVectorField(VectorField):
613
632
  The root point of the vector.
614
633
 
615
634
  """
616
- output = np.asarray(self.func(point))
635
+ output = np.array(self.func(point))
617
636
  norm = np.linalg.norm(output)
618
637
  if norm != 0:
619
638
  output *= self.length_func(norm) / norm
@@ -707,11 +726,11 @@ class StreamLines(VectorField):
707
726
  def __init__(
708
727
  self,
709
728
  func: Callable[[np.ndarray], np.ndarray],
710
- color: Color | None = None,
729
+ color: ParsableManimColor | None = None,
711
730
  color_scheme: Callable[[np.ndarray], float] | None = None,
712
731
  min_color_scheme_value: float = 0,
713
732
  max_color_scheme_value: float = 2,
714
- colors: Sequence[Color] = DEFAULT_SCALAR_FIELD_COLORS,
733
+ colors: Sequence[ParsableManimColor] = DEFAULT_SCALAR_FIELD_COLORS,
715
734
  # Determining stream line starting positions:
716
735
  x_range: Sequence[float] = None,
717
736
  y_range: Sequence[float] = None,
@@ -821,7 +840,9 @@ class StreamLines(VectorField):
821
840
  step = max(1, int(len(points) / self.max_anchors_per_line))
822
841
  line.set_points_smoothly(points[::step])
823
842
  if self.single_color:
824
- line.set_stroke(self.color)
843
+ line.set_stroke(
844
+ color=self.color, width=self.stroke_width, opacity=opacity
845
+ )
825
846
  else:
826
847
  if config.renderer == RendererType.OPENGL:
827
848
  # scaled for compatibility with cairo
@@ -940,7 +961,6 @@ class StreamLines(VectorField):
940
961
  self.wait(stream_lines.virtual_time / stream_lines.flow_speed)
941
962
 
942
963
  """
943
-
944
964
  for line in self.stream_lines:
945
965
  run_time = line.duration / flow_speed
946
966
  line.anim = line_animation_class(
@@ -1000,7 +1020,6 @@ class StreamLines(VectorField):
1000
1020
  self.play(stream_lines.end_animation())
1001
1021
 
1002
1022
  """
1003
-
1004
1023
  if self.flow_animation is None:
1005
1024
  raise ValueError("You have to start the animation before fading it out.")
1006
1025
 
manim/opengl/__init__.py CHANGED
@@ -1,9 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- try:
3
+ import contextlib
4
+
5
+ with contextlib.suppress(ImportError):
4
6
  from dearpygui import dearpygui as dpg
5
- except ImportError:
6
- pass
7
7
 
8
8
 
9
9
  from manim.mobject.opengl.dot_cloud import *
manim/plugins/__init__.py CHANGED
@@ -1,3 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
- from .import_plugins import *
3
+ from manim._config import config, logger
4
+ from manim.plugins.plugins_flags import get_plugins, list_plugins
5
+
6
+ __all__ = [
7
+ "get_plugins",
8
+ "list_plugins",
9
+ ]
10
+
11
+ requested_plugins: set[str] = set(config["plugins"])
12
+ missing_plugins = requested_plugins - set(get_plugins().keys())
13
+
14
+
15
+ if missing_plugins:
16
+ logger.warning("Missing Plugins: %s", missing_plugins)
@@ -1,30 +1,26 @@
1
- """
2
- plugins_flags.py
3
- ------------
4
-
5
- Plugin Managing Utility.
6
- """
1
+ """Plugin Managing Utility"""
7
2
 
8
3
  from __future__ import annotations
9
4
 
10
- import pkg_resources
5
+ from importlib.metadata import entry_points
6
+ from typing import Any
11
7
 
12
- from manim import console
8
+ from manim._config import console
13
9
 
14
10
  __all__ = ["list_plugins"]
15
11
 
16
12
 
17
- def get_plugins():
18
- plugins = {
13
+ def get_plugins() -> dict[str, Any]:
14
+ plugins: dict[str, Any] = {
19
15
  entry_point.name: entry_point.load()
20
- for entry_point in pkg_resources.iter_entry_points("manim.plugins")
16
+ for entry_point in entry_points(group="manim.plugins")
21
17
  }
22
18
  return plugins
23
19
 
24
20
 
25
- def list_plugins():
21
+ def list_plugins() -> None:
26
22
  console.print("[green bold]Plugins:[/green bold]", justify="left")
27
23
 
28
24
  plugins = get_plugins()
29
- for plugin in plugins:
30
- console.print(f" • {plugin}")
25
+ for plugin_name in plugins:
26
+ console.print(f" • {plugin_name}")