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/animation.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Animate mobjects."""
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
from __future__ import annotations
|
|
5
4
|
|
|
6
5
|
from manim.mobject.opengl.opengl_mobject import OpenGLMobject
|
|
@@ -8,15 +7,19 @@ from manim.mobject.opengl.opengl_mobject import OpenGLMobject
|
|
|
8
7
|
from .. import config, logger
|
|
9
8
|
from ..constants import RendererType
|
|
10
9
|
from ..mobject import mobject
|
|
11
|
-
from ..mobject.mobject import Mobject
|
|
10
|
+
from ..mobject.mobject import Group, Mobject
|
|
12
11
|
from ..mobject.opengl import opengl_mobject
|
|
13
12
|
from ..utils.rate_functions import linear, smooth
|
|
14
13
|
|
|
15
|
-
__all__ = ["Animation", "Wait", "override_animation"]
|
|
14
|
+
__all__ = ["Animation", "Wait", "Add", "override_animation"]
|
|
16
15
|
|
|
17
16
|
|
|
17
|
+
from collections.abc import Callable, Iterable, Sequence
|
|
18
18
|
from copy import deepcopy
|
|
19
|
-
from
|
|
19
|
+
from functools import partialmethod
|
|
20
|
+
from typing import TYPE_CHECKING, Any
|
|
21
|
+
|
|
22
|
+
from typing_extensions import Self
|
|
20
23
|
|
|
21
24
|
if TYPE_CHECKING:
|
|
22
25
|
from manim.scene.scene import Scene
|
|
@@ -51,7 +54,6 @@ class Animation:
|
|
|
51
54
|
For example ``rate_func(0.5)`` is the proportion of the animation that is done
|
|
52
55
|
after half of the animations run time.
|
|
53
56
|
|
|
54
|
-
|
|
55
57
|
reverse_rate_function
|
|
56
58
|
Reverses the rate function of the animation. Setting ``reverse_rate_function``
|
|
57
59
|
does not have any effect on ``remover`` or ``introducer``. These need to be
|
|
@@ -112,13 +114,13 @@ class Animation:
|
|
|
112
114
|
*args,
|
|
113
115
|
use_override=True,
|
|
114
116
|
**kwargs,
|
|
115
|
-
):
|
|
117
|
+
) -> Self:
|
|
116
118
|
if isinstance(mobject, Mobject) and use_override:
|
|
117
119
|
func = mobject.animation_override_for(cls)
|
|
118
120
|
if func is not None:
|
|
119
121
|
anim = func(mobject, *args, **kwargs)
|
|
120
122
|
logger.debug(
|
|
121
|
-
f"The {cls.__name__} animation has been
|
|
123
|
+
f"The {cls.__name__} animation has been overridden for "
|
|
122
124
|
f"{type(mobject).__name__} mobjects. use_override = False can "
|
|
123
125
|
f" be used as keyword argument to prevent animation overriding.",
|
|
124
126
|
)
|
|
@@ -127,7 +129,7 @@ class Animation:
|
|
|
127
129
|
|
|
128
130
|
def __init__(
|
|
129
131
|
self,
|
|
130
|
-
mobject: Mobject | None,
|
|
132
|
+
mobject: Mobject | OpenGLMobject | None,
|
|
131
133
|
lag_ratio: float = DEFAULT_ANIMATION_LAG_RATIO,
|
|
132
134
|
run_time: float = DEFAULT_ANIMATION_RUN_TIME,
|
|
133
135
|
rate_func: Callable[[float], float] = smooth,
|
|
@@ -138,7 +140,7 @@ class Animation:
|
|
|
138
140
|
introducer: bool = False,
|
|
139
141
|
*,
|
|
140
142
|
_on_finish: Callable[[], None] = lambda _: None,
|
|
141
|
-
|
|
143
|
+
use_override: bool = True, # included here to avoid TypeError if passed from a subclass' constructor
|
|
142
144
|
) -> None:
|
|
143
145
|
self._typecheck_input(mobject)
|
|
144
146
|
self.run_time: float = run_time
|
|
@@ -158,8 +160,6 @@ class Animation:
|
|
|
158
160
|
else:
|
|
159
161
|
self.starting_mobject: Mobject = Mobject()
|
|
160
162
|
self.mobject: Mobject = mobject if mobject is not None else Mobject()
|
|
161
|
-
if kwargs:
|
|
162
|
-
logger.debug("Animation received extra kwargs: %s", kwargs)
|
|
163
163
|
|
|
164
164
|
if hasattr(self, "CONFIG"):
|
|
165
165
|
logger.error(
|
|
@@ -169,6 +169,19 @@ class Animation:
|
|
|
169
169
|
),
|
|
170
170
|
)
|
|
171
171
|
|
|
172
|
+
@property
|
|
173
|
+
def run_time(self) -> float:
|
|
174
|
+
return self._run_time
|
|
175
|
+
|
|
176
|
+
@run_time.setter
|
|
177
|
+
def run_time(self, value: float) -> None:
|
|
178
|
+
if value < 0:
|
|
179
|
+
raise ValueError(
|
|
180
|
+
f"The run_time of {self.__class__.__name__} cannot be "
|
|
181
|
+
f"negative. The given value was {value}."
|
|
182
|
+
)
|
|
183
|
+
self._run_time = value
|
|
184
|
+
|
|
172
185
|
def _typecheck_input(self, mobject: Mobject | None) -> None:
|
|
173
186
|
if mobject is None:
|
|
174
187
|
logger.debug("Animation with empty mobject")
|
|
@@ -249,11 +262,11 @@ class Animation:
|
|
|
249
262
|
):
|
|
250
263
|
scene.add(self.mobject)
|
|
251
264
|
|
|
252
|
-
def create_starting_mobject(self) -> Mobject:
|
|
265
|
+
def create_starting_mobject(self) -> Mobject | OpenGLMobject:
|
|
253
266
|
# Keep track of where the mobject starts
|
|
254
267
|
return self.mobject.copy()
|
|
255
268
|
|
|
256
|
-
def get_all_mobjects(self) -> Sequence[Mobject]:
|
|
269
|
+
def get_all_mobjects(self) -> Sequence[Mobject | OpenGLMobject]:
|
|
257
270
|
"""Get all mobjects involved in the animation.
|
|
258
271
|
|
|
259
272
|
Ordering must match the ordering of arguments to interpolate_submobject
|
|
@@ -398,6 +411,7 @@ class Animation:
|
|
|
398
411
|
self.run_time = run_time
|
|
399
412
|
return self
|
|
400
413
|
|
|
414
|
+
# TODO: is this getter even necessary?
|
|
401
415
|
def get_run_time(self) -> float:
|
|
402
416
|
"""Get the run time of the animation.
|
|
403
417
|
|
|
@@ -457,7 +471,7 @@ class Animation:
|
|
|
457
471
|
return self
|
|
458
472
|
|
|
459
473
|
def is_remover(self) -> bool:
|
|
460
|
-
"""Test if
|
|
474
|
+
"""Test if the animation is a remover.
|
|
461
475
|
|
|
462
476
|
Returns
|
|
463
477
|
-------
|
|
@@ -467,7 +481,7 @@ class Animation:
|
|
|
467
481
|
return self.remover
|
|
468
482
|
|
|
469
483
|
def is_introducer(self) -> bool:
|
|
470
|
-
"""Test if
|
|
484
|
+
"""Test if the animation is an introducer.
|
|
471
485
|
|
|
472
486
|
Returns
|
|
473
487
|
-------
|
|
@@ -476,9 +490,57 @@ class Animation:
|
|
|
476
490
|
"""
|
|
477
491
|
return self.introducer
|
|
478
492
|
|
|
493
|
+
@classmethod
|
|
494
|
+
def __init_subclass__(cls, **kwargs) -> None:
|
|
495
|
+
super().__init_subclass__(**kwargs)
|
|
496
|
+
|
|
497
|
+
cls._original__init__ = cls.__init__
|
|
498
|
+
|
|
499
|
+
_original__init__ = __init__ # needed if set_default() is called with no kwargs directly from Animation
|
|
500
|
+
|
|
501
|
+
@classmethod
|
|
502
|
+
def set_default(cls, **kwargs) -> None:
|
|
503
|
+
"""Sets the default values of keyword arguments.
|
|
504
|
+
|
|
505
|
+
If this method is called without any additional keyword
|
|
506
|
+
arguments, the original default values of the initialization
|
|
507
|
+
method of this class are restored.
|
|
508
|
+
|
|
509
|
+
Parameters
|
|
510
|
+
----------
|
|
511
|
+
|
|
512
|
+
kwargs
|
|
513
|
+
Passing any keyword argument will update the default
|
|
514
|
+
values of the keyword arguments of the initialization
|
|
515
|
+
function of this class.
|
|
516
|
+
|
|
517
|
+
Examples
|
|
518
|
+
--------
|
|
519
|
+
|
|
520
|
+
.. manim:: ChangeDefaultAnimation
|
|
521
|
+
|
|
522
|
+
class ChangeDefaultAnimation(Scene):
|
|
523
|
+
def construct(self):
|
|
524
|
+
Rotate.set_default(run_time=2, rate_func=rate_functions.linear)
|
|
525
|
+
Indicate.set_default(color=None)
|
|
526
|
+
|
|
527
|
+
S = Square(color=BLUE, fill_color=BLUE, fill_opacity=0.25)
|
|
528
|
+
self.add(S)
|
|
529
|
+
self.play(Rotate(S, PI))
|
|
530
|
+
self.play(Indicate(S))
|
|
531
|
+
|
|
532
|
+
Rotate.set_default()
|
|
533
|
+
Indicate.set_default()
|
|
534
|
+
|
|
535
|
+
"""
|
|
536
|
+
if kwargs:
|
|
537
|
+
cls.__init__ = partialmethod(cls.__init__, **kwargs)
|
|
538
|
+
else:
|
|
539
|
+
cls.__init__ = cls._original__init__
|
|
540
|
+
|
|
479
541
|
|
|
480
542
|
def prepare_animation(
|
|
481
|
-
anim: Animation | mobject._AnimationBuilder,
|
|
543
|
+
anim: Animation | mobject._AnimationBuilder | opengl_mobject._AnimationBuilder,
|
|
482
544
|
) -> Animation:
|
|
483
545
|
r"""Returns either an unchanged animation, or the animation built
|
|
484
546
|
from a passed animation factory.
|
|
@@ -528,8 +590,8 @@ class Wait(Animation):
|
|
|
528
590
|
stop_condition
|
|
529
591
|
A function without positional arguments that evaluates to a boolean.
|
|
530
592
|
The function is evaluated after every new frame has been rendered.
|
|
531
|
-
Playing the animation
|
|
532
|
-
|
|
593
|
+
Playing the animation stops after the return value is truthy, or
|
|
594
|
+
after the specified ``run_time`` has passed.
|
|
533
595
|
frozen_frame
|
|
534
596
|
Controls whether or not the wait animation is static, i.e., corresponds
|
|
535
597
|
to a frozen frame. If ``False`` is passed, the render loop still
|
|
@@ -575,6 +637,90 @@ class Wait(Animation):
|
|
|
575
637
|
pass
|
|
576
638
|
|
|
577
639
|
|
|
640
|
+
class Add(Animation):
|
|
641
|
+
"""Add Mobjects to a scene, without animating them in any other way. This
|
|
642
|
+
is similar to the :meth:`.Scene.add` method, but :class:`Add` is an
|
|
643
|
+
animation which can be grouped into other animations.
|
|
644
|
+
|
|
645
|
+
Parameters
|
|
646
|
+
----------
|
|
647
|
+
mobjects
|
|
648
|
+
One :class:`~.Mobject` or more to add to a scene.
|
|
649
|
+
run_time
|
|
650
|
+
The duration of the animation after adding the ``mobjects``. Defaults
|
|
651
|
+
to 0, which means this is an instant animation without extra wait time
|
|
652
|
+
after adding them.
|
|
653
|
+
**kwargs
|
|
654
|
+
Additional arguments to pass to the parent :class:`Animation` class.
|
|
655
|
+
|
|
656
|
+
Examples
|
|
657
|
+
--------
|
|
658
|
+
|
|
659
|
+
.. manim:: DefaultAddScene
|
|
660
|
+
|
|
661
|
+
class DefaultAddScene(Scene):
|
|
662
|
+
def construct(self):
|
|
663
|
+
text_1 = Text("I was added with Add!")
|
|
664
|
+
text_2 = Text("Me too!")
|
|
665
|
+
text_3 = Text("And me!")
|
|
666
|
+
texts = VGroup(text_1, text_2, text_3).arrange(DOWN)
|
|
667
|
+
rect = SurroundingRectangle(texts, buff=0.5)
|
|
668
|
+
|
|
669
|
+
self.play(
|
|
670
|
+
Create(rect, run_time=3.0),
|
|
671
|
+
Succession(
|
|
672
|
+
Wait(1.0),
|
|
673
|
+
# You can Add a Mobject in the middle of an animation...
|
|
674
|
+
Add(text_1),
|
|
675
|
+
Wait(1.0),
|
|
676
|
+
# ...or multiple Mobjects at once!
|
|
677
|
+
Add(text_2, text_3),
|
|
678
|
+
),
|
|
679
|
+
)
|
|
680
|
+
self.wait()
|
|
681
|
+
|
|
682
|
+
.. manim:: AddWithRunTimeScene
|
|
683
|
+
|
|
684
|
+
class AddWithRunTimeScene(Scene):
|
|
685
|
+
def construct(self):
|
|
686
|
+
# A 5x5 grid of circles
|
|
687
|
+
circles = VGroup(
|
|
688
|
+
*[Circle(radius=0.5) for _ in range(25)]
|
|
689
|
+
).arrange_in_grid(5, 5)
|
|
690
|
+
|
|
691
|
+
self.play(
|
|
692
|
+
Succession(
|
|
693
|
+
# Add a run_time of 0.2 to wait for 0.2 seconds after
|
|
694
|
+
# adding the circle, instead of using Wait(0.2) after Add!
|
|
695
|
+
*[Add(circle, run_time=0.2) for circle in circles],
|
|
696
|
+
rate_func=smooth,
|
|
697
|
+
)
|
|
698
|
+
)
|
|
699
|
+
self.wait()
|
|
700
|
+
"""
|
|
701
|
+
|
|
702
|
+
def __init__(
|
|
703
|
+
self, *mobjects: Mobject, run_time: float = 0.0, **kwargs: Any
|
|
704
|
+
) -> None:
|
|
705
|
+
mobject = mobjects[0] if len(mobjects) == 1 else Group(*mobjects)
|
|
706
|
+
super().__init__(mobject, run_time=run_time, introducer=True, **kwargs)
|
|
707
|
+
|
|
708
|
+
def begin(self) -> None:
|
|
709
|
+
pass
|
|
710
|
+
|
|
711
|
+
def finish(self) -> None:
|
|
712
|
+
pass
|
|
713
|
+
|
|
714
|
+
def clean_up_from_scene(self, scene: Scene) -> None:
|
|
715
|
+
pass
|
|
716
|
+
|
|
717
|
+
def update_mobjects(self, dt: float) -> None:
|
|
718
|
+
pass
|
|
719
|
+
|
|
720
|
+
def interpolate(self, alpha: float) -> None:
|
|
721
|
+
pass
|
|
722
|
+
|
|
723
|
+
|
|
578
724
|
def override_animation(
|
|
579
725
|
animation_class: type[Animation],
|
|
580
726
|
) -> Callable[[Callable], Callable]:
|
manim/animation/changing.py
CHANGED
|
@@ -4,15 +4,23 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
__all__ = ["AnimatedBoundary", "TracedPath"]
|
|
6
6
|
|
|
7
|
-
from
|
|
7
|
+
from collections.abc import Callable, Sequence
|
|
8
|
+
from typing import Any
|
|
8
9
|
|
|
9
|
-
from
|
|
10
|
+
from typing_extensions import Self
|
|
10
11
|
|
|
11
|
-
from manim.
|
|
12
|
+
from manim.mobject.mobject import Mobject
|
|
12
13
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
13
14
|
from manim.mobject.types.vectorized_mobject import VGroup, VMobject
|
|
14
|
-
from manim.utils.color import
|
|
15
|
-
|
|
15
|
+
from manim.utils.color import (
|
|
16
|
+
BLUE_B,
|
|
17
|
+
BLUE_D,
|
|
18
|
+
BLUE_E,
|
|
19
|
+
GREY_BROWN,
|
|
20
|
+
WHITE,
|
|
21
|
+
ParsableManimColor,
|
|
22
|
+
)
|
|
23
|
+
from manim.utils.rate_functions import RateFunction, smooth
|
|
16
24
|
|
|
17
25
|
|
|
18
26
|
class AnimatedBoundary(VGroup):
|
|
@@ -34,14 +42,14 @@ class AnimatedBoundary(VGroup):
|
|
|
34
42
|
|
|
35
43
|
def __init__(
|
|
36
44
|
self,
|
|
37
|
-
vmobject,
|
|
38
|
-
colors=[BLUE_D, BLUE_B, BLUE_E, GREY_BROWN],
|
|
39
|
-
max_stroke_width=3,
|
|
40
|
-
cycle_rate=0.5,
|
|
41
|
-
back_and_forth=True,
|
|
42
|
-
draw_rate_func=smooth,
|
|
43
|
-
fade_rate_func=smooth,
|
|
44
|
-
**kwargs,
|
|
45
|
+
vmobject: VMobject,
|
|
46
|
+
colors: Sequence[ParsableManimColor] = [BLUE_D, BLUE_B, BLUE_E, GREY_BROWN],
|
|
47
|
+
max_stroke_width: float = 3,
|
|
48
|
+
cycle_rate: float = 0.5,
|
|
49
|
+
back_and_forth: bool = True,
|
|
50
|
+
draw_rate_func: RateFunction = smooth,
|
|
51
|
+
fade_rate_func: RateFunction = smooth,
|
|
52
|
+
**kwargs: Any,
|
|
45
53
|
):
|
|
46
54
|
super().__init__(**kwargs)
|
|
47
55
|
self.colors = colors
|
|
@@ -55,10 +63,10 @@ class AnimatedBoundary(VGroup):
|
|
|
55
63
|
vmobject.copy().set_style(stroke_width=0, fill_opacity=0) for x in range(2)
|
|
56
64
|
]
|
|
57
65
|
self.add(*self.boundary_copies)
|
|
58
|
-
self.total_time = 0
|
|
66
|
+
self.total_time = 0.0
|
|
59
67
|
self.add_updater(lambda m, dt: self.update_boundary_copies(dt))
|
|
60
68
|
|
|
61
|
-
def update_boundary_copies(self, dt):
|
|
69
|
+
def update_boundary_copies(self, dt: float) -> None:
|
|
62
70
|
# Not actual time, but something which passes at
|
|
63
71
|
# an altered rate to make the implementation below
|
|
64
72
|
# cleaner
|
|
@@ -74,9 +82,9 @@ class AnimatedBoundary(VGroup):
|
|
|
74
82
|
fade_alpha = self.fade_rate_func(alpha)
|
|
75
83
|
|
|
76
84
|
if self.back_and_forth and int(time) % 2 == 1:
|
|
77
|
-
bounds = (1 - draw_alpha, 1)
|
|
85
|
+
bounds = (1.0 - draw_alpha, 1.0)
|
|
78
86
|
else:
|
|
79
|
-
bounds = (0, draw_alpha)
|
|
87
|
+
bounds = (0.0, draw_alpha)
|
|
80
88
|
self.full_family_become_partial(growing, vmobject, *bounds)
|
|
81
89
|
growing.set_stroke(colors[index], width=msw)
|
|
82
90
|
|
|
@@ -86,7 +94,9 @@ class AnimatedBoundary(VGroup):
|
|
|
86
94
|
|
|
87
95
|
self.total_time += dt
|
|
88
96
|
|
|
89
|
-
def full_family_become_partial(
|
|
97
|
+
def full_family_become_partial(
|
|
98
|
+
self, mob1: VMobject, mob2: VMobject, a: float, b: float
|
|
99
|
+
) -> Self:
|
|
90
100
|
family1 = mob1.family_members_with_points()
|
|
91
101
|
family2 = mob2.family_members_with_points()
|
|
92
102
|
for sm1, sm2 in zip(family1, family2):
|
|
@@ -140,22 +150,23 @@ class TracedPath(VMobject, metaclass=ConvertToOpenGL):
|
|
|
140
150
|
self,
|
|
141
151
|
traced_point_func: Callable,
|
|
142
152
|
stroke_width: float = 2,
|
|
143
|
-
stroke_color:
|
|
153
|
+
stroke_color: ParsableManimColor | None = WHITE,
|
|
144
154
|
dissipating_time: float | None = None,
|
|
145
|
-
**kwargs,
|
|
146
|
-
):
|
|
155
|
+
**kwargs: Any,
|
|
156
|
+
) -> None:
|
|
147
157
|
super().__init__(stroke_color=stroke_color, stroke_width=stroke_width, **kwargs)
|
|
148
158
|
self.traced_point_func = traced_point_func
|
|
149
159
|
self.dissipating_time = dissipating_time
|
|
150
|
-
self.time = 1 if self.dissipating_time else None
|
|
160
|
+
self.time = 1.0 if self.dissipating_time else None
|
|
151
161
|
self.add_updater(self.update_path)
|
|
152
162
|
|
|
153
|
-
def update_path(self, mob, dt):
|
|
163
|
+
def update_path(self, mob: Mobject, dt: float) -> None:
|
|
154
164
|
new_point = self.traced_point_func()
|
|
155
165
|
if not self.has_points():
|
|
156
166
|
self.start_new_path(new_point)
|
|
157
167
|
self.add_line_to(new_point)
|
|
158
168
|
if self.dissipating_time:
|
|
169
|
+
assert self.time is not None
|
|
159
170
|
self.time += dt
|
|
160
171
|
if self.time - 1 > self.dissipating_time:
|
|
161
172
|
nppcc = self.n_points_per_curve
|