manim 0.18.0.post0__py3-none-any.whl → 0.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of manim might be problematic. Click here for more details.
- manim/__init__.py +3 -6
- manim/__main__.py +61 -20
- manim/_config/__init__.py +6 -3
- manim/_config/cli_colors.py +16 -8
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +14 -8
- manim/_config/utils.py +651 -472
- manim/animation/animation.py +152 -5
- manim/animation/composition.py +80 -39
- manim/animation/creation.py +196 -14
- manim/animation/fading.py +5 -9
- manim/animation/indication.py +103 -47
- manim/animation/movement.py +22 -5
- manim/animation/rotation.py +3 -2
- manim/animation/specialized.py +4 -6
- manim/animation/speedmodifier.py +10 -5
- manim/animation/transform.py +4 -5
- manim/animation/transform_matching_parts.py +1 -1
- manim/animation/updaters/mobject_update_utils.py +17 -14
- manim/camera/camera.py +15 -6
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +70 -44
- manim/cli/checkhealth/checks.py +93 -75
- manim/cli/checkhealth/commands.py +14 -5
- manim/cli/default_group.py +157 -25
- manim/cli/init/commands.py +32 -24
- 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 +51 -15
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +97 -32
- manim/constants.py +65 -19
- manim/gui/gui.py +2 -0
- manim/mobject/frame.py +0 -1
- manim/mobject/geometry/arc.py +112 -78
- manim/mobject/geometry/boolean_ops.py +32 -25
- manim/mobject/geometry/labeled.py +300 -77
- manim/mobject/geometry/line.py +132 -64
- manim/mobject/geometry/polygram.py +126 -30
- manim/mobject/geometry/shape_matchers.py +35 -15
- manim/mobject/geometry/tips.py +38 -29
- manim/mobject/graph.py +414 -133
- manim/mobject/graphing/coordinate_systems.py +126 -64
- manim/mobject/graphing/functions.py +25 -15
- manim/mobject/graphing/number_line.py +24 -10
- manim/mobject/graphing/probability.py +2 -10
- manim/mobject/graphing/scale.py +6 -5
- manim/mobject/matrix.py +17 -19
- manim/mobject/mobject.py +314 -165
- manim/mobject/opengl/opengl_compatibility.py +2 -0
- manim/mobject/opengl/opengl_geometry.py +30 -9
- manim/mobject/opengl/opengl_image_mobject.py +2 -0
- manim/mobject/opengl/opengl_mobject.py +509 -343
- manim/mobject/opengl/opengl_point_cloud_mobject.py +5 -7
- manim/mobject/opengl/opengl_surface.py +3 -2
- manim/mobject/opengl/opengl_three_dimensions.py +2 -0
- manim/mobject/opengl/opengl_vectorized_mobject.py +46 -79
- manim/mobject/svg/brace.py +63 -13
- manim/mobject/svg/svg_mobject.py +4 -3
- manim/mobject/table.py +11 -13
- manim/mobject/text/code_mobject.py +186 -548
- manim/mobject/text/numbers.py +9 -7
- manim/mobject/text/tex_mobject.py +23 -14
- manim/mobject/text/text_mobject.py +70 -24
- manim/mobject/three_d/polyhedra.py +98 -1
- manim/mobject/three_d/three_d_utils.py +4 -4
- manim/mobject/three_d/three_dimensions.py +62 -34
- manim/mobject/types/image_mobject.py +42 -24
- manim/mobject/types/point_cloud_mobject.py +105 -67
- manim/mobject/types/vectorized_mobject.py +496 -228
- manim/mobject/value_tracker.py +5 -4
- manim/mobject/vector_field.py +5 -5
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +14 -8
- manim/renderer/cairo_renderer.py +20 -10
- manim/renderer/opengl_renderer.py +21 -23
- manim/renderer/opengl_renderer_window.py +2 -0
- manim/renderer/shader.py +2 -3
- manim/renderer/shader_wrapper.py +5 -2
- manim/renderer/vectorized_mobject_rendering.py +5 -0
- manim/scene/moving_camera_scene.py +23 -0
- manim/scene/scene.py +90 -43
- manim/scene/scene_file_writer.py +316 -165
- manim/scene/section.py +17 -15
- manim/scene/three_d_scene.py +13 -21
- manim/scene/vector_space_scene.py +22 -9
- manim/typing.py +830 -70
- manim/utils/bezier.py +1667 -399
- manim/utils/caching.py +13 -5
- manim/utils/color/AS2700.py +2 -0
- manim/utils/color/BS381.py +3 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +3 -0
- manim/utils/color/XKCD.py +3 -0
- manim/utils/color/__init__.py +8 -5
- manim/utils/color/core.py +844 -309
- manim/utils/color/manim_colors.py +7 -9
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +18 -13
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +90 -40
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +234 -0
- manim/utils/docbuild/autocolor_directive.py +21 -17
- manim/utils/docbuild/manim_directive.py +50 -35
- 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 +26 -16
- manim/utils/hashing.py +9 -7
- manim/utils/images.py +10 -4
- manim/utils/ipython_magic.py +14 -8
- manim/utils/iterables.py +161 -119
- manim/utils/module_ops.py +57 -19
- manim/utils/opengl.py +83 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +21 -23
- manim/utils/polylabel.py +168 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +74 -39
- manim/utils/simple_functions.py +24 -15
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +125 -69
- 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 +33 -18
- manim/utils/testing/frames_comparison.py +27 -19
- manim/utils/tex.py +127 -197
- manim/utils/tex_file_writing.py +47 -45
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE.community +1 -1
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/METADATA +40 -39
- manim-0.19.0.dist-info/RECORD +221 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
- manim/cli/new/__init__.py +0 -0
- manim/cli/new/group.py +0 -189
- manim/plugins/import_plugins.py +0 -43
- manim-0.18.0.post0.dist-info/RECORD +0 -217
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
manim/animation/fading.py
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
from __future__ import annotations
|
|
17
16
|
|
|
18
17
|
__all__ = [
|
|
@@ -58,10 +57,7 @@ class _Fade(Transform):
|
|
|
58
57
|
) -> None:
|
|
59
58
|
if not mobjects:
|
|
60
59
|
raise ValueError("At least one mobject must be passed.")
|
|
61
|
-
if len(mobjects) == 1
|
|
62
|
-
mobject = mobjects[0]
|
|
63
|
-
else:
|
|
64
|
-
mobject = Group(*mobjects)
|
|
60
|
+
mobject = mobjects[0] if len(mobjects) == 1 else Group(*mobjects)
|
|
65
61
|
|
|
66
62
|
self.point_target = False
|
|
67
63
|
if shift is None:
|
|
@@ -98,7 +94,7 @@ class _Fade(Transform):
|
|
|
98
94
|
|
|
99
95
|
|
|
100
96
|
class FadeIn(_Fade):
|
|
101
|
-
"""Fade in :class:`~.Mobject` s.
|
|
97
|
+
r"""Fade in :class:`~.Mobject` s.
|
|
102
98
|
|
|
103
99
|
Parameters
|
|
104
100
|
----------
|
|
@@ -123,7 +119,7 @@ class FadeIn(_Fade):
|
|
|
123
119
|
dot = Dot(UP * 2 + LEFT)
|
|
124
120
|
self.add(dot)
|
|
125
121
|
tex = Tex(
|
|
126
|
-
"FadeIn with ", "shift ", " or target
|
|
122
|
+
"FadeIn with ", "shift ", r" or target\_position", " and scale"
|
|
127
123
|
).scale(1)
|
|
128
124
|
animations = [
|
|
129
125
|
FadeIn(tex[0]),
|
|
@@ -146,7 +142,7 @@ class FadeIn(_Fade):
|
|
|
146
142
|
|
|
147
143
|
|
|
148
144
|
class FadeOut(_Fade):
|
|
149
|
-
"""Fade out :class:`~.Mobject` s.
|
|
145
|
+
r"""Fade out :class:`~.Mobject` s.
|
|
150
146
|
|
|
151
147
|
Parameters
|
|
152
148
|
----------
|
|
@@ -170,7 +166,7 @@ class FadeOut(_Fade):
|
|
|
170
166
|
dot = Dot(UP * 2 + LEFT)
|
|
171
167
|
self.add(dot)
|
|
172
168
|
tex = Tex(
|
|
173
|
-
"FadeOut with ", "shift ", " or target
|
|
169
|
+
"FadeOut with ", "shift ", r" or target\_position", " and scale"
|
|
174
170
|
).scale(1)
|
|
175
171
|
animations = [
|
|
176
172
|
FadeOut(tex[0]),
|
manim/animation/indication.py
CHANGED
|
@@ -25,19 +25,22 @@ Examples
|
|
|
25
25
|
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
28
30
|
__all__ = [
|
|
29
31
|
"FocusOn",
|
|
30
32
|
"Indicate",
|
|
31
33
|
"Flash",
|
|
32
34
|
"ShowPassingFlash",
|
|
33
35
|
"ShowPassingFlashWithThinningStrokeWidth",
|
|
34
|
-
"ShowCreationThenFadeOut",
|
|
35
36
|
"ApplyWave",
|
|
36
37
|
"Circumscribe",
|
|
37
38
|
"Wiggle",
|
|
39
|
+
"Blink",
|
|
38
40
|
]
|
|
39
41
|
|
|
40
|
-
from
|
|
42
|
+
from collections.abc import Iterable
|
|
43
|
+
from typing import Callable
|
|
41
44
|
|
|
42
45
|
import numpy as np
|
|
43
46
|
|
|
@@ -54,12 +57,12 @@ from ..animation.creation import Create, ShowPartial, Uncreate
|
|
|
54
57
|
from ..animation.fading import FadeIn, FadeOut
|
|
55
58
|
from ..animation.movement import Homotopy
|
|
56
59
|
from ..animation.transform import Transform
|
|
60
|
+
from ..animation.updaters.update import UpdateFromFunc
|
|
57
61
|
from ..constants import *
|
|
58
62
|
from ..mobject.mobject import Mobject
|
|
59
63
|
from ..mobject.types.vectorized_mobject import VGroup, VMobject
|
|
60
64
|
from ..utils.bezier import interpolate, inverse_interpolate
|
|
61
65
|
from ..utils.color import GREY, YELLOW, ParsableManimColor
|
|
62
|
-
from ..utils.deprecation import deprecated
|
|
63
66
|
from ..utils.rate_functions import smooth, there_and_back, wiggle
|
|
64
67
|
from ..utils.space_ops import normalize
|
|
65
68
|
|
|
@@ -77,8 +80,6 @@ class FocusOn(Transform):
|
|
|
77
80
|
The color of the spotlight.
|
|
78
81
|
run_time
|
|
79
82
|
The duration of the animation.
|
|
80
|
-
kwargs
|
|
81
|
-
Additional arguments to be passed to the :class:`~.Succession` constructor
|
|
82
83
|
|
|
83
84
|
Examples
|
|
84
85
|
--------
|
|
@@ -94,11 +95,11 @@ class FocusOn(Transform):
|
|
|
94
95
|
|
|
95
96
|
def __init__(
|
|
96
97
|
self,
|
|
97
|
-
focus_point:
|
|
98
|
+
focus_point: np.ndarray | Mobject,
|
|
98
99
|
opacity: float = 0.2,
|
|
99
100
|
color: str = GREY,
|
|
100
101
|
run_time: float = 2,
|
|
101
|
-
**kwargs
|
|
102
|
+
**kwargs,
|
|
102
103
|
) -> None:
|
|
103
104
|
self.focus_point = focus_point
|
|
104
105
|
self.color = color
|
|
@@ -131,7 +132,7 @@ class Indicate(Transform):
|
|
|
131
132
|
color
|
|
132
133
|
The color the mobject temporally takes.
|
|
133
134
|
rate_func
|
|
134
|
-
The function
|
|
135
|
+
The function defining the animation progress at every point in time.
|
|
135
136
|
kwargs
|
|
136
137
|
Additional arguments to be passed to the :class:`~.Succession` constructor
|
|
137
138
|
|
|
@@ -148,17 +149,17 @@ class Indicate(Transform):
|
|
|
148
149
|
|
|
149
150
|
def __init__(
|
|
150
151
|
self,
|
|
151
|
-
mobject:
|
|
152
|
+
mobject: Mobject,
|
|
152
153
|
scale_factor: float = 1.2,
|
|
153
154
|
color: str = YELLOW,
|
|
154
|
-
rate_func: Callable[[float,
|
|
155
|
-
**kwargs
|
|
155
|
+
rate_func: Callable[[float, float | None], np.ndarray] = there_and_back,
|
|
156
|
+
**kwargs,
|
|
156
157
|
) -> None:
|
|
157
158
|
self.color = color
|
|
158
159
|
self.scale_factor = scale_factor
|
|
159
160
|
super().__init__(mobject, rate_func=rate_func, **kwargs)
|
|
160
161
|
|
|
161
|
-
def create_target(self) ->
|
|
162
|
+
def create_target(self) -> Mobject:
|
|
162
163
|
target = self.mobject.copy()
|
|
163
164
|
target.scale(self.scale_factor)
|
|
164
165
|
target.set_color(self.color)
|
|
@@ -218,7 +219,7 @@ class Flash(AnimationGroup):
|
|
|
218
219
|
|
|
219
220
|
def __init__(
|
|
220
221
|
self,
|
|
221
|
-
point:
|
|
222
|
+
point: np.ndarray | Mobject,
|
|
222
223
|
line_length: float = 0.2,
|
|
223
224
|
num_lines: int = 12,
|
|
224
225
|
flash_radius: float = 0.1,
|
|
@@ -226,7 +227,7 @@ class Flash(AnimationGroup):
|
|
|
226
227
|
color: str = YELLOW,
|
|
227
228
|
time_width: float = 1,
|
|
228
229
|
run_time: float = 1.0,
|
|
229
|
-
**kwargs
|
|
230
|
+
**kwargs,
|
|
230
231
|
) -> None:
|
|
231
232
|
if isinstance(point, Mobject):
|
|
232
233
|
self.point = point.get_center()
|
|
@@ -256,7 +257,7 @@ class Flash(AnimationGroup):
|
|
|
256
257
|
lines.set_stroke(width=self.line_stroke_width)
|
|
257
258
|
return lines
|
|
258
259
|
|
|
259
|
-
def create_line_anims(self) -> Iterable[
|
|
260
|
+
def create_line_anims(self) -> Iterable[ShowPassingFlash]:
|
|
260
261
|
return [
|
|
261
262
|
ShowPassingFlash(
|
|
262
263
|
line,
|
|
@@ -269,7 +270,7 @@ class Flash(AnimationGroup):
|
|
|
269
270
|
|
|
270
271
|
|
|
271
272
|
class ShowPassingFlash(ShowPartial):
|
|
272
|
-
"""Show only a sliver of the VMobject each frame.
|
|
273
|
+
r"""Show only a sliver of the VMobject each frame.
|
|
273
274
|
|
|
274
275
|
Parameters
|
|
275
276
|
----------
|
|
@@ -289,7 +290,7 @@ class ShowPassingFlash(ShowPartial):
|
|
|
289
290
|
self.add(p, lbl)
|
|
290
291
|
p = p.copy().set_color(BLUE)
|
|
291
292
|
for time_width in [0.2, 0.5, 1, 2]:
|
|
292
|
-
lbl.become(Tex(r"
|
|
293
|
+
lbl.become(Tex(r"\texttt{time\_width={{%.1f}}}"%time_width))
|
|
293
294
|
self.play(ShowPassingFlash(
|
|
294
295
|
p.copy().set_color(BLUE),
|
|
295
296
|
run_time=2,
|
|
@@ -302,11 +303,11 @@ class ShowPassingFlash(ShowPartial):
|
|
|
302
303
|
|
|
303
304
|
"""
|
|
304
305
|
|
|
305
|
-
def __init__(self, mobject:
|
|
306
|
+
def __init__(self, mobject: VMobject, time_width: float = 0.1, **kwargs) -> None:
|
|
306
307
|
self.time_width = time_width
|
|
307
308
|
super().__init__(mobject, remover=True, introducer=True, **kwargs)
|
|
308
309
|
|
|
309
|
-
def _get_bounds(self, alpha: float) ->
|
|
310
|
+
def _get_bounds(self, alpha: float) -> tuple[float]:
|
|
310
311
|
tw = self.time_width
|
|
311
312
|
upper = interpolate(0, 1 + tw, alpha)
|
|
312
313
|
lower = upper - tw
|
|
@@ -342,16 +343,6 @@ class ShowPassingFlashWithThinningStrokeWidth(AnimationGroup):
|
|
|
342
343
|
)
|
|
343
344
|
|
|
344
345
|
|
|
345
|
-
@deprecated(
|
|
346
|
-
since="v0.15.0",
|
|
347
|
-
until="v0.16.0",
|
|
348
|
-
message="Use Create then FadeOut to achieve this effect.",
|
|
349
|
-
)
|
|
350
|
-
class ShowCreationThenFadeOut(Succession):
|
|
351
|
-
def __init__(self, mobject: "Mobject", remover: bool = True, **kwargs) -> None:
|
|
352
|
-
super().__init__(Create(mobject), FadeOut(mobject), remover=remover, **kwargs)
|
|
353
|
-
|
|
354
|
-
|
|
355
346
|
class ApplyWave(Homotopy):
|
|
356
347
|
"""Send a wave through the Mobject distorting it temporarily.
|
|
357
348
|
|
|
@@ -397,14 +388,14 @@ class ApplyWave(Homotopy):
|
|
|
397
388
|
|
|
398
389
|
def __init__(
|
|
399
390
|
self,
|
|
400
|
-
mobject:
|
|
391
|
+
mobject: Mobject,
|
|
401
392
|
direction: np.ndarray = UP,
|
|
402
393
|
amplitude: float = 0.2,
|
|
403
394
|
wave_func: Callable[[float], float] = smooth,
|
|
404
395
|
time_width: float = 1,
|
|
405
396
|
ripples: int = 1,
|
|
406
397
|
run_time: float = 2,
|
|
407
|
-
**kwargs
|
|
398
|
+
**kwargs,
|
|
408
399
|
) -> None:
|
|
409
400
|
x_min = mobject.get_left()[0]
|
|
410
401
|
x_max = mobject.get_right()[0]
|
|
@@ -415,7 +406,7 @@ class ApplyWave(Homotopy):
|
|
|
415
406
|
# This wave is build up as follows:
|
|
416
407
|
# The time is split into 2*ripples phases. In every phase the amplitude
|
|
417
408
|
# either rises to one or goes down to zero. Consecutive ripples will have
|
|
418
|
-
# their amplitudes in
|
|
409
|
+
# their amplitudes in opposing directions (first ripple from 0 to 1 to 0,
|
|
419
410
|
# second from 0 to -1 to 0 and so on). This is how two ripples would be
|
|
420
411
|
# divided into phases:
|
|
421
412
|
|
|
@@ -454,7 +445,7 @@ class ApplyWave(Homotopy):
|
|
|
454
445
|
return wave_func(t * phases)
|
|
455
446
|
elif phase == phases - 1:
|
|
456
447
|
# last ripple. Rising or falling depending on the number of ripples
|
|
457
|
-
# The (ripples % 2)-term is used to make this
|
|
448
|
+
# The (ripples % 2)-term is used to make this distinction.
|
|
458
449
|
t -= phase / phases # Time relative to the phase
|
|
459
450
|
return (1 - wave_func(t * phases)) * (2 * (ripples % 2) - 1)
|
|
460
451
|
else:
|
|
@@ -470,7 +461,7 @@ class ApplyWave(Homotopy):
|
|
|
470
461
|
y: float,
|
|
471
462
|
z: float,
|
|
472
463
|
t: float,
|
|
473
|
-
) ->
|
|
464
|
+
) -> tuple[float, float, float]:
|
|
474
465
|
upper = interpolate(0, 1 + time_width, t)
|
|
475
466
|
lower = upper - time_width
|
|
476
467
|
relative_x = inverse_interpolate(x_min, x_max, x)
|
|
@@ -516,14 +507,14 @@ class Wiggle(Animation):
|
|
|
516
507
|
|
|
517
508
|
def __init__(
|
|
518
509
|
self,
|
|
519
|
-
mobject:
|
|
510
|
+
mobject: Mobject,
|
|
520
511
|
scale_value: float = 1.1,
|
|
521
512
|
rotation_angle: float = 0.01 * TAU,
|
|
522
513
|
n_wiggles: int = 6,
|
|
523
|
-
scale_about_point:
|
|
524
|
-
rotate_about_point:
|
|
514
|
+
scale_about_point: np.ndarray | None = None,
|
|
515
|
+
rotate_about_point: np.ndarray | None = None,
|
|
525
516
|
run_time: float = 2,
|
|
526
|
-
**kwargs
|
|
517
|
+
**kwargs,
|
|
527
518
|
) -> None:
|
|
528
519
|
self.scale_value = scale_value
|
|
529
520
|
self.rotation_angle = rotation_angle
|
|
@@ -544,8 +535,8 @@ class Wiggle(Animation):
|
|
|
544
535
|
|
|
545
536
|
def interpolate_submobject(
|
|
546
537
|
self,
|
|
547
|
-
submobject:
|
|
548
|
-
starting_submobject:
|
|
538
|
+
submobject: Mobject,
|
|
539
|
+
starting_submobject: Mobject,
|
|
549
540
|
alpha: float,
|
|
550
541
|
) -> None:
|
|
551
542
|
submobject.points[:, :] = starting_submobject.points
|
|
@@ -560,14 +551,14 @@ class Wiggle(Animation):
|
|
|
560
551
|
|
|
561
552
|
|
|
562
553
|
class Circumscribe(Succession):
|
|
563
|
-
"""Draw a temporary line surrounding the mobject.
|
|
554
|
+
r"""Draw a temporary line surrounding the mobject.
|
|
564
555
|
|
|
565
556
|
Parameters
|
|
566
557
|
----------
|
|
567
558
|
mobject
|
|
568
559
|
The mobject to be circumscribed.
|
|
569
560
|
shape
|
|
570
|
-
The shape with which to
|
|
561
|
+
The shape with which to surround the given mobject. Should be either
|
|
571
562
|
:class:`~.Rectangle` or :class:`~.Circle`
|
|
572
563
|
fade_in
|
|
573
564
|
Whether to make the surrounding shape to fade in. It will be drawn otherwise.
|
|
@@ -591,7 +582,7 @@ class Circumscribe(Succession):
|
|
|
591
582
|
|
|
592
583
|
class UsingCircumscribe(Scene):
|
|
593
584
|
def construct(self):
|
|
594
|
-
lbl = Tex(r"Circum
|
|
585
|
+
lbl = Tex(r"Circum-\\scribe").scale(2)
|
|
595
586
|
self.add(lbl)
|
|
596
587
|
self.play(Circumscribe(lbl))
|
|
597
588
|
self.play(Circumscribe(lbl, Circle))
|
|
@@ -604,7 +595,7 @@ class Circumscribe(Succession):
|
|
|
604
595
|
def __init__(
|
|
605
596
|
self,
|
|
606
597
|
mobject: Mobject,
|
|
607
|
-
shape:
|
|
598
|
+
shape: type = Rectangle,
|
|
608
599
|
fade_in=False,
|
|
609
600
|
fade_out=False,
|
|
610
601
|
time_width=0.3,
|
|
@@ -612,13 +603,13 @@ class Circumscribe(Succession):
|
|
|
612
603
|
color: ParsableManimColor = YELLOW,
|
|
613
604
|
run_time=1,
|
|
614
605
|
stroke_width=DEFAULT_STROKE_WIDTH,
|
|
615
|
-
**kwargs
|
|
606
|
+
**kwargs,
|
|
616
607
|
):
|
|
617
608
|
if shape is Rectangle:
|
|
618
609
|
frame = SurroundingRectangle(
|
|
619
610
|
mobject,
|
|
620
|
-
color,
|
|
621
|
-
buff,
|
|
611
|
+
color=color,
|
|
612
|
+
buff=buff,
|
|
622
613
|
stroke_width=stroke_width,
|
|
623
614
|
)
|
|
624
615
|
elif shape is Circle:
|
|
@@ -654,3 +645,68 @@ class Circumscribe(Succession):
|
|
|
654
645
|
super().__init__(
|
|
655
646
|
ShowPassingFlash(frame, time_width, run_time=run_time), **kwargs
|
|
656
647
|
)
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
class Blink(Succession):
|
|
651
|
+
"""Blink the mobject.
|
|
652
|
+
|
|
653
|
+
Parameters
|
|
654
|
+
----------
|
|
655
|
+
mobject
|
|
656
|
+
The mobject to be blinked.
|
|
657
|
+
time_on
|
|
658
|
+
The duration that the mobject is shown for one blink.
|
|
659
|
+
time_off
|
|
660
|
+
The duration that the mobject is hidden for one blink.
|
|
661
|
+
blinks
|
|
662
|
+
The number of blinks
|
|
663
|
+
hide_at_end
|
|
664
|
+
Whether to hide the mobject at the end of the animation.
|
|
665
|
+
kwargs
|
|
666
|
+
Additional arguments to be passed to the :class:`~.Succession` constructor.
|
|
667
|
+
|
|
668
|
+
Examples
|
|
669
|
+
--------
|
|
670
|
+
|
|
671
|
+
.. manim:: BlinkingExample
|
|
672
|
+
|
|
673
|
+
class BlinkingExample(Scene):
|
|
674
|
+
def construct(self):
|
|
675
|
+
text = Text("Blinking").scale(1.5)
|
|
676
|
+
self.add(text)
|
|
677
|
+
self.play(Blink(text, blinks=3))
|
|
678
|
+
|
|
679
|
+
"""
|
|
680
|
+
|
|
681
|
+
def __init__(
|
|
682
|
+
self,
|
|
683
|
+
mobject: Mobject,
|
|
684
|
+
time_on: float = 0.5,
|
|
685
|
+
time_off: float = 0.5,
|
|
686
|
+
blinks: int = 1,
|
|
687
|
+
hide_at_end: bool = False,
|
|
688
|
+
**kwargs,
|
|
689
|
+
):
|
|
690
|
+
animations = [
|
|
691
|
+
UpdateFromFunc(
|
|
692
|
+
mobject,
|
|
693
|
+
update_function=lambda mob: mob.set_opacity(1.0),
|
|
694
|
+
run_time=time_on,
|
|
695
|
+
),
|
|
696
|
+
UpdateFromFunc(
|
|
697
|
+
mobject,
|
|
698
|
+
update_function=lambda mob: mob.set_opacity(0.0),
|
|
699
|
+
run_time=time_off,
|
|
700
|
+
),
|
|
701
|
+
] * blinks
|
|
702
|
+
|
|
703
|
+
if not hide_at_end:
|
|
704
|
+
animations.append(
|
|
705
|
+
UpdateFromFunc(
|
|
706
|
+
mobject,
|
|
707
|
+
update_function=lambda mob: mob.set_opacity(1.0),
|
|
708
|
+
run_time=time_on,
|
|
709
|
+
),
|
|
710
|
+
)
|
|
711
|
+
|
|
712
|
+
super().__init__(*animations, **kwargs)
|
manim/animation/movement.py
CHANGED
|
@@ -44,6 +44,26 @@ class Homotopy(Animation):
|
|
|
44
44
|
Keyword arguments propagated to :meth:`.Mobject.apply_function`.
|
|
45
45
|
kwargs
|
|
46
46
|
Further keyword arguments passed to the parent class.
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
|
|
51
|
+
.. manim:: HomotopyExample
|
|
52
|
+
|
|
53
|
+
class HomotopyExample(Scene):
|
|
54
|
+
def construct(self):
|
|
55
|
+
square = Square()
|
|
56
|
+
|
|
57
|
+
def homotopy(x, y, z, t):
|
|
58
|
+
if t <= 0.25:
|
|
59
|
+
progress = t / 0.25
|
|
60
|
+
return (x, y + progress * 0.2 * np.sin(x), z)
|
|
61
|
+
else:
|
|
62
|
+
wave_progress = (t - 0.25) / 0.75
|
|
63
|
+
return (x, y + 0.2 * np.sin(x + 10 * wave_progress), z)
|
|
64
|
+
|
|
65
|
+
self.play(Homotopy(homotopy, square, rate_func= linear, run_time=2))
|
|
66
|
+
|
|
47
67
|
"""
|
|
48
68
|
|
|
49
69
|
def __init__(
|
|
@@ -90,9 +110,7 @@ class ComplexHomotopy(Homotopy):
|
|
|
90
110
|
def __init__(
|
|
91
111
|
self, complex_homotopy: Callable[[complex], float], mobject: Mobject, **kwargs
|
|
92
112
|
) -> None:
|
|
93
|
-
"""
|
|
94
|
-
Complex Homotopy a function Cx[0, 1] to C
|
|
95
|
-
"""
|
|
113
|
+
"""Complex Homotopy a function Cx[0, 1] to C"""
|
|
96
114
|
|
|
97
115
|
def homotopy(
|
|
98
116
|
x: float,
|
|
@@ -136,8 +154,7 @@ class PhaseFlow(Animation):
|
|
|
136
154
|
|
|
137
155
|
class MoveAlongPath(Animation):
|
|
138
156
|
"""Make one mobject move along the path of another mobject.
|
|
139
|
-
|
|
140
|
-
--------
|
|
157
|
+
|
|
141
158
|
.. manim:: MoveAlongPathExample
|
|
142
159
|
|
|
143
160
|
class MoveAlongPathExample(Scene):
|
manim/animation/rotation.py
CHANGED
|
@@ -4,7 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
__all__ = ["Rotating", "Rotate"]
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
from typing import TYPE_CHECKING, Callable
|
|
8
9
|
|
|
9
10
|
import numpy as np
|
|
10
11
|
|
|
@@ -59,7 +60,7 @@ class Rotate(Transform):
|
|
|
59
60
|
about_point
|
|
60
61
|
The rotation center.
|
|
61
62
|
about_edge
|
|
62
|
-
If ``about_point``is ``None``, this argument specifies
|
|
63
|
+
If ``about_point`` is ``None``, this argument specifies
|
|
63
64
|
the direction of the bounding box point to be taken as
|
|
64
65
|
the rotation center.
|
|
65
66
|
|
manim/animation/specialized.py
CHANGED
|
@@ -2,7 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
__all__ = ["Broadcast"]
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from typing import Any
|
|
6
7
|
|
|
7
8
|
from manim.animation.transform import Restore
|
|
8
9
|
|
|
@@ -69,10 +70,7 @@ class Broadcast(LaggedStart):
|
|
|
69
70
|
anims = []
|
|
70
71
|
|
|
71
72
|
# Works by saving the mob that is passed into the animation, scaling it to 0 (or the initial_width) and then restoring the original mob.
|
|
72
|
-
|
|
73
|
-
fill_o = True
|
|
74
|
-
else:
|
|
75
|
-
fill_o = False
|
|
73
|
+
fill_o = bool(mobject.fill_opacity)
|
|
76
74
|
|
|
77
75
|
for _ in range(self.n_mobs):
|
|
78
76
|
mob = mobject.copy()
|
|
@@ -84,7 +82,7 @@ class Broadcast(LaggedStart):
|
|
|
84
82
|
|
|
85
83
|
mob.move_to(self.focal_point)
|
|
86
84
|
mob.save_state()
|
|
87
|
-
mob.
|
|
85
|
+
mob.set(width=self.initial_width)
|
|
88
86
|
|
|
89
87
|
if fill_o:
|
|
90
88
|
mob.set_opacity(self.initial_opacity)
|
manim/animation/speedmodifier.py
CHANGED
|
@@ -4,15 +4,20 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import inspect
|
|
6
6
|
import types
|
|
7
|
-
from typing import Callable
|
|
7
|
+
from typing import TYPE_CHECKING, Callable
|
|
8
8
|
|
|
9
9
|
from numpy import piecewise
|
|
10
10
|
|
|
11
11
|
from ..animation.animation import Animation, Wait, prepare_animation
|
|
12
12
|
from ..animation.composition import AnimationGroup
|
|
13
|
-
from ..mobject.mobject import Mobject,
|
|
13
|
+
from ..mobject.mobject import Mobject, _AnimationBuilder
|
|
14
14
|
from ..scene.scene import Scene
|
|
15
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from ..mobject.mobject import Updater
|
|
18
|
+
|
|
19
|
+
__all__ = ["ChangeSpeed"]
|
|
20
|
+
|
|
16
21
|
|
|
17
22
|
class ChangeSpeed(Animation):
|
|
18
23
|
"""Modifies the speed of passed animation.
|
|
@@ -108,9 +113,9 @@ class ChangeSpeed(Animation):
|
|
|
108
113
|
self.anim = self.setup(anim)
|
|
109
114
|
|
|
110
115
|
if affects_speed_updaters:
|
|
111
|
-
assert (
|
|
112
|
-
ChangeSpeed
|
|
113
|
-
)
|
|
116
|
+
assert ChangeSpeed.is_changing_dt is False, (
|
|
117
|
+
"Only one animation at a time can play that changes speed (dt) for ChangeSpeed updaters"
|
|
118
|
+
)
|
|
114
119
|
ChangeSpeed.is_changing_dt = True
|
|
115
120
|
self.t = 0
|
|
116
121
|
self.affects_speed_updaters = affects_speed_updaters
|
manim/animation/transform.py
CHANGED
|
@@ -28,7 +28,8 @@ __all__ = [
|
|
|
28
28
|
|
|
29
29
|
import inspect
|
|
30
30
|
import types
|
|
31
|
-
from
|
|
31
|
+
from collections.abc import Iterable, Sequence
|
|
32
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
32
33
|
|
|
33
34
|
import numpy as np
|
|
34
35
|
|
|
@@ -297,9 +298,7 @@ class ReplacementTransform(Transform):
|
|
|
297
298
|
|
|
298
299
|
|
|
299
300
|
class TransformFromCopy(Transform):
|
|
300
|
-
"""
|
|
301
|
-
Performs a reversed Transform
|
|
302
|
-
"""
|
|
301
|
+
"""Performs a reversed Transform"""
|
|
303
302
|
|
|
304
303
|
def __init__(self, mobject: Mobject, target_mobject: Mobject, **kwargs) -> None:
|
|
305
304
|
super().__init__(target_mobject, mobject, **kwargs)
|
|
@@ -430,7 +429,7 @@ class MoveToTarget(Transform):
|
|
|
430
429
|
def check_validity_of_input(self, mobject: Mobject) -> None:
|
|
431
430
|
if not hasattr(mobject, "target"):
|
|
432
431
|
raise ValueError(
|
|
433
|
-
"MoveToTarget called on
|
|
432
|
+
"MoveToTarget called on mobjectwithout attribute 'target'",
|
|
434
433
|
)
|
|
435
434
|
|
|
436
435
|
|
|
@@ -225,7 +225,7 @@ class TransformMatchingShapes(TransformMatchingAbstractBase):
|
|
|
225
225
|
def get_mobject_key(mobject: Mobject) -> int:
|
|
226
226
|
mobject.save_state()
|
|
227
227
|
mobject.center()
|
|
228
|
-
mobject.
|
|
228
|
+
mobject.set(height=1)
|
|
229
229
|
result = hash(np.round(mobject.points, 3).tobytes())
|
|
230
230
|
mobject.restore()
|
|
231
231
|
return result
|
|
@@ -178,7 +178,7 @@ def always_rotate(mobject: Mobject, rate: float = 20 * DEGREES, **kwargs) -> Mob
|
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
def turn_animation_into_updater(
|
|
181
|
-
animation: Animation, cycle: bool = False, **kwargs
|
|
181
|
+
animation: Animation, cycle: bool = False, delay: float = 0, **kwargs
|
|
182
182
|
) -> Mobject:
|
|
183
183
|
"""
|
|
184
184
|
Add an updater to the animation's mobject which applies
|
|
@@ -187,6 +187,8 @@ def turn_animation_into_updater(
|
|
|
187
187
|
If cycle is True, this repeats over and over. Otherwise,
|
|
188
188
|
the updater will be popped upon completion
|
|
189
189
|
|
|
190
|
+
The ``delay`` parameter is the delay (in seconds) before the animation starts..
|
|
191
|
+
|
|
190
192
|
Examples
|
|
191
193
|
--------
|
|
192
194
|
|
|
@@ -206,21 +208,22 @@ def turn_animation_into_updater(
|
|
|
206
208
|
mobject = animation.mobject
|
|
207
209
|
animation.suspend_mobject_updating = False
|
|
208
210
|
animation.begin()
|
|
209
|
-
animation.total_time =
|
|
211
|
+
animation.total_time = -delay
|
|
210
212
|
|
|
211
213
|
def update(m: Mobject, dt: float):
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
214
|
+
if animation.total_time >= 0:
|
|
215
|
+
run_time = animation.get_run_time()
|
|
216
|
+
time_ratio = animation.total_time / run_time
|
|
217
|
+
if cycle:
|
|
218
|
+
alpha = time_ratio % 1
|
|
219
|
+
else:
|
|
220
|
+
alpha = np.clip(time_ratio, 0, 1)
|
|
221
|
+
if alpha >= 1:
|
|
222
|
+
animation.finish()
|
|
223
|
+
m.remove_updater(update)
|
|
224
|
+
return
|
|
225
|
+
animation.interpolate(alpha)
|
|
226
|
+
animation.update_mobjects(dt)
|
|
224
227
|
animation.total_time += dt
|
|
225
228
|
|
|
226
229
|
mobject.add_updater(update)
|