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/creation.py
CHANGED
|
@@ -70,29 +70,33 @@ __all__ = [
|
|
|
70
70
|
"RemoveTextLetterByLetter",
|
|
71
71
|
"ShowSubmobjectsOneByOne",
|
|
72
72
|
"AddTextWordByWord",
|
|
73
|
+
"TypeWithCursor",
|
|
74
|
+
"UntypeWithCursor",
|
|
73
75
|
]
|
|
74
76
|
|
|
75
77
|
|
|
76
78
|
import itertools as it
|
|
77
|
-
from
|
|
79
|
+
from collections.abc import Callable, Iterable, Sequence
|
|
80
|
+
from typing import TYPE_CHECKING
|
|
78
81
|
|
|
79
82
|
import numpy as np
|
|
80
|
-
from colour import Color
|
|
81
83
|
|
|
82
84
|
if TYPE_CHECKING:
|
|
83
85
|
from manim.mobject.text.text_mobject import Text
|
|
86
|
+
from manim.scene.scene import Scene
|
|
84
87
|
|
|
88
|
+
from manim.constants import RIGHT, TAU
|
|
85
89
|
from manim.mobject.opengl.opengl_surface import OpenGLSurface
|
|
86
90
|
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
|
|
91
|
+
from manim.utils.color import ManimColor
|
|
87
92
|
|
|
88
93
|
from .. import config
|
|
89
94
|
from ..animation.animation import Animation
|
|
90
95
|
from ..animation.composition import Succession
|
|
91
|
-
from ..constants import TAU
|
|
92
96
|
from ..mobject.mobject import Group, Mobject
|
|
93
97
|
from ..mobject.types.vectorized_mobject import VMobject
|
|
94
98
|
from ..utils.bezier import integer_interpolate
|
|
95
|
-
from ..utils.rate_functions import double_smooth, linear
|
|
99
|
+
from ..utils.rate_functions import double_smooth, linear
|
|
96
100
|
|
|
97
101
|
|
|
98
102
|
class ShowPartial(Animation):
|
|
@@ -116,7 +120,7 @@ class ShowPartial(Animation):
|
|
|
116
120
|
):
|
|
117
121
|
pointwise = getattr(mobject, "pointwise_become_partial", None)
|
|
118
122
|
if not callable(pointwise):
|
|
119
|
-
raise
|
|
123
|
+
raise TypeError(f"{self.__class__.__name__} only works for VMobjects.")
|
|
120
124
|
super().__init__(mobject, **kwargs)
|
|
121
125
|
|
|
122
126
|
def interpolate_submobject(
|
|
@@ -129,7 +133,7 @@ class ShowPartial(Animation):
|
|
|
129
133
|
starting_submobject, *self._get_bounds(alpha)
|
|
130
134
|
)
|
|
131
135
|
|
|
132
|
-
def _get_bounds(self, alpha: float) ->
|
|
136
|
+
def _get_bounds(self, alpha: float) -> tuple[float, float]:
|
|
133
137
|
raise NotImplementedError("Please use Create or ShowPassingFlash")
|
|
134
138
|
|
|
135
139
|
|
|
@@ -169,7 +173,7 @@ class Create(ShowPartial):
|
|
|
169
173
|
) -> None:
|
|
170
174
|
super().__init__(mobject, lag_ratio=lag_ratio, introducer=introducer, **kwargs)
|
|
171
175
|
|
|
172
|
-
def _get_bounds(self, alpha: float) -> tuple[
|
|
176
|
+
def _get_bounds(self, alpha: float) -> tuple[float, float]:
|
|
173
177
|
return (0, alpha)
|
|
174
178
|
|
|
175
179
|
|
|
@@ -225,8 +229,6 @@ class DrawBorderThenFill(Animation):
|
|
|
225
229
|
rate_func: Callable[[float], float] = double_smooth,
|
|
226
230
|
stroke_width: float = 2,
|
|
227
231
|
stroke_color: str = None,
|
|
228
|
-
draw_border_animation_config: dict = {}, # what does this dict accept?
|
|
229
|
-
fill_animation_config: dict = {},
|
|
230
232
|
introducer: bool = True,
|
|
231
233
|
**kwargs,
|
|
232
234
|
) -> None:
|
|
@@ -240,13 +242,13 @@ class DrawBorderThenFill(Animation):
|
|
|
240
242
|
)
|
|
241
243
|
self.stroke_width = stroke_width
|
|
242
244
|
self.stroke_color = stroke_color
|
|
243
|
-
self.draw_border_animation_config = draw_border_animation_config
|
|
244
|
-
self.fill_animation_config = fill_animation_config
|
|
245
245
|
self.outline = self.get_outline()
|
|
246
246
|
|
|
247
247
|
def _typecheck_input(self, vmobject: VMobject | OpenGLVMobject) -> None:
|
|
248
248
|
if not isinstance(vmobject, (VMobject, OpenGLVMobject)):
|
|
249
|
-
raise TypeError(
|
|
249
|
+
raise TypeError(
|
|
250
|
+
f"{self.__class__.__name__} only works for vectorized Mobjects"
|
|
251
|
+
)
|
|
250
252
|
|
|
251
253
|
def begin(self) -> None:
|
|
252
254
|
self.outline = self.get_outline()
|
|
@@ -259,7 +261,7 @@ class DrawBorderThenFill(Animation):
|
|
|
259
261
|
sm.set_stroke(color=self.get_stroke_color(sm), width=self.stroke_width)
|
|
260
262
|
return outline
|
|
261
263
|
|
|
262
|
-
def get_stroke_color(self, vmobject: VMobject | OpenGLVMobject) ->
|
|
264
|
+
def get_stroke_color(self, vmobject: VMobject | OpenGLVMobject) -> ManimColor:
|
|
263
265
|
if self.stroke_color:
|
|
264
266
|
return self.stroke_color
|
|
265
267
|
elif vmobject.get_stroke_width() > 0:
|
|
@@ -277,7 +279,7 @@ class DrawBorderThenFill(Animation):
|
|
|
277
279
|
alpha: float,
|
|
278
280
|
) -> None: # Fixme: not matching the parent class? What is outline doing here?
|
|
279
281
|
index: int
|
|
280
|
-
subalpha:
|
|
282
|
+
subalpha: float
|
|
281
283
|
index, subalpha = integer_interpolate(0, 2, alpha)
|
|
282
284
|
if index == 0:
|
|
283
285
|
submobject.pointwise_become_partial(outline, 0, subalpha)
|
|
@@ -301,7 +303,7 @@ class Write(DrawBorderThenFill):
|
|
|
301
303
|
|
|
302
304
|
class ShowWriteReversed(Scene):
|
|
303
305
|
def construct(self):
|
|
304
|
-
self.play(Write(Text("Hello", font_size=144), reverse=True))
|
|
306
|
+
self.play(Write(Text("Hello", font_size=144), reverse=True, remover=False))
|
|
305
307
|
|
|
306
308
|
Tests
|
|
307
309
|
-----
|
|
@@ -347,10 +349,7 @@ class Write(DrawBorderThenFill):
|
|
|
347
349
|
) -> tuple[float, float]:
|
|
348
350
|
length = len(vmobject.family_members_with_points())
|
|
349
351
|
if run_time is None:
|
|
350
|
-
if length < 15
|
|
351
|
-
run_time = 1
|
|
352
|
-
else:
|
|
353
|
-
run_time = 2
|
|
352
|
+
run_time = 1 if length < 15 else 2
|
|
354
353
|
if lag_ratio is None:
|
|
355
354
|
lag_ratio = min(4.0 / max(1.0, length), 0.2)
|
|
356
355
|
return run_time, lag_ratio
|
|
@@ -404,7 +403,6 @@ class Unwrite(Write):
|
|
|
404
403
|
reverse: bool = True,
|
|
405
404
|
**kwargs,
|
|
406
405
|
) -> None:
|
|
407
|
-
|
|
408
406
|
run_time: float | None = kwargs.pop("run_time", None)
|
|
409
407
|
lag_ratio: float | None = kwargs.pop("lag_ratio", None)
|
|
410
408
|
run_time, lag_ratio = self._set_default_config_from_length(
|
|
@@ -457,7 +455,7 @@ class SpiralIn(Animation):
|
|
|
457
455
|
fade_in_fraction=0.3,
|
|
458
456
|
**kwargs,
|
|
459
457
|
) -> None:
|
|
460
|
-
self.shapes = shapes
|
|
458
|
+
self.shapes = shapes.copy()
|
|
461
459
|
self.scale_factor = scale_factor
|
|
462
460
|
self.shape_center = shapes.get_center()
|
|
463
461
|
self.fade_in_fraction = fade_in_fraction
|
|
@@ -474,15 +472,21 @@ class SpiralIn(Animation):
|
|
|
474
472
|
|
|
475
473
|
def interpolate_mobject(self, alpha: float) -> None:
|
|
476
474
|
alpha = self.rate_func(alpha)
|
|
477
|
-
for shape in self.shapes:
|
|
475
|
+
for original_shape, shape in zip(self.shapes, self.mobject):
|
|
478
476
|
shape.restore()
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
477
|
+
fill_opacity = original_shape.get_fill_opacity()
|
|
478
|
+
stroke_opacity = original_shape.get_stroke_opacity()
|
|
479
|
+
new_fill_opacity = min(
|
|
480
|
+
fill_opacity, alpha * fill_opacity / self.fade_in_fraction
|
|
481
|
+
)
|
|
482
|
+
new_stroke_opacity = min(
|
|
483
|
+
stroke_opacity, alpha * stroke_opacity / self.fade_in_fraction
|
|
484
|
+
)
|
|
482
485
|
shape.shift((shape.final_position - shape.initial_position) * alpha)
|
|
483
486
|
shape.rotate(TAU * alpha, about_point=self.shape_center)
|
|
484
487
|
shape.rotate(-TAU * alpha, about_point=shape.get_center_of_mass())
|
|
485
|
-
shape.
|
|
488
|
+
shape.set_fill(opacity=new_fill_opacity)
|
|
489
|
+
shape.set_stroke(opacity=new_stroke_opacity)
|
|
486
490
|
|
|
487
491
|
|
|
488
492
|
class ShowIncreasingSubsets(Animation):
|
|
@@ -564,6 +568,11 @@ class AddTextLetterByLetter(ShowIncreasingSubsets):
|
|
|
564
568
|
**kwargs,
|
|
565
569
|
) -> None:
|
|
566
570
|
self.time_per_char = time_per_char
|
|
571
|
+
# Check for empty text using family_members_with_points()
|
|
572
|
+
if not text.family_members_with_points():
|
|
573
|
+
raise ValueError(
|
|
574
|
+
f"The text mobject {text} does not seem to contain any characters."
|
|
575
|
+
)
|
|
567
576
|
if run_time is None:
|
|
568
577
|
# minimum time per character is 1/frame_rate, otherwise
|
|
569
578
|
# the animation does not finish.
|
|
@@ -664,3 +673,176 @@ class AddTextWordByWord(Succession):
|
|
|
664
673
|
)
|
|
665
674
|
)
|
|
666
675
|
super().__init__(*anims, **kwargs)
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
class TypeWithCursor(AddTextLetterByLetter):
|
|
679
|
+
"""Similar to :class:`~.AddTextLetterByLetter` , but with an additional cursor mobject at the end.
|
|
680
|
+
|
|
681
|
+
Parameters
|
|
682
|
+
----------
|
|
683
|
+
time_per_char
|
|
684
|
+
Frequency of appearance of the letters.
|
|
685
|
+
cursor
|
|
686
|
+
:class:`~.Mobject` shown after the last added letter.
|
|
687
|
+
buff
|
|
688
|
+
Controls how far away the cursor is to the right of the last added letter.
|
|
689
|
+
keep_cursor_y
|
|
690
|
+
If ``True``, the cursor's y-coordinate is set to the center of the ``Text`` and remains the same throughout the animation. Otherwise, it is set to the center of the last added letter.
|
|
691
|
+
leave_cursor_on
|
|
692
|
+
Whether to show the cursor after the animation.
|
|
693
|
+
|
|
694
|
+
.. tip::
|
|
695
|
+
This is currently only possible for class:`~.Text` and not for class:`~.MathTex`.
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
Examples
|
|
699
|
+
--------
|
|
700
|
+
|
|
701
|
+
.. manim:: InsertingTextExample
|
|
702
|
+
:ref_classes: Blink
|
|
703
|
+
|
|
704
|
+
class InsertingTextExample(Scene):
|
|
705
|
+
def construct(self):
|
|
706
|
+
text = Text("Inserting", color=PURPLE).scale(1.5).to_edge(LEFT)
|
|
707
|
+
cursor = Rectangle(
|
|
708
|
+
color = GREY_A,
|
|
709
|
+
fill_color = GREY_A,
|
|
710
|
+
fill_opacity = 1.0,
|
|
711
|
+
height = 1.1,
|
|
712
|
+
width = 0.5,
|
|
713
|
+
).move_to(text[0]) # Position the cursor
|
|
714
|
+
|
|
715
|
+
self.play(TypeWithCursor(text, cursor))
|
|
716
|
+
self.play(Blink(cursor, blinks=2))
|
|
717
|
+
|
|
718
|
+
"""
|
|
719
|
+
|
|
720
|
+
def __init__(
|
|
721
|
+
self,
|
|
722
|
+
text: Text,
|
|
723
|
+
cursor: Mobject,
|
|
724
|
+
buff: float = 0.1,
|
|
725
|
+
keep_cursor_y: bool = True,
|
|
726
|
+
leave_cursor_on: bool = True,
|
|
727
|
+
time_per_char: float = 0.1,
|
|
728
|
+
reverse_rate_function=False,
|
|
729
|
+
introducer=True,
|
|
730
|
+
**kwargs,
|
|
731
|
+
) -> None:
|
|
732
|
+
self.cursor = cursor
|
|
733
|
+
self.buff = buff
|
|
734
|
+
self.keep_cursor_y = keep_cursor_y
|
|
735
|
+
self.leave_cursor_on = leave_cursor_on
|
|
736
|
+
super().__init__(
|
|
737
|
+
text,
|
|
738
|
+
time_per_char=time_per_char,
|
|
739
|
+
reverse_rate_function=reverse_rate_function,
|
|
740
|
+
introducer=introducer,
|
|
741
|
+
**kwargs,
|
|
742
|
+
)
|
|
743
|
+
|
|
744
|
+
def begin(self) -> None:
|
|
745
|
+
self.y_cursor = self.cursor.get_y()
|
|
746
|
+
self.cursor.initial_position = self.mobject.get_center()
|
|
747
|
+
if self.keep_cursor_y:
|
|
748
|
+
self.cursor.set_y(self.y_cursor)
|
|
749
|
+
|
|
750
|
+
self.cursor.set_opacity(0)
|
|
751
|
+
self.mobject.add(self.cursor)
|
|
752
|
+
super().begin()
|
|
753
|
+
|
|
754
|
+
def finish(self) -> None:
|
|
755
|
+
if self.leave_cursor_on:
|
|
756
|
+
self.cursor.set_opacity(1)
|
|
757
|
+
else:
|
|
758
|
+
self.cursor.set_opacity(0)
|
|
759
|
+
self.mobject.remove(self.cursor)
|
|
760
|
+
super().finish()
|
|
761
|
+
|
|
762
|
+
def clean_up_from_scene(self, scene: Scene) -> None:
|
|
763
|
+
if not self.leave_cursor_on:
|
|
764
|
+
scene.remove(self.cursor)
|
|
765
|
+
super().clean_up_from_scene(scene)
|
|
766
|
+
|
|
767
|
+
def update_submobject_list(self, index: int) -> None:
|
|
768
|
+
for mobj in self.all_submobs[:index]:
|
|
769
|
+
mobj.set_opacity(1)
|
|
770
|
+
|
|
771
|
+
for mobj in self.all_submobs[index:]:
|
|
772
|
+
mobj.set_opacity(0)
|
|
773
|
+
|
|
774
|
+
if index != 0:
|
|
775
|
+
self.cursor.next_to(
|
|
776
|
+
self.all_submobs[index - 1], RIGHT, buff=self.buff
|
|
777
|
+
).set_y(self.cursor.initial_position[1])
|
|
778
|
+
else:
|
|
779
|
+
self.cursor.move_to(self.all_submobs[0]).set_y(
|
|
780
|
+
self.cursor.initial_position[1]
|
|
781
|
+
)
|
|
782
|
+
|
|
783
|
+
if self.keep_cursor_y:
|
|
784
|
+
self.cursor.set_y(self.y_cursor)
|
|
785
|
+
self.cursor.set_opacity(1)
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
class UntypeWithCursor(TypeWithCursor):
|
|
789
|
+
"""Similar to :class:`~.RemoveTextLetterByLetter` , but with an additional cursor mobject at the end.
|
|
790
|
+
|
|
791
|
+
Parameters
|
|
792
|
+
----------
|
|
793
|
+
time_per_char
|
|
794
|
+
Frequency of appearance of the letters.
|
|
795
|
+
cursor
|
|
796
|
+
:class:`~.Mobject` shown after the last added letter.
|
|
797
|
+
buff
|
|
798
|
+
Controls how far away the cursor is to the right of the last added letter.
|
|
799
|
+
keep_cursor_y
|
|
800
|
+
If ``True``, the cursor's y-coordinate is set to the center of the ``Text`` and remains the same throughout the animation. Otherwise, it is set to the center of the last added letter.
|
|
801
|
+
leave_cursor_on
|
|
802
|
+
Whether to show the cursor after the animation.
|
|
803
|
+
|
|
804
|
+
.. tip::
|
|
805
|
+
This is currently only possible for class:`~.Text` and not for class:`~.MathTex`.
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
Examples
|
|
809
|
+
--------
|
|
810
|
+
|
|
811
|
+
.. manim:: DeletingTextExample
|
|
812
|
+
:ref_classes: Blink
|
|
813
|
+
|
|
814
|
+
class DeletingTextExample(Scene):
|
|
815
|
+
def construct(self):
|
|
816
|
+
text = Text("Deleting", color=PURPLE).scale(1.5).to_edge(LEFT)
|
|
817
|
+
cursor = Rectangle(
|
|
818
|
+
color = GREY_A,
|
|
819
|
+
fill_color = GREY_A,
|
|
820
|
+
fill_opacity = 1.0,
|
|
821
|
+
height = 1.1,
|
|
822
|
+
width = 0.5,
|
|
823
|
+
).move_to(text[0]) # Position the cursor
|
|
824
|
+
|
|
825
|
+
self.play(UntypeWithCursor(text, cursor))
|
|
826
|
+
self.play(Blink(cursor, blinks=2))
|
|
827
|
+
|
|
828
|
+
"""
|
|
829
|
+
|
|
830
|
+
def __init__(
|
|
831
|
+
self,
|
|
832
|
+
text: Text,
|
|
833
|
+
cursor: VMobject | None = None,
|
|
834
|
+
time_per_char: float = 0.1,
|
|
835
|
+
reverse_rate_function=True,
|
|
836
|
+
introducer=False,
|
|
837
|
+
remover=True,
|
|
838
|
+
**kwargs,
|
|
839
|
+
) -> None:
|
|
840
|
+
super().__init__(
|
|
841
|
+
text,
|
|
842
|
+
cursor=cursor,
|
|
843
|
+
time_per_char=time_per_char,
|
|
844
|
+
reverse_rate_function=reverse_rate_function,
|
|
845
|
+
introducer=introducer,
|
|
846
|
+
remover=remover,
|
|
847
|
+
**kwargs,
|
|
848
|
+
)
|
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__ = [
|
|
@@ -20,6 +19,8 @@ __all__ = [
|
|
|
20
19
|
"FadeIn",
|
|
21
20
|
]
|
|
22
21
|
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
23
24
|
import numpy as np
|
|
24
25
|
|
|
25
26
|
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
|
|
@@ -54,14 +55,11 @@ class _Fade(Transform):
|
|
|
54
55
|
shift: np.ndarray | None = None,
|
|
55
56
|
target_position: np.ndarray | Mobject | None = None,
|
|
56
57
|
scale: float = 1,
|
|
57
|
-
**kwargs,
|
|
58
|
+
**kwargs: Any,
|
|
58
59
|
) -> None:
|
|
59
60
|
if not mobjects:
|
|
60
61
|
raise ValueError("At least one mobject must be passed.")
|
|
61
|
-
if len(mobjects) == 1
|
|
62
|
-
mobject = mobjects[0]
|
|
63
|
-
else:
|
|
64
|
-
mobject = Group(*mobjects)
|
|
62
|
+
mobject = mobjects[0] if len(mobjects) == 1 else Group(*mobjects)
|
|
65
63
|
|
|
66
64
|
self.point_target = False
|
|
67
65
|
if shift is None:
|
|
@@ -89,7 +87,7 @@ class _Fade(Transform):
|
|
|
89
87
|
Mobject
|
|
90
88
|
The faded, shifted and scaled copy of the mobject.
|
|
91
89
|
"""
|
|
92
|
-
faded_mobject = self.mobject.copy()
|
|
90
|
+
faded_mobject: Mobject = self.mobject.copy() # type: ignore[assignment]
|
|
93
91
|
faded_mobject.fade(1)
|
|
94
92
|
direction_modifier = -1 if fadeIn and not self.point_target else 1
|
|
95
93
|
faded_mobject.shift(self.shift_vector * direction_modifier)
|
|
@@ -98,7 +96,7 @@ class _Fade(Transform):
|
|
|
98
96
|
|
|
99
97
|
|
|
100
98
|
class FadeIn(_Fade):
|
|
101
|
-
"""Fade in :class:`~.Mobject` s.
|
|
99
|
+
r"""Fade in :class:`~.Mobject` s.
|
|
102
100
|
|
|
103
101
|
Parameters
|
|
104
102
|
----------
|
|
@@ -123,7 +121,7 @@ class FadeIn(_Fade):
|
|
|
123
121
|
dot = Dot(UP * 2 + LEFT)
|
|
124
122
|
self.add(dot)
|
|
125
123
|
tex = Tex(
|
|
126
|
-
"FadeIn with ", "shift ", " or target
|
|
124
|
+
"FadeIn with ", "shift ", r" or target\_position", " and scale"
|
|
127
125
|
).scale(1)
|
|
128
126
|
animations = [
|
|
129
127
|
FadeIn(tex[0]),
|
|
@@ -135,18 +133,18 @@ class FadeIn(_Fade):
|
|
|
135
133
|
|
|
136
134
|
"""
|
|
137
135
|
|
|
138
|
-
def __init__(self, *mobjects: Mobject, **kwargs) -> None:
|
|
136
|
+
def __init__(self, *mobjects: Mobject, **kwargs: Any) -> None:
|
|
139
137
|
super().__init__(*mobjects, introducer=True, **kwargs)
|
|
140
138
|
|
|
141
|
-
def create_target(self):
|
|
142
|
-
return self.mobject
|
|
139
|
+
def create_target(self) -> Mobject:
|
|
140
|
+
return self.mobject # type: ignore[return-value]
|
|
143
141
|
|
|
144
|
-
def create_starting_mobject(self):
|
|
142
|
+
def create_starting_mobject(self) -> Mobject:
|
|
145
143
|
return self._create_faded_mobject(fadeIn=True)
|
|
146
144
|
|
|
147
145
|
|
|
148
146
|
class FadeOut(_Fade):
|
|
149
|
-
"""Fade out :class:`~.Mobject` s.
|
|
147
|
+
r"""Fade out :class:`~.Mobject` s.
|
|
150
148
|
|
|
151
149
|
Parameters
|
|
152
150
|
----------
|
|
@@ -170,7 +168,7 @@ class FadeOut(_Fade):
|
|
|
170
168
|
dot = Dot(UP * 2 + LEFT)
|
|
171
169
|
self.add(dot)
|
|
172
170
|
tex = Tex(
|
|
173
|
-
"FadeOut with ", "shift ", " or target
|
|
171
|
+
"FadeOut with ", "shift ", r" or target\_position", " and scale"
|
|
174
172
|
).scale(1)
|
|
175
173
|
animations = [
|
|
176
174
|
FadeOut(tex[0]),
|
|
@@ -183,12 +181,12 @@ class FadeOut(_Fade):
|
|
|
183
181
|
|
|
184
182
|
"""
|
|
185
183
|
|
|
186
|
-
def __init__(self, *mobjects: Mobject, **kwargs) -> None:
|
|
184
|
+
def __init__(self, *mobjects: Mobject, **kwargs: Any) -> None:
|
|
187
185
|
super().__init__(*mobjects, remover=True, **kwargs)
|
|
188
186
|
|
|
189
|
-
def create_target(self):
|
|
187
|
+
def create_target(self) -> Mobject:
|
|
190
188
|
return self._create_faded_mobject(fadeIn=False)
|
|
191
189
|
|
|
192
|
-
def clean_up_from_scene(self, scene: Scene
|
|
190
|
+
def clean_up_from_scene(self, scene: Scene) -> None:
|
|
193
191
|
super().clean_up_from_scene(scene)
|
|
194
192
|
self.interpolate(0)
|
manim/animation/growing.py
CHANGED
|
@@ -31,16 +31,17 @@ __all__ = [
|
|
|
31
31
|
"SpinInFromNothing",
|
|
32
32
|
]
|
|
33
33
|
|
|
34
|
-
import
|
|
35
|
-
|
|
36
|
-
import numpy as np
|
|
34
|
+
from typing import TYPE_CHECKING, Any
|
|
37
35
|
|
|
38
36
|
from ..animation.transform import Transform
|
|
39
37
|
from ..constants import PI
|
|
40
38
|
from ..utils.paths import spiral_path
|
|
41
39
|
|
|
42
|
-
if
|
|
40
|
+
if TYPE_CHECKING:
|
|
43
41
|
from manim.mobject.geometry.line import Arrow
|
|
42
|
+
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
|
|
43
|
+
from manim.typing import Point3DLike, Vector3DLike
|
|
44
|
+
from manim.utils.color import ParsableManimColor
|
|
44
45
|
|
|
45
46
|
from ..mobject.mobject import Mobject
|
|
46
47
|
|
|
@@ -76,16 +77,20 @@ class GrowFromPoint(Transform):
|
|
|
76
77
|
"""
|
|
77
78
|
|
|
78
79
|
def __init__(
|
|
79
|
-
self,
|
|
80
|
-
|
|
80
|
+
self,
|
|
81
|
+
mobject: Mobject,
|
|
82
|
+
point: Point3DLike,
|
|
83
|
+
point_color: ParsableManimColor | None = None,
|
|
84
|
+
**kwargs: Any,
|
|
85
|
+
):
|
|
81
86
|
self.point = point
|
|
82
87
|
self.point_color = point_color
|
|
83
88
|
super().__init__(mobject, introducer=True, **kwargs)
|
|
84
89
|
|
|
85
|
-
def create_target(self) -> Mobject:
|
|
90
|
+
def create_target(self) -> Mobject | OpenGLMobject:
|
|
86
91
|
return self.mobject
|
|
87
92
|
|
|
88
|
-
def create_starting_mobject(self) -> Mobject:
|
|
93
|
+
def create_starting_mobject(self) -> Mobject | OpenGLMobject:
|
|
89
94
|
start = super().create_starting_mobject()
|
|
90
95
|
start.scale(0)
|
|
91
96
|
start.move_to(self.point)
|
|
@@ -118,7 +123,12 @@ class GrowFromCenter(GrowFromPoint):
|
|
|
118
123
|
|
|
119
124
|
"""
|
|
120
125
|
|
|
121
|
-
def __init__(
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
mobject: Mobject,
|
|
129
|
+
point_color: ParsableManimColor | None = None,
|
|
130
|
+
**kwargs: Any,
|
|
131
|
+
):
|
|
122
132
|
point = mobject.get_center()
|
|
123
133
|
super().__init__(mobject, point, point_color=point_color, **kwargs)
|
|
124
134
|
|
|
@@ -153,8 +163,12 @@ class GrowFromEdge(GrowFromPoint):
|
|
|
153
163
|
"""
|
|
154
164
|
|
|
155
165
|
def __init__(
|
|
156
|
-
self,
|
|
157
|
-
|
|
166
|
+
self,
|
|
167
|
+
mobject: Mobject,
|
|
168
|
+
edge: Vector3DLike,
|
|
169
|
+
point_color: ParsableManimColor | None = None,
|
|
170
|
+
**kwargs: Any,
|
|
171
|
+
):
|
|
158
172
|
point = mobject.get_critical_point(edge)
|
|
159
173
|
super().__init__(mobject, point, point_color=point_color, **kwargs)
|
|
160
174
|
|
|
@@ -183,11 +197,13 @@ class GrowArrow(GrowFromPoint):
|
|
|
183
197
|
|
|
184
198
|
"""
|
|
185
199
|
|
|
186
|
-
def __init__(
|
|
200
|
+
def __init__(
|
|
201
|
+
self, arrow: Arrow, point_color: ParsableManimColor | None = None, **kwargs: Any
|
|
202
|
+
):
|
|
187
203
|
point = arrow.get_start()
|
|
188
204
|
super().__init__(arrow, point, point_color=point_color, **kwargs)
|
|
189
205
|
|
|
190
|
-
def create_starting_mobject(self) -> Mobject:
|
|
206
|
+
def create_starting_mobject(self) -> Mobject | OpenGLMobject:
|
|
191
207
|
start_arrow = self.mobject.copy()
|
|
192
208
|
start_arrow.scale(0, scale_tips=True, about_point=self.point)
|
|
193
209
|
if self.point_color:
|
|
@@ -224,8 +240,12 @@ class SpinInFromNothing(GrowFromCenter):
|
|
|
224
240
|
"""
|
|
225
241
|
|
|
226
242
|
def __init__(
|
|
227
|
-
self,
|
|
228
|
-
|
|
243
|
+
self,
|
|
244
|
+
mobject: Mobject,
|
|
245
|
+
angle: float = PI / 2,
|
|
246
|
+
point_color: ParsableManimColor | None = None,
|
|
247
|
+
**kwargs: Any,
|
|
248
|
+
):
|
|
229
249
|
self.angle = angle
|
|
230
250
|
super().__init__(
|
|
231
251
|
mobject, path_func=spiral_path(angle), point_color=point_color, **kwargs
|