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.
- manim/__init__.py +11 -6
- manim/__main__.py +62 -19
- manim/_config/__init__.py +10 -9
- manim/_config/cli_colors.py +26 -9
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +23 -13
- manim/_config/utils.py +662 -468
- manim/animation/animation.py +164 -18
- manim/animation/changing.py +34 -23
- manim/animation/composition.py +265 -67
- manim/animation/creation.py +208 -26
- manim/animation/fading.py +16 -18
- manim/animation/growing.py +35 -15
- manim/animation/indication.py +150 -76
- manim/animation/movement.py +56 -22
- manim/animation/numbers.py +64 -6
- manim/animation/rotation.py +78 -7
- manim/animation/specialized.py +6 -7
- manim/animation/speedmodifier.py +13 -10
- manim/animation/transform.py +14 -11
- manim/animation/transform_matching_parts.py +3 -4
- manim/animation/updaters/mobject_update_utils.py +152 -30
- manim/animation/updaters/update.py +10 -7
- manim/camera/camera.py +182 -118
- manim/camera/mapping_camera.py +34 -3
- manim/camera/moving_camera.py +95 -74
- manim/camera/multi_camera.py +23 -15
- manim/camera/three_d_camera.py +70 -52
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +76 -44
- manim/cli/checkhealth/checks.py +192 -0
- manim/cli/checkhealth/commands.py +90 -0
- manim/cli/default_group.py +158 -25
- manim/cli/init/commands.py +33 -25
- manim/cli/plugins/commands.py +16 -3
- manim/cli/render/commands.py +72 -60
- manim/cli/render/ease_of_access_options.py +4 -3
- manim/cli/render/global_options.py +59 -17
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +98 -33
- manim/constants.py +109 -59
- manim/data_structures.py +31 -0
- manim/mobject/frame.py +8 -5
- manim/mobject/geometry/__init__.py +1 -0
- manim/mobject/geometry/arc.py +277 -135
- manim/mobject/geometry/boolean_ops.py +32 -31
- manim/mobject/geometry/labeled.py +376 -0
- manim/mobject/geometry/line.py +192 -87
- manim/mobject/geometry/polygram.py +224 -58
- manim/mobject/geometry/shape_matchers.py +61 -25
- manim/mobject/geometry/tips.py +122 -48
- manim/mobject/graph.py +1027 -419
- manim/mobject/graphing/coordinate_systems.py +533 -278
- manim/mobject/graphing/functions.py +53 -32
- manim/mobject/graphing/number_line.py +123 -65
- manim/mobject/graphing/probability.py +88 -62
- manim/mobject/graphing/scale.py +33 -19
- manim/mobject/logo.py +118 -28
- manim/mobject/matrix.py +87 -83
- manim/mobject/mobject.py +912 -442
- manim/mobject/opengl/dot_cloud.py +16 -5
- manim/mobject/opengl/opengl_compatibility.py +4 -2
- manim/mobject/opengl/opengl_geometry.py +254 -153
- manim/mobject/opengl/opengl_image_mobject.py +3 -1
- manim/mobject/opengl/opengl_mobject.py +779 -482
- manim/mobject/opengl/opengl_point_cloud_mobject.py +41 -14
- manim/mobject/opengl/opengl_surface.py +14 -92
- manim/mobject/opengl/opengl_three_dimensions.py +12 -8
- manim/mobject/opengl/opengl_vectorized_mobject.py +98 -100
- manim/mobject/svg/brace.py +173 -41
- manim/mobject/svg/svg_mobject.py +139 -53
- manim/mobject/table.py +61 -68
- manim/mobject/text/code_mobject.py +193 -539
- manim/mobject/text/numbers.py +81 -34
- manim/mobject/text/tex_mobject.py +130 -78
- manim/mobject/text/text_mobject.py +288 -164
- manim/mobject/three_d/polyhedra.py +111 -13
- manim/mobject/three_d/three_d_utils.py +17 -8
- manim/mobject/three_d/three_dimensions.py +239 -106
- manim/mobject/types/image_mobject.py +50 -30
- manim/mobject/types/point_cloud_mobject.py +120 -75
- manim/mobject/types/vectorized_mobject.py +841 -408
- manim/mobject/value_tracker.py +105 -38
- manim/mobject/vector_field.py +50 -31
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +10 -14
- manim/renderer/cairo_renderer.py +65 -50
- manim/renderer/opengl_renderer.py +89 -69
- manim/renderer/opengl_renderer_window.py +39 -18
- manim/renderer/shader.py +123 -87
- manim/renderer/shader_wrapper.py +44 -28
- manim/renderer/vectorized_mobject_rendering.py +38 -10
- manim/scene/moving_camera_scene.py +32 -3
- manim/scene/scene.py +507 -242
- manim/scene/scene_file_writer.py +371 -220
- manim/scene/section.py +20 -16
- manim/scene/three_d_scene.py +14 -22
- manim/scene/vector_space_scene.py +223 -129
- manim/scene/zoomed_scene.py +46 -41
- manim/typing.py +990 -0
- manim/utils/bezier.py +1823 -371
- manim/utils/caching.py +12 -5
- manim/utils/color/AS2700.py +236 -0
- manim/utils/color/BS381.py +318 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +533 -0
- manim/utils/color/XKCD.py +952 -0
- manim/utils/color/__init__.py +61 -0
- manim/utils/color/core.py +1667 -0
- manim/utils/color/manim_colors.py +218 -0
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +39 -19
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +86 -39
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +236 -0
- manim/utils/docbuild/autocolor_directive.py +99 -0
- manim/utils/docbuild/manim_directive.py +94 -41
- manim/utils/docbuild/module_parsing.py +245 -0
- manim/utils/exceptions.py +6 -0
- manim/utils/family.py +5 -3
- manim/utils/family_ops.py +17 -4
- manim/utils/file_ops.py +27 -17
- manim/utils/hashing.py +55 -45
- manim/utils/images.py +13 -7
- manim/utils/ipython_magic.py +13 -7
- manim/utils/iterables.py +163 -120
- manim/utils/module_ops.py +66 -24
- manim/utils/opengl.py +77 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +30 -33
- manim/utils/polylabel.py +235 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +98 -32
- manim/utils/simple_functions.py +25 -33
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +188 -115
- manim/utils/testing/__init__.py +17 -0
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +34 -18
- manim/utils/testing/frames_comparison.py +37 -19
- manim/utils/tex.py +130 -198
- manim/utils/tex_file_writing.py +77 -47
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/METADATA +64 -65
- manim-0.19.1.dist-info/RECORD +220 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/WHEEL +1 -1
- manim-0.19.1.dist-info/entry_points.txt +3 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE.community +1 -1
- manim/cli/new/group.py +0 -189
- manim/communitycolors.py +0 -9
- manim/gui/__init__.py +0 -0
- manim/gui/gui.py +0 -82
- manim/plugins/import_plugins.py +0 -43
- manim/utils/color.py +0 -552
- manim-0.17.0.dist-info/RECORD +0 -206
- manim-0.17.0.dist-info/entry_points.txt +0 -4
- /manim/cli/{new → checkhealth}/__init__.py +0 -0
- {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE +0 -0
manim/camera/three_d_camera.py
CHANGED
|
@@ -5,7 +5,8 @@ from __future__ import annotations
|
|
|
5
5
|
__all__ = ["ThreeDCamera"]
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from collections.abc import Callable, Iterable
|
|
9
|
+
from typing import Any
|
|
9
10
|
|
|
10
11
|
import numpy as np
|
|
11
12
|
|
|
@@ -16,7 +17,15 @@ from manim.mobject.three_d.three_d_utils import (
|
|
|
16
17
|
get_3d_vmob_start_corner,
|
|
17
18
|
get_3d_vmob_start_corner_unit_normal,
|
|
18
19
|
)
|
|
20
|
+
from manim.mobject.types.vectorized_mobject import VMobject
|
|
19
21
|
from manim.mobject.value_tracker import ValueTracker
|
|
22
|
+
from manim.typing import (
|
|
23
|
+
FloatRGBA_Array,
|
|
24
|
+
MatrixMN,
|
|
25
|
+
Point3D,
|
|
26
|
+
Point3D_Array,
|
|
27
|
+
Point3DLike,
|
|
28
|
+
)
|
|
20
29
|
|
|
21
30
|
from .. import config
|
|
22
31
|
from ..camera.camera import Camera
|
|
@@ -30,17 +39,17 @@ from ..utils.space_ops import rotation_about_z, rotation_matrix
|
|
|
30
39
|
class ThreeDCamera(Camera):
|
|
31
40
|
def __init__(
|
|
32
41
|
self,
|
|
33
|
-
focal_distance=20.0,
|
|
34
|
-
shading_factor=0.2,
|
|
35
|
-
default_distance=5.0,
|
|
36
|
-
light_source_start_point=9 * DOWN + 7 * LEFT + 10 * OUT,
|
|
37
|
-
should_apply_shading=True,
|
|
38
|
-
exponential_projection=False,
|
|
39
|
-
phi=0,
|
|
40
|
-
theta
|
|
41
|
-
gamma=0,
|
|
42
|
-
zoom=1,
|
|
43
|
-
**kwargs,
|
|
42
|
+
focal_distance: float = 20.0,
|
|
43
|
+
shading_factor: float = 0.2,
|
|
44
|
+
default_distance: float = 5.0,
|
|
45
|
+
light_source_start_point: Point3DLike = 9 * DOWN + 7 * LEFT + 10 * OUT,
|
|
46
|
+
should_apply_shading: bool = True,
|
|
47
|
+
exponential_projection: bool = False,
|
|
48
|
+
phi: float = 0,
|
|
49
|
+
theta: float = -90 * DEGREES,
|
|
50
|
+
gamma: float = 0,
|
|
51
|
+
zoom: float = 1,
|
|
52
|
+
**kwargs: Any,
|
|
44
53
|
):
|
|
45
54
|
"""Initializes the ThreeDCamera
|
|
46
55
|
|
|
@@ -68,24 +77,25 @@ class ThreeDCamera(Camera):
|
|
|
68
77
|
self.focal_distance_tracker = ValueTracker(self.focal_distance)
|
|
69
78
|
self.gamma_tracker = ValueTracker(self.gamma)
|
|
70
79
|
self.zoom_tracker = ValueTracker(self.zoom)
|
|
71
|
-
self.fixed_orientation_mobjects = {}
|
|
72
|
-
self.fixed_in_frame_mobjects = set()
|
|
80
|
+
self.fixed_orientation_mobjects: dict[Mobject, Callable[[], Point3D]] = {}
|
|
81
|
+
self.fixed_in_frame_mobjects: set[Mobject] = set()
|
|
73
82
|
self.reset_rotation_matrix()
|
|
74
83
|
|
|
75
84
|
@property
|
|
76
|
-
def frame_center(self):
|
|
85
|
+
def frame_center(self) -> Point3D:
|
|
77
86
|
return self._frame_center.points[0]
|
|
78
87
|
|
|
79
88
|
@frame_center.setter
|
|
80
|
-
def frame_center(self, point):
|
|
89
|
+
def frame_center(self, point: Point3DLike) -> None:
|
|
81
90
|
self._frame_center.move_to(point)
|
|
82
91
|
|
|
83
|
-
def capture_mobjects(self, mobjects, **kwargs):
|
|
92
|
+
def capture_mobjects(self, mobjects: Iterable[Mobject], **kwargs: Any) -> None:
|
|
84
93
|
self.reset_rotation_matrix()
|
|
85
94
|
super().capture_mobjects(mobjects, **kwargs)
|
|
86
95
|
|
|
87
|
-
def get_value_trackers(self):
|
|
88
|
-
"""
|
|
96
|
+
def get_value_trackers(self) -> list[ValueTracker]:
|
|
97
|
+
"""A list of :class:`ValueTrackers <.ValueTracker>` of phi, theta, focal_distance,
|
|
98
|
+
gamma and zoom.
|
|
89
99
|
|
|
90
100
|
Returns
|
|
91
101
|
-------
|
|
@@ -100,7 +110,9 @@ class ThreeDCamera(Camera):
|
|
|
100
110
|
self.zoom_tracker,
|
|
101
111
|
]
|
|
102
112
|
|
|
103
|
-
def modified_rgbas(
|
|
113
|
+
def modified_rgbas(
|
|
114
|
+
self, vmobject: VMobject, rgbas: FloatRGBA_Array
|
|
115
|
+
) -> FloatRGBA_Array:
|
|
104
116
|
if not self.should_apply_shading:
|
|
105
117
|
return rgbas
|
|
106
118
|
if vmobject.shade_in_3d and (vmobject.get_num_points() > 0):
|
|
@@ -126,28 +138,33 @@ class ThreeDCamera(Camera):
|
|
|
126
138
|
|
|
127
139
|
def get_stroke_rgbas(
|
|
128
140
|
self,
|
|
129
|
-
vmobject,
|
|
130
|
-
background=False,
|
|
131
|
-
): # NOTE : DocStrings From parent
|
|
141
|
+
vmobject: VMobject,
|
|
142
|
+
background: bool = False,
|
|
143
|
+
) -> FloatRGBA_Array: # NOTE : DocStrings From parent
|
|
132
144
|
return self.modified_rgbas(vmobject, vmobject.get_stroke_rgbas(background))
|
|
133
145
|
|
|
134
|
-
def get_fill_rgbas(
|
|
146
|
+
def get_fill_rgbas(
|
|
147
|
+
self, vmobject: VMobject
|
|
148
|
+
) -> FloatRGBA_Array: # NOTE : DocStrings From parent
|
|
135
149
|
return self.modified_rgbas(vmobject, vmobject.get_fill_rgbas())
|
|
136
150
|
|
|
137
|
-
def get_mobjects_to_display(
|
|
151
|
+
def get_mobjects_to_display(
|
|
152
|
+
self, *args: Any, **kwargs: Any
|
|
153
|
+
) -> list[Mobject]: # NOTE : DocStrings From parent
|
|
138
154
|
mobjects = super().get_mobjects_to_display(*args, **kwargs)
|
|
139
155
|
rot_matrix = self.get_rotation_matrix()
|
|
140
156
|
|
|
141
|
-
def z_key(mob):
|
|
157
|
+
def z_key(mob: Mobject) -> float:
|
|
142
158
|
if not (hasattr(mob, "shade_in_3d") and mob.shade_in_3d):
|
|
143
|
-
return np.inf
|
|
159
|
+
return np.inf # type: ignore[no-any-return]
|
|
144
160
|
# Assign a number to a three dimensional mobjects
|
|
145
161
|
# based on how close it is to the camera
|
|
146
|
-
|
|
162
|
+
distance: float = np.dot(mob.get_z_index_reference_point(), rot_matrix.T)[2]
|
|
163
|
+
return distance
|
|
147
164
|
|
|
148
165
|
return sorted(mobjects, key=z_key)
|
|
149
166
|
|
|
150
|
-
def get_phi(self):
|
|
167
|
+
def get_phi(self) -> float:
|
|
151
168
|
"""Returns the Polar angle (the angle off Z_AXIS) phi.
|
|
152
169
|
|
|
153
170
|
Returns
|
|
@@ -157,7 +174,7 @@ class ThreeDCamera(Camera):
|
|
|
157
174
|
"""
|
|
158
175
|
return self.phi_tracker.get_value()
|
|
159
176
|
|
|
160
|
-
def get_theta(self):
|
|
177
|
+
def get_theta(self) -> float:
|
|
161
178
|
"""Returns the Azimuthal i.e the angle that spins the camera around the Z_AXIS.
|
|
162
179
|
|
|
163
180
|
Returns
|
|
@@ -167,7 +184,7 @@ class ThreeDCamera(Camera):
|
|
|
167
184
|
"""
|
|
168
185
|
return self.theta_tracker.get_value()
|
|
169
186
|
|
|
170
|
-
def get_focal_distance(self):
|
|
187
|
+
def get_focal_distance(self) -> float:
|
|
171
188
|
"""Returns focal_distance of the Camera.
|
|
172
189
|
|
|
173
190
|
Returns
|
|
@@ -177,7 +194,7 @@ class ThreeDCamera(Camera):
|
|
|
177
194
|
"""
|
|
178
195
|
return self.focal_distance_tracker.get_value()
|
|
179
196
|
|
|
180
|
-
def get_gamma(self):
|
|
197
|
+
def get_gamma(self) -> float:
|
|
181
198
|
"""Returns the rotation of the camera about the vector from the ORIGIN to the Camera.
|
|
182
199
|
|
|
183
200
|
Returns
|
|
@@ -188,7 +205,7 @@ class ThreeDCamera(Camera):
|
|
|
188
205
|
"""
|
|
189
206
|
return self.gamma_tracker.get_value()
|
|
190
207
|
|
|
191
|
-
def get_zoom(self):
|
|
208
|
+
def get_zoom(self) -> float:
|
|
192
209
|
"""Returns the zoom amount of the camera.
|
|
193
210
|
|
|
194
211
|
Returns
|
|
@@ -198,7 +215,7 @@ class ThreeDCamera(Camera):
|
|
|
198
215
|
"""
|
|
199
216
|
return self.zoom_tracker.get_value()
|
|
200
217
|
|
|
201
|
-
def set_phi(self, value: float):
|
|
218
|
+
def set_phi(self, value: float) -> None:
|
|
202
219
|
"""Sets the polar angle i.e the angle between Z_AXIS and Camera through ORIGIN in radians.
|
|
203
220
|
|
|
204
221
|
Parameters
|
|
@@ -208,7 +225,7 @@ class ThreeDCamera(Camera):
|
|
|
208
225
|
"""
|
|
209
226
|
self.phi_tracker.set_value(value)
|
|
210
227
|
|
|
211
|
-
def set_theta(self, value: float):
|
|
228
|
+
def set_theta(self, value: float) -> None:
|
|
212
229
|
"""Sets the azimuthal angle i.e the angle that spins the camera around Z_AXIS in radians.
|
|
213
230
|
|
|
214
231
|
Parameters
|
|
@@ -218,7 +235,7 @@ class ThreeDCamera(Camera):
|
|
|
218
235
|
"""
|
|
219
236
|
self.theta_tracker.set_value(value)
|
|
220
237
|
|
|
221
|
-
def set_focal_distance(self, value: float):
|
|
238
|
+
def set_focal_distance(self, value: float) -> None:
|
|
222
239
|
"""Sets the focal_distance of the Camera.
|
|
223
240
|
|
|
224
241
|
Parameters
|
|
@@ -228,7 +245,7 @@ class ThreeDCamera(Camera):
|
|
|
228
245
|
"""
|
|
229
246
|
self.focal_distance_tracker.set_value(value)
|
|
230
247
|
|
|
231
|
-
def set_gamma(self, value: float):
|
|
248
|
+
def set_gamma(self, value: float) -> None:
|
|
232
249
|
"""Sets the angle of rotation of the camera about the vector from the ORIGIN to the Camera.
|
|
233
250
|
|
|
234
251
|
Parameters
|
|
@@ -238,7 +255,7 @@ class ThreeDCamera(Camera):
|
|
|
238
255
|
"""
|
|
239
256
|
self.gamma_tracker.set_value(value)
|
|
240
257
|
|
|
241
|
-
def set_zoom(self, value: float):
|
|
258
|
+
def set_zoom(self, value: float) -> None:
|
|
242
259
|
"""Sets the zoom amount of the camera.
|
|
243
260
|
|
|
244
261
|
Parameters
|
|
@@ -248,13 +265,13 @@ class ThreeDCamera(Camera):
|
|
|
248
265
|
"""
|
|
249
266
|
self.zoom_tracker.set_value(value)
|
|
250
267
|
|
|
251
|
-
def reset_rotation_matrix(self):
|
|
268
|
+
def reset_rotation_matrix(self) -> None:
|
|
252
269
|
"""Sets the value of self.rotation_matrix to
|
|
253
270
|
the matrix corresponding to the current position of the camera
|
|
254
271
|
"""
|
|
255
272
|
self.rotation_matrix = self.generate_rotation_matrix()
|
|
256
273
|
|
|
257
|
-
def get_rotation_matrix(self):
|
|
274
|
+
def get_rotation_matrix(self) -> MatrixMN:
|
|
258
275
|
"""Returns the matrix corresponding to the current position of the camera.
|
|
259
276
|
|
|
260
277
|
Returns
|
|
@@ -264,7 +281,7 @@ class ThreeDCamera(Camera):
|
|
|
264
281
|
"""
|
|
265
282
|
return self.rotation_matrix
|
|
266
283
|
|
|
267
|
-
def generate_rotation_matrix(self):
|
|
284
|
+
def generate_rotation_matrix(self) -> MatrixMN:
|
|
268
285
|
"""Generates a rotation matrix based off the current position of the camera.
|
|
269
286
|
|
|
270
287
|
Returns
|
|
@@ -285,7 +302,7 @@ class ThreeDCamera(Camera):
|
|
|
285
302
|
result = np.dot(matrix, result)
|
|
286
303
|
return result
|
|
287
304
|
|
|
288
|
-
def project_points(self, points:
|
|
305
|
+
def project_points(self, points: Point3D_Array) -> Point3D_Array:
|
|
289
306
|
"""Applies the current rotation_matrix as a projection
|
|
290
307
|
matrix to the passed array of points.
|
|
291
308
|
|
|
@@ -322,7 +339,7 @@ class ThreeDCamera(Camera):
|
|
|
322
339
|
points[:, i] *= factor * zoom
|
|
323
340
|
return points
|
|
324
341
|
|
|
325
|
-
def project_point(self, point:
|
|
342
|
+
def project_point(self, point: Point3D) -> Point3D:
|
|
326
343
|
"""Applies the current rotation_matrix as a projection
|
|
327
344
|
matrix to the passed point.
|
|
328
345
|
|
|
@@ -340,9 +357,9 @@ class ThreeDCamera(Camera):
|
|
|
340
357
|
|
|
341
358
|
def transform_points_pre_display(
|
|
342
359
|
self,
|
|
343
|
-
mobject,
|
|
344
|
-
points,
|
|
345
|
-
): # TODO: Write Docstrings for this Method.
|
|
360
|
+
mobject: Mobject,
|
|
361
|
+
points: Point3D_Array,
|
|
362
|
+
) -> Point3D_Array: # TODO: Write Docstrings for this Method.
|
|
346
363
|
points = super().transform_points_pre_display(mobject, points)
|
|
347
364
|
fixed_orientation = mobject in self.fixed_orientation_mobjects
|
|
348
365
|
fixed_in_frame = mobject in self.fixed_in_frame_mobjects
|
|
@@ -361,8 +378,8 @@ class ThreeDCamera(Camera):
|
|
|
361
378
|
self,
|
|
362
379
|
*mobjects: Mobject,
|
|
363
380
|
use_static_center_func: bool = False,
|
|
364
|
-
center_func: Callable[[],
|
|
365
|
-
):
|
|
381
|
+
center_func: Callable[[], Point3D] | None = None,
|
|
382
|
+
) -> None:
|
|
366
383
|
"""This method allows the mobject to have a fixed orientation,
|
|
367
384
|
even when the camera moves around.
|
|
368
385
|
E.G If it was passed through this method, facing the camera, it
|
|
@@ -380,9 +397,10 @@ class ThreeDCamera(Camera):
|
|
|
380
397
|
The function which returns the centerpoint
|
|
381
398
|
with respect to which the mobject will be oriented, by default None
|
|
382
399
|
"""
|
|
400
|
+
|
|
383
401
|
# This prevents the computation of mobject.get_center
|
|
384
402
|
# every single time a projection happens
|
|
385
|
-
def get_static_center_func(mobject):
|
|
403
|
+
def get_static_center_func(mobject: Mobject) -> Callable[[], Point3D]:
|
|
386
404
|
point = mobject.get_center()
|
|
387
405
|
return lambda: point
|
|
388
406
|
|
|
@@ -396,7 +414,7 @@ class ThreeDCamera(Camera):
|
|
|
396
414
|
for submob in mobject.get_family():
|
|
397
415
|
self.fixed_orientation_mobjects[submob] = func
|
|
398
416
|
|
|
399
|
-
def add_fixed_in_frame_mobjects(self, *mobjects: Mobject):
|
|
417
|
+
def add_fixed_in_frame_mobjects(self, *mobjects: Mobject) -> None:
|
|
400
418
|
"""This method allows the mobject to have a fixed position,
|
|
401
419
|
even when the camera moves around.
|
|
402
420
|
E.G If it was passed through this method, at the top of the frame, it
|
|
@@ -412,7 +430,7 @@ class ThreeDCamera(Camera):
|
|
|
412
430
|
for mobject in extract_mobject_family_members(mobjects):
|
|
413
431
|
self.fixed_in_frame_mobjects.add(mobject)
|
|
414
432
|
|
|
415
|
-
def remove_fixed_orientation_mobjects(self, *mobjects: Mobject):
|
|
433
|
+
def remove_fixed_orientation_mobjects(self, *mobjects: Mobject) -> None:
|
|
416
434
|
"""If a mobject was fixed in its orientation by passing it through
|
|
417
435
|
:meth:`.add_fixed_orientation_mobjects`, then this undoes that fixing.
|
|
418
436
|
The Mobject will no longer have a fixed orientation.
|
|
@@ -426,7 +444,7 @@ class ThreeDCamera(Camera):
|
|
|
426
444
|
if mobject in self.fixed_orientation_mobjects:
|
|
427
445
|
del self.fixed_orientation_mobjects[mobject]
|
|
428
446
|
|
|
429
|
-
def remove_fixed_in_frame_mobjects(self, *mobjects: Mobject):
|
|
447
|
+
def remove_fixed_in_frame_mobjects(self, *mobjects: Mobject) -> None:
|
|
430
448
|
"""If a mobject was fixed in frame by passing it through
|
|
431
449
|
:meth:`.add_fixed_in_frame_mobjects`, then this undoes that fixing.
|
|
432
450
|
The Mobject will no longer be fixed in frame.
|
manim/cli/__init__.py
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""The Manim CLI, and the available commands for ``manim``.
|
|
2
|
+
|
|
3
|
+
This page is a work in progress. Please run ``manim`` or ``manim --help`` in
|
|
4
|
+
your terminal to find more information on the following commands.
|
|
5
|
+
|
|
6
|
+
Available commands
|
|
7
|
+
------------------
|
|
8
|
+
|
|
9
|
+
.. autosummary::
|
|
10
|
+
:toctree: ../reference
|
|
11
|
+
|
|
12
|
+
cfg
|
|
13
|
+
checkhealth
|
|
14
|
+
init
|
|
15
|
+
plugins
|
|
16
|
+
render
|
|
17
|
+
"""
|
manim/cli/cfg/group.py
CHANGED
|
@@ -5,32 +5,45 @@ cfg``. Here you can specify options, subcommands, and subgroups for the cfg
|
|
|
5
5
|
group.
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
|
+
|
|
8
9
|
from __future__ import annotations
|
|
9
10
|
|
|
10
|
-
import
|
|
11
|
+
import contextlib
|
|
11
12
|
from ast import literal_eval
|
|
12
13
|
from pathlib import Path
|
|
14
|
+
from typing import Any, cast
|
|
13
15
|
|
|
14
|
-
import click
|
|
15
16
|
import cloup
|
|
16
17
|
from rich.errors import StyleSyntaxError
|
|
17
18
|
from rich.style import Style
|
|
18
19
|
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
20
|
+
from manim._config import cli_ctx_settings, console
|
|
21
|
+
from manim._config.utils import config_file_paths, make_config_parser
|
|
22
|
+
from manim.constants import EPILOG
|
|
23
|
+
from manim.utils.file_ops import guarantee_existence, open_file
|
|
23
24
|
|
|
24
25
|
RICH_COLOUR_INSTRUCTIONS: str = """
|
|
25
26
|
[red]The default colour is used by the input statement.
|
|
26
27
|
If left empty, the default colour will be used.[/red]
|
|
27
28
|
[magenta] For a full list of styles, visit[/magenta] [green]https://rich.readthedocs.io/en/latest/style.html[/green]
|
|
28
29
|
"""
|
|
29
|
-
RICH_NON_STYLE_ENTRIES: str = ["log.width", "log.height", "log.timestamps"]
|
|
30
|
+
RICH_NON_STYLE_ENTRIES: list[str] = ["log.width", "log.height", "log.timestamps"]
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"value_from_string",
|
|
34
|
+
"value_from_string",
|
|
35
|
+
"is_valid_style",
|
|
36
|
+
"replace_keys",
|
|
37
|
+
"cfg",
|
|
38
|
+
"write",
|
|
39
|
+
"show",
|
|
40
|
+
"export",
|
|
41
|
+
]
|
|
30
42
|
|
|
31
43
|
|
|
32
44
|
def value_from_string(value: str) -> str | int | bool:
|
|
33
|
-
"""
|
|
45
|
+
"""Extract the literal of proper datatype from a ``value`` string.
|
|
46
|
+
|
|
34
47
|
Parameters
|
|
35
48
|
----------
|
|
36
49
|
value
|
|
@@ -38,51 +51,60 @@ def value_from_string(value: str) -> str | int | bool:
|
|
|
38
51
|
|
|
39
52
|
Returns
|
|
40
53
|
-------
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
:class:`str` | :class:`int` | :class:`bool`
|
|
55
|
+
The literal of appropriate datatype.
|
|
43
56
|
"""
|
|
44
|
-
|
|
57
|
+
with contextlib.suppress(SyntaxError, ValueError):
|
|
45
58
|
value = literal_eval(value)
|
|
46
|
-
except (SyntaxError, ValueError):
|
|
47
|
-
pass
|
|
48
59
|
return value
|
|
49
60
|
|
|
50
61
|
|
|
51
|
-
def _is_expected_datatype(
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
def _is_expected_datatype(
|
|
63
|
+
value: str, expected: str, validate_style: bool = False
|
|
64
|
+
) -> bool:
|
|
65
|
+
"""Check whether the literal from ``value`` is the same datatype as the
|
|
66
|
+
literal from ``expected``. If ``validate_style`` is ``True``, also check if
|
|
67
|
+
the style given by ``value`` is valid, according to ``rich``.
|
|
54
68
|
|
|
55
69
|
Parameters
|
|
56
70
|
----------
|
|
57
71
|
value
|
|
58
|
-
The string of the value to check
|
|
72
|
+
The string of the value to check, obtained from reading the user input.
|
|
59
73
|
expected
|
|
60
|
-
The string of the literal datatype must be matched by
|
|
61
|
-
reading the cfg file.
|
|
62
|
-
|
|
63
|
-
Whether or not to confirm if
|
|
74
|
+
The string of the literal datatype which must be matched by ``value``.
|
|
75
|
+
This is obtained from reading the ``cfg`` file.
|
|
76
|
+
validate_style
|
|
77
|
+
Whether or not to confirm if ``value`` is a valid style, according to
|
|
78
|
+
``rich``. Default is ``False``.
|
|
64
79
|
|
|
65
80
|
Returns
|
|
66
81
|
-------
|
|
67
82
|
:class:`bool`
|
|
68
|
-
Whether or not
|
|
83
|
+
Whether or not the literal from ``value`` matches the datatype of the
|
|
84
|
+
literal from ``expected``.
|
|
69
85
|
"""
|
|
70
|
-
|
|
71
|
-
|
|
86
|
+
value_literal = value_from_string(value)
|
|
87
|
+
ExpectedLiteralType = type(value_from_string(expected))
|
|
72
88
|
|
|
73
|
-
return isinstance(
|
|
89
|
+
return isinstance(value_literal, ExpectedLiteralType) and (
|
|
90
|
+
(isinstance(value_literal, str) and is_valid_style(value_literal))
|
|
91
|
+
if validate_style
|
|
92
|
+
else True
|
|
93
|
+
)
|
|
74
94
|
|
|
75
95
|
|
|
76
96
|
def is_valid_style(style: str) -> bool:
|
|
77
|
-
"""Checks whether the entered color is
|
|
97
|
+
"""Checks whether the entered color style is valid, according to ``rich``.
|
|
98
|
+
|
|
78
99
|
Parameters
|
|
79
100
|
----------
|
|
80
101
|
style
|
|
81
102
|
The style to check whether it is valid.
|
|
103
|
+
|
|
82
104
|
Returns
|
|
83
105
|
-------
|
|
84
|
-
|
|
85
|
-
|
|
106
|
+
:class:`bool`
|
|
107
|
+
Whether the color style is valid or not, according to ``rich``.
|
|
86
108
|
"""
|
|
87
109
|
try:
|
|
88
110
|
Style.parse(style)
|
|
@@ -91,16 +113,20 @@ def is_valid_style(style: str) -> bool:
|
|
|
91
113
|
return False
|
|
92
114
|
|
|
93
115
|
|
|
94
|
-
def replace_keys(default: dict) -> dict:
|
|
95
|
-
"""
|
|
116
|
+
def replace_keys(default: dict[str, Any]) -> dict[str, Any]:
|
|
117
|
+
"""Replace ``_`` with ``.`` and vice versa in a dictionary's keys for
|
|
118
|
+
``rich``.
|
|
119
|
+
|
|
96
120
|
Parameters
|
|
97
121
|
----------
|
|
98
122
|
default
|
|
99
|
-
The dictionary
|
|
123
|
+
The dictionary whose keys will be checked and replaced.
|
|
124
|
+
|
|
100
125
|
Returns
|
|
101
126
|
-------
|
|
102
127
|
:class:`dict`
|
|
103
|
-
The dictionary
|
|
128
|
+
The dictionary whose keys are modified by replacing ``_`` with ``.``
|
|
129
|
+
and vice versa.
|
|
104
130
|
"""
|
|
105
131
|
for key in default:
|
|
106
132
|
if "_" in key:
|
|
@@ -123,22 +149,22 @@ def replace_keys(default: dict) -> dict:
|
|
|
123
149
|
epilog=EPILOG,
|
|
124
150
|
help="Manages Manim configuration files.",
|
|
125
151
|
)
|
|
126
|
-
@
|
|
127
|
-
def cfg(ctx):
|
|
152
|
+
@cloup.pass_context
|
|
153
|
+
def cfg(ctx: cloup.Context) -> None:
|
|
128
154
|
"""Responsible for the cfg subcommand."""
|
|
129
155
|
pass
|
|
130
156
|
|
|
131
157
|
|
|
132
158
|
@cfg.command(context_settings=cli_ctx_settings, no_args_is_help=True)
|
|
133
|
-
@
|
|
159
|
+
@cloup.option(
|
|
134
160
|
"-l",
|
|
135
161
|
"--level",
|
|
136
|
-
type=
|
|
162
|
+
type=cloup.Choice(["user", "cwd"], case_sensitive=False),
|
|
137
163
|
default="cwd",
|
|
138
164
|
help="Specify if this config is for user or the working directory.",
|
|
139
165
|
)
|
|
140
|
-
@
|
|
141
|
-
def write(level: str = None, openfile: bool = False) -> None:
|
|
166
|
+
@cloup.option("-o", "--open", "openfile", is_flag=True)
|
|
167
|
+
def write(level: str | None = None, openfile: bool = False) -> None:
|
|
142
168
|
config_paths = config_file_paths()
|
|
143
169
|
console.print(
|
|
144
170
|
"[yellow bold]Manim Configuration File Writer[/yellow bold]",
|
|
@@ -157,7 +183,7 @@ To save your config please save that file and place it in your current working d
|
|
|
157
183
|
action = "save this as"
|
|
158
184
|
for category in parser:
|
|
159
185
|
console.print(f"{category}", style="bold green underline")
|
|
160
|
-
default = parser[category]
|
|
186
|
+
default = cast(dict[str, Any], parser[category])
|
|
161
187
|
if category == "logger":
|
|
162
188
|
console.print(RICH_COLOUR_INSTRUCTIONS)
|
|
163
189
|
default = replace_keys(default)
|
|
@@ -187,7 +213,7 @@ To save your config please save that file and place it in your current working d
|
|
|
187
213
|
"""Not enough values in input.
|
|
188
214
|
You may have added a new entry to default.cfg, in which case you will have to
|
|
189
215
|
modify write_cfg_subcmd_input to account for it.""",
|
|
190
|
-
)
|
|
216
|
+
) from None
|
|
191
217
|
if temp:
|
|
192
218
|
while temp and not _is_expected_datatype(
|
|
193
219
|
temp,
|
|
@@ -240,7 +266,13 @@ modify write_cfg_subcmd_input to account for it.""",
|
|
|
240
266
|
|
|
241
267
|
|
|
242
268
|
@cfg.command(context_settings=cli_ctx_settings)
|
|
243
|
-
def show():
|
|
269
|
+
def show() -> None:
|
|
270
|
+
console.print("CONFIG FILES READ", style="bold green underline")
|
|
271
|
+
for path in config_file_paths():
|
|
272
|
+
if path.exists():
|
|
273
|
+
console.print(f"{path}")
|
|
274
|
+
console.print()
|
|
275
|
+
|
|
244
276
|
parser = make_config_parser()
|
|
245
277
|
rich_non_style_entries = [a.replace(".", "_") for a in RICH_NON_STYLE_ENTRIES]
|
|
246
278
|
for category in parser:
|
|
@@ -258,9 +290,9 @@ def show():
|
|
|
258
290
|
|
|
259
291
|
|
|
260
292
|
@cfg.command(context_settings=cli_ctx_settings)
|
|
261
|
-
@
|
|
262
|
-
@
|
|
263
|
-
def export(ctx, directory):
|
|
293
|
+
@cloup.option("-d", "--directory", default=Path.cwd())
|
|
294
|
+
@cloup.pass_context
|
|
295
|
+
def export(ctx: cloup.Context, directory: str) -> None:
|
|
264
296
|
directory_path = Path(directory)
|
|
265
297
|
if directory_path.absolute == Path.cwd().absolute:
|
|
266
298
|
console.print(
|