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/animation/composition.py
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
"""Tools for displaying multiple animations at once."""
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
|
-
from
|
|
5
|
+
from collections.abc import Callable, Iterable, Sequence
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
|
|
10
|
-
from manim.
|
|
11
|
-
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
10
|
+
from manim._config import config
|
|
11
|
+
from manim.animation.animation import Animation, prepare_animation
|
|
12
|
+
from manim.constants import RendererType
|
|
13
|
+
from manim.mobject.mobject import Group, Mobject
|
|
14
|
+
from manim.mobject.opengl.opengl_mobject import OpenGLGroup, OpenGLMobject
|
|
15
|
+
from manim.scene.scene import Scene
|
|
16
|
+
from manim.utils.iterables import remove_list_redundancies
|
|
17
|
+
from manim.utils.parameter_parsing import flatten_iterable_parameters
|
|
18
|
+
from manim.utils.rate_functions import linear
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
21
|
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVGroup
|
|
22
|
-
|
|
23
|
-
from ..mobject.types.vectorized_mobject import VGroup
|
|
22
|
+
from manim.mobject.types.vectorized_mobject import VGroup
|
|
24
23
|
|
|
25
24
|
__all__ = ["AnimationGroup", "Succession", "LaggedStart", "LaggedStartMap"]
|
|
26
25
|
|
|
@@ -29,47 +28,82 @@ DEFAULT_LAGGED_START_LAG_RATIO: float = 0.05
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
class AnimationGroup(Animation):
|
|
31
|
+
"""Plays a group or series of :class:`~.Animation`.
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
animations
|
|
36
|
+
Sequence of :class:`~.Animation` objects to be played.
|
|
37
|
+
group
|
|
38
|
+
A group of multiple :class:`~.Mobject`.
|
|
39
|
+
run_time
|
|
40
|
+
The duration of the animation in seconds.
|
|
41
|
+
rate_func
|
|
42
|
+
The function defining the animation progress based on the relative
|
|
43
|
+
runtime (see :mod:`~.rate_functions`) .
|
|
44
|
+
lag_ratio
|
|
45
|
+
Defines the delay after which the animation is applied to submobjects. A lag_ratio of
|
|
46
|
+
``n.nn`` means the next animation will play when ``nnn%`` of the current animation has played.
|
|
47
|
+
Defaults to 0.0, meaning that all animations will be played together.
|
|
48
|
+
|
|
49
|
+
This does not influence the total runtime of the animation. Instead the runtime
|
|
50
|
+
of individual animations is adjusted so that the complete animation has the defined
|
|
51
|
+
run time.
|
|
52
|
+
"""
|
|
53
|
+
|
|
32
54
|
def __init__(
|
|
33
55
|
self,
|
|
34
|
-
*animations: Animation,
|
|
35
|
-
group: Group | VGroup | OpenGLGroup | OpenGLVGroup = None,
|
|
56
|
+
*animations: Animation | Iterable[Animation],
|
|
57
|
+
group: Group | VGroup | OpenGLGroup | OpenGLVGroup | None = None,
|
|
36
58
|
run_time: float | None = None,
|
|
37
59
|
rate_func: Callable[[float], float] = linear,
|
|
38
60
|
lag_ratio: float = 0,
|
|
39
|
-
**kwargs,
|
|
40
|
-
)
|
|
41
|
-
|
|
61
|
+
**kwargs: Any,
|
|
62
|
+
):
|
|
63
|
+
arg_anim = flatten_iterable_parameters(animations)
|
|
64
|
+
self.animations = [prepare_animation(anim) for anim in arg_anim]
|
|
42
65
|
self.rate_func = rate_func
|
|
43
|
-
|
|
44
|
-
if self.group is None:
|
|
66
|
+
if group is None:
|
|
45
67
|
mobjects = remove_list_redundancies(
|
|
46
68
|
[anim.mobject for anim in self.animations if not anim.is_introducer()],
|
|
47
69
|
)
|
|
48
70
|
if config["renderer"] == RendererType.OPENGL:
|
|
49
|
-
self.group = OpenGLGroup(
|
|
71
|
+
self.group: Group | VGroup | OpenGLGroup | OpenGLVGroup = OpenGLGroup(
|
|
72
|
+
*mobjects
|
|
73
|
+
)
|
|
50
74
|
else:
|
|
51
75
|
self.group = Group(*mobjects)
|
|
76
|
+
else:
|
|
77
|
+
self.group = group
|
|
52
78
|
super().__init__(
|
|
53
79
|
self.group, rate_func=self.rate_func, lag_ratio=lag_ratio, **kwargs
|
|
54
80
|
)
|
|
55
81
|
self.run_time: float = self.init_run_time(run_time)
|
|
56
82
|
|
|
57
|
-
def get_all_mobjects(self) -> Sequence[Mobject]:
|
|
83
|
+
def get_all_mobjects(self) -> Sequence[Mobject | OpenGLMobject]:
|
|
58
84
|
return list(self.group)
|
|
59
85
|
|
|
60
86
|
def begin(self) -> None:
|
|
87
|
+
if not self.animations:
|
|
88
|
+
raise ValueError(
|
|
89
|
+
f"Trying to play {self} without animations, this is not supported. "
|
|
90
|
+
"Please add at least one subanimation."
|
|
91
|
+
)
|
|
92
|
+
self.anim_group_time = 0.0
|
|
61
93
|
if self.suspend_mobject_updating:
|
|
62
94
|
self.group.suspend_updating()
|
|
63
95
|
for anim in self.animations:
|
|
64
96
|
anim.begin()
|
|
65
97
|
|
|
66
|
-
def _setup_scene(self, scene) -> None:
|
|
98
|
+
def _setup_scene(self, scene: Scene) -> None:
|
|
67
99
|
for anim in self.animations:
|
|
68
100
|
anim._setup_scene(scene)
|
|
69
101
|
|
|
70
102
|
def finish(self) -> None:
|
|
71
103
|
for anim in self.animations:
|
|
72
104
|
anim.finish()
|
|
105
|
+
self.anims_begun[:] = True
|
|
106
|
+
self.anims_finished[:] = True
|
|
73
107
|
if self.suspend_mobject_updating:
|
|
74
108
|
self.group.resume_updating()
|
|
75
109
|
|
|
@@ -81,30 +115,49 @@ class AnimationGroup(Animation):
|
|
|
81
115
|
anim.clean_up_from_scene(scene)
|
|
82
116
|
|
|
83
117
|
def update_mobjects(self, dt: float) -> None:
|
|
84
|
-
for anim in self.
|
|
118
|
+
for anim in self.anims_with_timings["anim"][
|
|
119
|
+
self.anims_begun & ~self.anims_finished
|
|
120
|
+
]:
|
|
85
121
|
anim.update_mobjects(dt)
|
|
86
122
|
|
|
87
|
-
def init_run_time(self, run_time) -> float:
|
|
123
|
+
def init_run_time(self, run_time: float | None) -> float:
|
|
124
|
+
"""Calculates the run time of the animation, if different from ``run_time``.
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
run_time
|
|
129
|
+
The duration of the animation in seconds.
|
|
130
|
+
|
|
131
|
+
Returns
|
|
132
|
+
-------
|
|
133
|
+
run_time
|
|
134
|
+
The duration of the animation in seconds.
|
|
135
|
+
"""
|
|
88
136
|
self.build_animations_with_timings()
|
|
89
|
-
if
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
137
|
+
# Note: if lag_ratio < 1, then not necessarily the final animation's
|
|
138
|
+
# end time will be the max end time! Therefore we must calculate the
|
|
139
|
+
# maximum over all the end times, and not just take the last one.
|
|
140
|
+
# Example: if you want to play 2 animations of 10s and 1s with a
|
|
141
|
+
# lag_ratio of 0.1, the 1st one will end at t=10 and the 2nd one will
|
|
142
|
+
# end at t=2, so the AnimationGroup will end at t=10.
|
|
143
|
+
self.max_end_time = max(self.anims_with_timings["end"], default=0)
|
|
93
144
|
return self.max_end_time if run_time is None else run_time
|
|
94
145
|
|
|
95
146
|
def build_animations_with_timings(self) -> None:
|
|
96
|
-
"""
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"""
|
|
100
|
-
self.anims_with_timings =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
147
|
+
"""Creates a list of triplets of the form (anim, start_time, end_time)."""
|
|
148
|
+
run_times = np.array([anim.run_time for anim in self.animations])
|
|
149
|
+
num_animations = run_times.shape[0]
|
|
150
|
+
dtype = [("anim", "O"), ("start", "f8"), ("end", "f8")]
|
|
151
|
+
self.anims_with_timings: np.ndarray = np.zeros(num_animations, dtype=dtype)
|
|
152
|
+
self.anims_begun: np.ndarray = np.zeros(num_animations, dtype=bool)
|
|
153
|
+
self.anims_finished: np.ndarray = np.zeros(num_animations, dtype=bool)
|
|
154
|
+
if num_animations == 0:
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
lags = run_times[:-1] * self.lag_ratio
|
|
158
|
+
self.anims_with_timings["anim"] = self.animations
|
|
159
|
+
self.anims_with_timings["start"][1:] = np.add.accumulate(lags)
|
|
160
|
+
self.anims_with_timings["end"] = self.anims_with_timings["start"] + run_times
|
|
108
161
|
|
|
109
162
|
def interpolate(self, alpha: float) -> None:
|
|
110
163
|
# Note, if the run_time of AnimationGroup has been
|
|
@@ -112,22 +165,80 @@ class AnimationGroup(Animation):
|
|
|
112
165
|
# times might not correspond to actual times,
|
|
113
166
|
# e.g. of the surrounding scene. Instead they'd
|
|
114
167
|
# be a rescaled version. But that's okay!
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
168
|
+
anim_group_time = self.rate_func(alpha) * self.max_end_time
|
|
169
|
+
time_goes_back = anim_group_time < self.anim_group_time
|
|
170
|
+
|
|
171
|
+
# Only update ongoing animations
|
|
172
|
+
awt = self.anims_with_timings
|
|
173
|
+
new_begun = anim_group_time >= awt["start"]
|
|
174
|
+
new_finished = anim_group_time > awt["end"]
|
|
175
|
+
to_update = awt[
|
|
176
|
+
(self.anims_begun | new_begun) & (~self.anims_finished | ~new_finished)
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
run_times = to_update["end"] - to_update["start"]
|
|
180
|
+
with_zero_run_time = run_times == 0
|
|
181
|
+
run_times[with_zero_run_time] = 1
|
|
182
|
+
sub_alphas = (anim_group_time - to_update["start"]) / run_times
|
|
183
|
+
if time_goes_back:
|
|
184
|
+
sub_alphas[(sub_alphas < 0) | with_zero_run_time] = 0
|
|
185
|
+
else:
|
|
186
|
+
sub_alphas[(sub_alphas > 1) | with_zero_run_time] = 1
|
|
187
|
+
|
|
188
|
+
for anim_to_update, sub_alpha in zip(to_update["anim"], sub_alphas):
|
|
189
|
+
anim_to_update.interpolate(sub_alpha)
|
|
190
|
+
|
|
191
|
+
self.anim_group_time = anim_group_time
|
|
192
|
+
self.anims_begun = new_begun
|
|
193
|
+
self.anims_finished = new_finished
|
|
123
194
|
|
|
124
195
|
|
|
125
196
|
class Succession(AnimationGroup):
|
|
126
|
-
|
|
197
|
+
"""Plays a series of animations in succession.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
animations
|
|
202
|
+
Sequence of :class:`~.Animation` objects to be played.
|
|
203
|
+
lag_ratio
|
|
204
|
+
Defines the delay after which the animation is applied to submobjects. A lag_ratio of
|
|
205
|
+
``n.nn`` means the next animation will play when ``nnn%`` of the current animation has played.
|
|
206
|
+
Defaults to 1.0, meaning that the next animation will begin when 100% of the current
|
|
207
|
+
animation has played.
|
|
208
|
+
|
|
209
|
+
This does not influence the total runtime of the animation. Instead the runtime
|
|
210
|
+
of individual animations is adjusted so that the complete animation has the defined
|
|
211
|
+
run time.
|
|
212
|
+
|
|
213
|
+
Examples
|
|
214
|
+
--------
|
|
215
|
+
.. manim:: SuccessionExample
|
|
216
|
+
|
|
217
|
+
class SuccessionExample(Scene):
|
|
218
|
+
def construct(self):
|
|
219
|
+
dot1 = Dot(point=LEFT * 2 + UP * 2, radius=0.16, color=BLUE)
|
|
220
|
+
dot2 = Dot(point=LEFT * 2 + DOWN * 2, radius=0.16, color=MAROON)
|
|
221
|
+
dot3 = Dot(point=RIGHT * 2 + DOWN * 2, radius=0.16, color=GREEN)
|
|
222
|
+
dot4 = Dot(point=RIGHT * 2 + UP * 2, radius=0.16, color=YELLOW)
|
|
223
|
+
self.add(dot1, dot2, dot3, dot4)
|
|
224
|
+
|
|
225
|
+
self.play(Succession(
|
|
226
|
+
dot1.animate.move_to(dot2),
|
|
227
|
+
dot2.animate.move_to(dot3),
|
|
228
|
+
dot3.animate.move_to(dot4),
|
|
229
|
+
dot4.animate.move_to(dot1)
|
|
230
|
+
))
|
|
231
|
+
"""
|
|
232
|
+
|
|
233
|
+
def __init__(self, *animations: Animation, lag_ratio: float = 1, **kwargs: Any):
|
|
127
234
|
super().__init__(*animations, lag_ratio=lag_ratio, **kwargs)
|
|
128
235
|
|
|
129
236
|
def begin(self) -> None:
|
|
130
|
-
|
|
237
|
+
if not self.animations:
|
|
238
|
+
raise ValueError(
|
|
239
|
+
f"Trying to play {self} without animations, this is not supported. "
|
|
240
|
+
"Please add at least one subanimation."
|
|
241
|
+
)
|
|
131
242
|
self.update_active_animation(0)
|
|
132
243
|
|
|
133
244
|
def finish(self) -> None:
|
|
@@ -138,7 +249,7 @@ class Succession(AnimationGroup):
|
|
|
138
249
|
if self.active_animation:
|
|
139
250
|
self.active_animation.update_mobjects(dt)
|
|
140
251
|
|
|
141
|
-
def _setup_scene(self, scene) -> None:
|
|
252
|
+
def _setup_scene(self, scene: Scene | None) -> None:
|
|
142
253
|
if scene is None:
|
|
143
254
|
return
|
|
144
255
|
if self.is_introducer():
|
|
@@ -158,10 +269,14 @@ class Succession(AnimationGroup):
|
|
|
158
269
|
self.active_animation = self.animations[index]
|
|
159
270
|
self.active_animation._setup_scene(self.scene)
|
|
160
271
|
self.active_animation.begin()
|
|
161
|
-
self.active_start_time = self.anims_with_timings[index][
|
|
162
|
-
self.active_end_time = self.anims_with_timings[index][
|
|
272
|
+
self.active_start_time = self.anims_with_timings[index]["start"]
|
|
273
|
+
self.active_end_time = self.anims_with_timings[index]["end"]
|
|
163
274
|
|
|
164
275
|
def next_animation(self) -> None:
|
|
276
|
+
"""Proceeds to the next animation.
|
|
277
|
+
|
|
278
|
+
This method is called right when the active animation finishes.
|
|
279
|
+
"""
|
|
165
280
|
if self.active_animation is not None:
|
|
166
281
|
self.active_animation.finish()
|
|
167
282
|
self.update_active_animation(self.active_index + 1)
|
|
@@ -172,38 +287,121 @@ class Succession(AnimationGroup):
|
|
|
172
287
|
self.next_animation()
|
|
173
288
|
if self.active_animation is not None and self.active_start_time is not None:
|
|
174
289
|
elapsed = current_time - self.active_start_time
|
|
175
|
-
active_run_time = self.active_animation.
|
|
290
|
+
active_run_time = self.active_animation.run_time
|
|
176
291
|
subalpha = elapsed / active_run_time if active_run_time != 0.0 else 1.0
|
|
177
292
|
self.active_animation.interpolate(subalpha)
|
|
178
293
|
|
|
179
294
|
|
|
180
295
|
class LaggedStart(AnimationGroup):
|
|
296
|
+
"""Adjusts the timing of a series of :class:`~.Animation` according to ``lag_ratio``.
|
|
297
|
+
|
|
298
|
+
Parameters
|
|
299
|
+
----------
|
|
300
|
+
animations
|
|
301
|
+
Sequence of :class:`~.Animation` objects to be played.
|
|
302
|
+
lag_ratio
|
|
303
|
+
Defines the delay after which the animation is applied to submobjects. A lag_ratio of
|
|
304
|
+
``n.nn`` means the next animation will play when ``nnn%`` of the current animation has played.
|
|
305
|
+
Defaults to 0.05, meaning that the next animation will begin when 5% of the current
|
|
306
|
+
animation has played.
|
|
307
|
+
|
|
308
|
+
This does not influence the total runtime of the animation. Instead the runtime
|
|
309
|
+
of individual animations is adjusted so that the complete animation has the defined
|
|
310
|
+
run time.
|
|
311
|
+
|
|
312
|
+
Examples
|
|
313
|
+
--------
|
|
314
|
+
.. manim:: LaggedStartExample
|
|
315
|
+
|
|
316
|
+
class LaggedStartExample(Scene):
|
|
317
|
+
def construct(self):
|
|
318
|
+
title = Text("lag_ratio = 0.25").to_edge(UP)
|
|
319
|
+
|
|
320
|
+
dot1 = Dot(point=LEFT * 2 + UP, radius=0.16)
|
|
321
|
+
dot2 = Dot(point=LEFT * 2, radius=0.16)
|
|
322
|
+
dot3 = Dot(point=LEFT * 2 + DOWN, radius=0.16)
|
|
323
|
+
line_25 = DashedLine(
|
|
324
|
+
start=LEFT + UP * 2,
|
|
325
|
+
end=LEFT + DOWN * 2,
|
|
326
|
+
color=RED
|
|
327
|
+
)
|
|
328
|
+
label = Text("25%", font_size=24).next_to(line_25, UP)
|
|
329
|
+
self.add(title, dot1, dot2, dot3, line_25, label)
|
|
330
|
+
|
|
331
|
+
self.play(LaggedStart(
|
|
332
|
+
dot1.animate.shift(RIGHT * 4),
|
|
333
|
+
dot2.animate.shift(RIGHT * 4),
|
|
334
|
+
dot3.animate.shift(RIGHT * 4),
|
|
335
|
+
lag_ratio=0.25,
|
|
336
|
+
run_time=4
|
|
337
|
+
))
|
|
338
|
+
"""
|
|
339
|
+
|
|
181
340
|
def __init__(
|
|
182
341
|
self,
|
|
183
342
|
*animations: Animation,
|
|
184
343
|
lag_ratio: float = DEFAULT_LAGGED_START_LAG_RATIO,
|
|
185
|
-
**kwargs,
|
|
344
|
+
**kwargs: Any,
|
|
186
345
|
):
|
|
187
346
|
super().__init__(*animations, lag_ratio=lag_ratio, **kwargs)
|
|
188
347
|
|
|
189
348
|
|
|
190
349
|
class LaggedStartMap(LaggedStart):
|
|
350
|
+
"""Plays a series of :class:`~.Animation` while mapping a function to submobjects.
|
|
351
|
+
|
|
352
|
+
Parameters
|
|
353
|
+
----------
|
|
354
|
+
AnimationClass
|
|
355
|
+
:class:`~.Animation` to apply to mobject.
|
|
356
|
+
mobject
|
|
357
|
+
:class:`~.Mobject` whose submobjects the animation, and optionally the function,
|
|
358
|
+
are to be applied.
|
|
359
|
+
arg_creator
|
|
360
|
+
Function which will be applied to :class:`~.Mobject`.
|
|
361
|
+
run_time
|
|
362
|
+
The duration of the animation in seconds.
|
|
363
|
+
|
|
364
|
+
Examples
|
|
365
|
+
--------
|
|
366
|
+
.. manim:: LaggedStartMapExample
|
|
367
|
+
|
|
368
|
+
class LaggedStartMapExample(Scene):
|
|
369
|
+
def construct(self):
|
|
370
|
+
title = Tex("LaggedStartMap").to_edge(UP, buff=LARGE_BUFF)
|
|
371
|
+
dots = VGroup(
|
|
372
|
+
*[Dot(radius=0.16) for _ in range(35)]
|
|
373
|
+
).arrange_in_grid(rows=5, cols=7, buff=MED_LARGE_BUFF)
|
|
374
|
+
self.add(dots, title)
|
|
375
|
+
|
|
376
|
+
# Animate yellow ripple effect
|
|
377
|
+
for mob in dots, title:
|
|
378
|
+
self.play(LaggedStartMap(
|
|
379
|
+
ApplyMethod, mob,
|
|
380
|
+
lambda m : (m.set_color, YELLOW),
|
|
381
|
+
lag_ratio = 0.1,
|
|
382
|
+
rate_func = there_and_back,
|
|
383
|
+
run_time = 2
|
|
384
|
+
))
|
|
385
|
+
"""
|
|
386
|
+
|
|
191
387
|
def __init__(
|
|
192
388
|
self,
|
|
193
|
-
|
|
389
|
+
animation_class: type[Animation],
|
|
194
390
|
mobject: Mobject,
|
|
195
|
-
arg_creator: Callable[[Mobject],
|
|
391
|
+
arg_creator: Callable[[Mobject], Iterable[Any]] | None = None,
|
|
196
392
|
run_time: float = 2,
|
|
197
|
-
**kwargs,
|
|
198
|
-
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
393
|
+
**kwargs: Any,
|
|
394
|
+
):
|
|
395
|
+
if arg_creator is None:
|
|
396
|
+
|
|
397
|
+
def identity(mob: Mobject) -> Mobject:
|
|
398
|
+
return mob
|
|
399
|
+
|
|
400
|
+
arg_creator = identity
|
|
401
|
+
|
|
402
|
+
args_list = [arg_creator(submob) for submob in mobject]
|
|
205
403
|
anim_kwargs = dict(kwargs)
|
|
206
404
|
if "lag_ratio" in anim_kwargs:
|
|
207
405
|
anim_kwargs.pop("lag_ratio")
|
|
208
|
-
animations = [
|
|
406
|
+
animations = [animation_class(*args, **anim_kwargs) for args in args_list]
|
|
209
407
|
super().__init__(*animations, run_time=run_time, **kwargs)
|