manim 0.17.3__py3-none-any.whl → 0.18.0.post0__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 +1 -0
- manim/__main__.py +2 -0
- manim/_config/__init__.py +0 -1
- manim/_config/logger_utils.py +1 -0
- manim/_config/utils.py +14 -5
- manim/animation/changing.py +9 -5
- manim/animation/creation.py +8 -3
- manim/animation/indication.py +4 -4
- manim/animation/speedmodifier.py +2 -4
- manim/animation/updaters/mobject_update_utils.py +134 -16
- manim/camera/camera.py +31 -17
- manim/cli/checkhealth/__init__.py +0 -0
- manim/cli/checkhealth/checks.py +173 -0
- manim/cli/checkhealth/commands.py +81 -0
- manim/cli/render/global_options.py +6 -0
- manim/constants.py +58 -54
- manim/mobject/geometry/__init__.py +1 -0
- manim/mobject/geometry/arc.py +126 -91
- manim/mobject/geometry/boolean_ops.py +6 -10
- manim/mobject/geometry/labeled.py +155 -0
- manim/mobject/geometry/line.py +66 -50
- manim/mobject/geometry/polygram.py +23 -15
- manim/mobject/geometry/shape_matchers.py +24 -15
- manim/mobject/geometry/tips.py +62 -40
- manim/mobject/graph.py +3 -4
- manim/mobject/graphing/coordinate_systems.py +190 -139
- manim/mobject/graphing/number_line.py +5 -2
- manim/mobject/graphing/probability.py +4 -3
- manim/mobject/graphing/scale.py +7 -7
- manim/mobject/logo.py +108 -22
- manim/mobject/matrix.py +33 -37
- manim/mobject/mobject.py +327 -260
- manim/mobject/opengl/opengl_image_mobject.py +1 -1
- manim/mobject/opengl/opengl_mobject.py +18 -12
- manim/mobject/opengl/opengl_point_cloud_mobject.py +1 -1
- manim/mobject/opengl/opengl_surface.py +1 -1
- manim/mobject/opengl/opengl_vectorized_mobject.py +21 -17
- manim/mobject/svg/brace.py +3 -1
- manim/mobject/svg/svg_mobject.py +9 -11
- manim/mobject/table.py +50 -54
- manim/mobject/text/numbers.py +48 -6
- manim/mobject/text/tex_mobject.py +8 -12
- manim/mobject/text/text_mobject.py +32 -24
- manim/mobject/three_d/three_d_utils.py +13 -8
- manim/mobject/three_d/three_dimensions.py +61 -43
- manim/mobject/types/image_mobject.py +5 -4
- manim/mobject/types/point_cloud_mobject.py +8 -6
- manim/mobject/types/vectorized_mobject.py +385 -258
- manim/mobject/vector_field.py +19 -11
- manim/plugins/import_plugins.py +1 -1
- manim/plugins/plugins_flags.py +1 -6
- manim/renderer/shader.py +2 -2
- manim/scene/scene.py +15 -7
- manim/scene/scene_file_writer.py +1 -2
- manim/scene/three_d_scene.py +1 -1
- manim/scene/vector_space_scene.py +17 -7
- manim/typing.py +133 -0
- manim/utils/bezier.py +267 -83
- manim/utils/color/AS2700.py +234 -0
- manim/utils/color/BS381.py +315 -0
- manim/utils/color/X11.py +530 -0
- manim/utils/color/XKCD.py +949 -0
- manim/utils/color/__init__.py +58 -0
- manim/utils/color/core.py +1036 -0
- manim/utils/color/manim_colors.py +220 -0
- manim/utils/docbuild/autocolor_directive.py +92 -0
- manim/utils/docbuild/manim_directive.py +40 -6
- manim/utils/file_ops.py +1 -1
- manim/utils/hashing.py +1 -1
- manim/utils/iterables.py +1 -1
- manim/utils/rate_functions.py +33 -0
- manim/utils/simple_functions.py +0 -18
- manim/utils/space_ops.py +55 -42
- manim/utils/testing/frames_comparison.py +9 -0
- manim/utils/tex.py +2 -0
- manim/utils/tex_file_writing.py +29 -2
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/METADATA +14 -14
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/RECORD +82 -71
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/WHEEL +1 -1
- manim/communitycolors.py +0 -9
- manim/utils/color.py +0 -552
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE +0 -0
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/LICENSE.community +0 -0
- {manim-0.17.3.dist-info → manim-0.18.0.post0.dist-info}/entry_points.txt +0 -0
manim/__init__.py
CHANGED
|
@@ -46,6 +46,7 @@ from .constants import *
|
|
|
46
46
|
from .mobject.frame import *
|
|
47
47
|
from .mobject.geometry.arc import *
|
|
48
48
|
from .mobject.geometry.boolean_ops import *
|
|
49
|
+
from .mobject.geometry.labeled import *
|
|
49
50
|
from .mobject.geometry.line import *
|
|
50
51
|
from .mobject.geometry.polygram import *
|
|
51
52
|
from .mobject.geometry.shape_matchers import *
|
manim/__main__.py
CHANGED
|
@@ -7,6 +7,7 @@ import cloup
|
|
|
7
7
|
|
|
8
8
|
from . import __version__, cli_ctx_settings, console
|
|
9
9
|
from .cli.cfg.group import cfg
|
|
10
|
+
from .cli.checkhealth.commands import checkhealth
|
|
10
11
|
from .cli.default_group import DefaultGroup
|
|
11
12
|
from .cli.init.commands import init
|
|
12
13
|
from .cli.new.group import new
|
|
@@ -48,6 +49,7 @@ def main(ctx):
|
|
|
48
49
|
pass
|
|
49
50
|
|
|
50
51
|
|
|
52
|
+
main.add_command(checkhealth)
|
|
51
53
|
main.add_command(cfg)
|
|
52
54
|
main.add_command(plugins)
|
|
53
55
|
main.add_command(init)
|
manim/_config/__init__.py
CHANGED
manim/_config/logger_utils.py
CHANGED
manim/_config/utils.py
CHANGED
|
@@ -23,13 +23,13 @@ from collections.abc import Mapping, MutableMapping
|
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any, Iterable, Iterator
|
|
25
25
|
|
|
26
|
-
import colour
|
|
27
26
|
import numpy as np
|
|
28
27
|
|
|
29
28
|
from .. import constants
|
|
30
29
|
from ..constants import RendererType
|
|
30
|
+
from ..typing import StrPath
|
|
31
|
+
from ..utils.color import ManimColor
|
|
31
32
|
from ..utils.tex import TexTemplate, TexTemplateFromFile
|
|
32
|
-
from ..utils.tex_templates import TexTemplateLibrary
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def config_file_paths() -> list[Path]:
|
|
@@ -76,7 +76,7 @@ def config_file_paths() -> list[Path]:
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def make_config_parser(
|
|
79
|
-
custom_file:
|
|
79
|
+
custom_file: StrPath | None = None,
|
|
80
80
|
) -> configparser.ConfigParser:
|
|
81
81
|
"""Make a :class:`ConfigParser` object and load any ``.cfg`` files.
|
|
82
82
|
|
|
@@ -309,6 +309,7 @@ class ManimConfig(MutableMapping):
|
|
|
309
309
|
"write_to_movie",
|
|
310
310
|
"zero_pad",
|
|
311
311
|
"force_window",
|
|
312
|
+
"no_latex_cleanup",
|
|
312
313
|
}
|
|
313
314
|
|
|
314
315
|
def __init__(self) -> None:
|
|
@@ -580,6 +581,7 @@ class ManimConfig(MutableMapping):
|
|
|
580
581
|
"use_projection_stroke_shaders",
|
|
581
582
|
"enable_wireframe",
|
|
582
583
|
"force_window",
|
|
584
|
+
"no_latex_cleanup",
|
|
583
585
|
]:
|
|
584
586
|
setattr(self, key, parser["CLI"].getboolean(key, fallback=False))
|
|
585
587
|
|
|
@@ -756,6 +758,7 @@ class ManimConfig(MutableMapping):
|
|
|
756
758
|
"enable_wireframe",
|
|
757
759
|
"force_window",
|
|
758
760
|
"dry_run",
|
|
761
|
+
"no_latex_cleanup",
|
|
759
762
|
]:
|
|
760
763
|
if hasattr(args, key):
|
|
761
764
|
attr = getattr(args, key)
|
|
@@ -960,6 +963,12 @@ class ManimConfig(MutableMapping):
|
|
|
960
963
|
doc="Set to force window when using the opengl renderer",
|
|
961
964
|
)
|
|
962
965
|
|
|
966
|
+
no_latex_cleanup = property(
|
|
967
|
+
lambda self: self._d["no_latex_cleanup"],
|
|
968
|
+
lambda self, val: self._set_boolean("no_latex_cleanup", val),
|
|
969
|
+
doc="Prevents deletion of .aux, .dvi, and .log files produced by Tex and MathTex.",
|
|
970
|
+
)
|
|
971
|
+
|
|
963
972
|
@property
|
|
964
973
|
def verbosity(self):
|
|
965
974
|
"""Logger verbosity; "DEBUG", "INFO", "WARNING", "ERROR", or "CRITICAL" (-v)."""
|
|
@@ -1096,7 +1105,7 @@ class ManimConfig(MutableMapping):
|
|
|
1096
1105
|
|
|
1097
1106
|
background_color = property(
|
|
1098
1107
|
lambda self: self._d["background_color"],
|
|
1099
|
-
lambda self, val: self._d.__setitem__("background_color",
|
|
1108
|
+
lambda self, val: self._d.__setitem__("background_color", ManimColor(val)),
|
|
1100
1109
|
doc="Background color of the scene (-c).",
|
|
1101
1110
|
)
|
|
1102
1111
|
|
|
@@ -1172,7 +1181,7 @@ class ManimConfig(MutableMapping):
|
|
|
1172
1181
|
keys = ["pixel_width", "pixel_height", "frame_rate"]
|
|
1173
1182
|
q = {k: self[k] for k in keys}
|
|
1174
1183
|
for qual in constants.QUALITIES:
|
|
1175
|
-
if all(
|
|
1184
|
+
if all(q[k] == constants.QUALITIES[qual][k] for k in keys):
|
|
1176
1185
|
return qual
|
|
1177
1186
|
return None
|
|
1178
1187
|
|
manim/animation/changing.py
CHANGED
|
@@ -6,12 +6,16 @@ __all__ = ["AnimatedBoundary", "TracedPath"]
|
|
|
6
6
|
|
|
7
7
|
from typing import Callable
|
|
8
8
|
|
|
9
|
-
from colour import Color
|
|
10
|
-
|
|
11
|
-
from manim._config import config
|
|
12
9
|
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
|
|
13
10
|
from manim.mobject.types.vectorized_mobject import VGroup, VMobject
|
|
14
|
-
from manim.utils.color import
|
|
11
|
+
from manim.utils.color import (
|
|
12
|
+
BLUE_B,
|
|
13
|
+
BLUE_D,
|
|
14
|
+
BLUE_E,
|
|
15
|
+
GREY_BROWN,
|
|
16
|
+
WHITE,
|
|
17
|
+
ParsableManimColor,
|
|
18
|
+
)
|
|
15
19
|
from manim.utils.rate_functions import smooth
|
|
16
20
|
|
|
17
21
|
|
|
@@ -140,7 +144,7 @@ class TracedPath(VMobject, metaclass=ConvertToOpenGL):
|
|
|
140
144
|
self,
|
|
141
145
|
traced_point_func: Callable,
|
|
142
146
|
stroke_width: float = 2,
|
|
143
|
-
stroke_color:
|
|
147
|
+
stroke_color: ParsableManimColor | None = WHITE,
|
|
144
148
|
dissipating_time: float | None = None,
|
|
145
149
|
**kwargs,
|
|
146
150
|
):
|
manim/animation/creation.py
CHANGED
|
@@ -77,13 +77,13 @@ import itertools as it
|
|
|
77
77
|
from typing import TYPE_CHECKING, Callable, Iterable, Sequence
|
|
78
78
|
|
|
79
79
|
import numpy as np
|
|
80
|
-
from colour import Color
|
|
81
80
|
|
|
82
81
|
if TYPE_CHECKING:
|
|
83
82
|
from manim.mobject.text.text_mobject import Text
|
|
84
83
|
|
|
85
84
|
from manim.mobject.opengl.opengl_surface import OpenGLSurface
|
|
86
85
|
from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject
|
|
86
|
+
from manim.utils.color import ManimColor
|
|
87
87
|
|
|
88
88
|
from .. import config
|
|
89
89
|
from ..animation.animation import Animation
|
|
@@ -92,7 +92,7 @@ from ..constants import TAU
|
|
|
92
92
|
from ..mobject.mobject import Group, Mobject
|
|
93
93
|
from ..mobject.types.vectorized_mobject import VMobject
|
|
94
94
|
from ..utils.bezier import integer_interpolate
|
|
95
|
-
from ..utils.rate_functions import double_smooth, linear
|
|
95
|
+
from ..utils.rate_functions import double_smooth, linear
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
class ShowPartial(Animation):
|
|
@@ -259,7 +259,7 @@ class DrawBorderThenFill(Animation):
|
|
|
259
259
|
sm.set_stroke(color=self.get_stroke_color(sm), width=self.stroke_width)
|
|
260
260
|
return outline
|
|
261
261
|
|
|
262
|
-
def get_stroke_color(self, vmobject: VMobject | OpenGLVMobject) ->
|
|
262
|
+
def get_stroke_color(self, vmobject: VMobject | OpenGLVMobject) -> ManimColor:
|
|
263
263
|
if self.stroke_color:
|
|
264
264
|
return self.stroke_color
|
|
265
265
|
elif vmobject.get_stroke_width() > 0:
|
|
@@ -563,6 +563,11 @@ class AddTextLetterByLetter(ShowIncreasingSubsets):
|
|
|
563
563
|
**kwargs,
|
|
564
564
|
) -> None:
|
|
565
565
|
self.time_per_char = time_per_char
|
|
566
|
+
# Check for empty text using family_members_with_points()
|
|
567
|
+
if not text.family_members_with_points():
|
|
568
|
+
raise ValueError(
|
|
569
|
+
f"The text mobject {text} does not seem to contain any characters."
|
|
570
|
+
)
|
|
566
571
|
if run_time is None:
|
|
567
572
|
# minimum time per character is 1/frame_rate, otherwise
|
|
568
573
|
# the animation does not finish.
|
manim/animation/indication.py
CHANGED
|
@@ -40,12 +40,12 @@ __all__ = [
|
|
|
40
40
|
from typing import Callable, Iterable, Optional, Tuple, Type, Union
|
|
41
41
|
|
|
42
42
|
import numpy as np
|
|
43
|
-
from colour import Color
|
|
44
43
|
|
|
45
44
|
from manim.mobject.geometry.arc import Circle, Dot
|
|
46
45
|
from manim.mobject.geometry.line import Line
|
|
47
46
|
from manim.mobject.geometry.polygram import Rectangle
|
|
48
47
|
from manim.mobject.geometry.shape_matchers import SurroundingRectangle
|
|
48
|
+
from manim.scene.scene import Scene
|
|
49
49
|
|
|
50
50
|
from .. import config
|
|
51
51
|
from ..animation.animation import Animation
|
|
@@ -58,7 +58,7 @@ from ..constants import *
|
|
|
58
58
|
from ..mobject.mobject import Mobject
|
|
59
59
|
from ..mobject.types.vectorized_mobject import VGroup, VMobject
|
|
60
60
|
from ..utils.bezier import interpolate, inverse_interpolate
|
|
61
|
-
from ..utils.color import GREY, YELLOW
|
|
61
|
+
from ..utils.color import GREY, YELLOW, ParsableManimColor
|
|
62
62
|
from ..utils.deprecation import deprecated
|
|
63
63
|
from ..utils.rate_functions import smooth, there_and_back, wiggle
|
|
64
64
|
from ..utils.space_ops import normalize
|
|
@@ -314,7 +314,7 @@ class ShowPassingFlash(ShowPartial):
|
|
|
314
314
|
lower = max(lower, 0)
|
|
315
315
|
return (lower, upper)
|
|
316
316
|
|
|
317
|
-
def clean_up_from_scene(self, scene:
|
|
317
|
+
def clean_up_from_scene(self, scene: Scene) -> None:
|
|
318
318
|
super().clean_up_from_scene(scene)
|
|
319
319
|
for submob, start in self.get_all_families_zipped():
|
|
320
320
|
submob.pointwise_become_partial(start, 0, 1)
|
|
@@ -609,7 +609,7 @@ class Circumscribe(Succession):
|
|
|
609
609
|
fade_out=False,
|
|
610
610
|
time_width=0.3,
|
|
611
611
|
buff: float = SMALL_BUFF,
|
|
612
|
-
color:
|
|
612
|
+
color: ParsableManimColor = YELLOW,
|
|
613
613
|
run_time=1,
|
|
614
614
|
stroke_width=DEFAULT_STROKE_WIDTH,
|
|
615
615
|
**kwargs
|
manim/animation/speedmodifier.py
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import inspect
|
|
5
6
|
import types
|
|
6
7
|
from typing import Callable
|
|
7
8
|
|
|
8
9
|
from numpy import piecewise
|
|
9
10
|
|
|
10
|
-
from manim.utils.simple_functions import get_parameters
|
|
11
|
-
|
|
12
11
|
from ..animation.animation import Animation, Wait, prepare_animation
|
|
13
12
|
from ..animation.composition import AnimationGroup
|
|
14
13
|
from ..mobject.mobject import Mobject, Updater, _AnimationBuilder
|
|
@@ -260,8 +259,7 @@ class ChangeSpeed(Animation):
|
|
|
260
259
|
:class:`.ChangeSpeed`
|
|
261
260
|
:meth:`.Mobject.add_updater`
|
|
262
261
|
"""
|
|
263
|
-
|
|
264
|
-
if "dt" in parameters:
|
|
262
|
+
if "dt" in inspect.signature(update_function).parameters:
|
|
265
263
|
mobject.add_updater(
|
|
266
264
|
lambda mob, dt: update_function(
|
|
267
265
|
mob, ChangeSpeed.dt if ChangeSpeed.is_changing_dt else dt
|
|
@@ -15,21 +15,26 @@ __all__ = [
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
import inspect
|
|
18
|
+
from typing import TYPE_CHECKING, Callable
|
|
18
19
|
|
|
19
20
|
import numpy as np
|
|
20
21
|
|
|
21
22
|
from manim.constants import DEGREES, RIGHT
|
|
22
23
|
from manim.mobject.mobject import Mobject
|
|
23
24
|
from manim.opengl import OpenGLMobject
|
|
25
|
+
from manim.utils.space_ops import normalize
|
|
24
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from manim.animation.animation import Animation
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
|
|
31
|
+
def assert_is_mobject_method(method: Callable) -> None:
|
|
27
32
|
assert inspect.ismethod(method)
|
|
28
33
|
mobject = method.__self__
|
|
29
34
|
assert isinstance(mobject, (Mobject, OpenGLMobject))
|
|
30
35
|
|
|
31
36
|
|
|
32
|
-
def always(method, *args, **kwargs):
|
|
37
|
+
def always(method: Callable, *args, **kwargs) -> Mobject:
|
|
33
38
|
assert_is_mobject_method(method)
|
|
34
39
|
mobject = method.__self__
|
|
35
40
|
func = method.__func__
|
|
@@ -37,7 +42,7 @@ def always(method, *args, **kwargs):
|
|
|
37
42
|
return mobject
|
|
38
43
|
|
|
39
44
|
|
|
40
|
-
def f_always(method, *arg_generators, **kwargs):
|
|
45
|
+
def f_always(method: Callable[[Mobject], None], *arg_generators, **kwargs) -> Mobject:
|
|
41
46
|
"""
|
|
42
47
|
More functional version of always, where instead
|
|
43
48
|
of taking in args, it takes in functions which output
|
|
@@ -55,42 +60,155 @@ def f_always(method, *arg_generators, **kwargs):
|
|
|
55
60
|
return mobject
|
|
56
61
|
|
|
57
62
|
|
|
58
|
-
def always_redraw(func):
|
|
63
|
+
def always_redraw(func: Callable[[], Mobject]) -> Mobject:
|
|
64
|
+
"""Redraw the mobject constructed by a function every frame.
|
|
65
|
+
|
|
66
|
+
This function returns a mobject with an attached updater that
|
|
67
|
+
continuously regenerates the mobject according to the
|
|
68
|
+
specified function.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
func
|
|
73
|
+
A function without (required) input arguments that returns
|
|
74
|
+
a mobject.
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
|
|
79
|
+
.. manim:: TangentAnimation
|
|
80
|
+
|
|
81
|
+
class TangentAnimation(Scene):
|
|
82
|
+
def construct(self):
|
|
83
|
+
ax = Axes()
|
|
84
|
+
sine = ax.plot(np.sin, color=RED)
|
|
85
|
+
alpha = ValueTracker(0)
|
|
86
|
+
point = always_redraw(
|
|
87
|
+
lambda: Dot(
|
|
88
|
+
sine.point_from_proportion(alpha.get_value()),
|
|
89
|
+
color=BLUE
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
tangent = always_redraw(
|
|
93
|
+
lambda: TangentLine(
|
|
94
|
+
sine,
|
|
95
|
+
alpha=alpha.get_value(),
|
|
96
|
+
color=YELLOW,
|
|
97
|
+
length=4
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
self.add(ax, sine, point, tangent)
|
|
101
|
+
self.play(alpha.animate.set_value(1), rate_func=linear, run_time=2)
|
|
102
|
+
"""
|
|
59
103
|
mob = func()
|
|
60
|
-
mob.add_updater(lambda
|
|
104
|
+
mob.add_updater(lambda _: mob.become(func()))
|
|
61
105
|
return mob
|
|
62
106
|
|
|
63
107
|
|
|
64
|
-
def always_shift(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
108
|
+
def always_shift(
|
|
109
|
+
mobject: Mobject, direction: np.ndarray[np.float64] = RIGHT, rate: float = 0.1
|
|
110
|
+
) -> Mobject:
|
|
111
|
+
"""A mobject which is continuously shifted along some direction
|
|
112
|
+
at a certain rate.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
mobject
|
|
117
|
+
The mobject to shift.
|
|
118
|
+
direction
|
|
119
|
+
The direction to shift. The vector is normalized, the specified magnitude
|
|
120
|
+
is not relevant.
|
|
121
|
+
rate
|
|
122
|
+
Length in Manim units which the mobject travels in one
|
|
123
|
+
second along the specified direction.
|
|
124
|
+
|
|
125
|
+
Examples
|
|
126
|
+
--------
|
|
127
|
+
|
|
128
|
+
.. manim:: ShiftingSquare
|
|
129
|
+
|
|
130
|
+
class ShiftingSquare(Scene):
|
|
131
|
+
def construct(self):
|
|
132
|
+
sq = Square().set_fill(opacity=1)
|
|
133
|
+
tri = Triangle()
|
|
134
|
+
VGroup(sq, tri).arrange(LEFT)
|
|
135
|
+
|
|
136
|
+
# construct a square which is continuously
|
|
137
|
+
# shifted to the right
|
|
138
|
+
always_shift(sq, RIGHT, rate=5)
|
|
139
|
+
|
|
140
|
+
self.add(sq)
|
|
141
|
+
self.play(tri.animate.set_fill(opacity=1))
|
|
142
|
+
"""
|
|
71
143
|
mobject.add_updater(lambda m, dt: m.shift(dt * rate * normalize(direction)))
|
|
72
144
|
return mobject
|
|
73
145
|
|
|
74
146
|
|
|
75
|
-
def always_rotate(mobject, rate=20 * DEGREES, **kwargs):
|
|
147
|
+
def always_rotate(mobject: Mobject, rate: float = 20 * DEGREES, **kwargs) -> Mobject:
|
|
148
|
+
"""A mobject which is continuously rotated at a certain rate.
|
|
149
|
+
|
|
150
|
+
Parameters
|
|
151
|
+
----------
|
|
152
|
+
mobject
|
|
153
|
+
The mobject to be rotated.
|
|
154
|
+
rate
|
|
155
|
+
The angle which the mobject is rotated by
|
|
156
|
+
over one second.
|
|
157
|
+
kwags
|
|
158
|
+
Further arguments to be passed to :meth:`.Mobject.rotate`.
|
|
159
|
+
|
|
160
|
+
Examples
|
|
161
|
+
--------
|
|
162
|
+
|
|
163
|
+
.. manim:: SpinningTriangle
|
|
164
|
+
|
|
165
|
+
class SpinningTriangle(Scene):
|
|
166
|
+
def construct(self):
|
|
167
|
+
tri = Triangle().set_fill(opacity=1).set_z_index(2)
|
|
168
|
+
sq = Square().to_edge(LEFT)
|
|
169
|
+
|
|
170
|
+
# will keep spinning while there is an animation going on
|
|
171
|
+
always_rotate(tri, rate=2*PI, about_point=ORIGIN)
|
|
172
|
+
|
|
173
|
+
self.add(tri, sq)
|
|
174
|
+
self.play(sq.animate.to_edge(RIGHT), rate_func=linear, run_time=1)
|
|
175
|
+
"""
|
|
76
176
|
mobject.add_updater(lambda m, dt: m.rotate(dt * rate, **kwargs))
|
|
77
177
|
return mobject
|
|
78
178
|
|
|
79
179
|
|
|
80
|
-
def turn_animation_into_updater(
|
|
180
|
+
def turn_animation_into_updater(
|
|
181
|
+
animation: Animation, cycle: bool = False, **kwargs
|
|
182
|
+
) -> Mobject:
|
|
81
183
|
"""
|
|
82
184
|
Add an updater to the animation's mobject which applies
|
|
83
185
|
the interpolation and update functions of the animation
|
|
84
186
|
|
|
85
187
|
If cycle is True, this repeats over and over. Otherwise,
|
|
86
188
|
the updater will be popped upon completion
|
|
189
|
+
|
|
190
|
+
Examples
|
|
191
|
+
--------
|
|
192
|
+
|
|
193
|
+
.. manim:: WelcomeToManim
|
|
194
|
+
|
|
195
|
+
class WelcomeToManim(Scene):
|
|
196
|
+
def construct(self):
|
|
197
|
+
words = Text("Welcome to")
|
|
198
|
+
banner = ManimBanner().scale(0.5)
|
|
199
|
+
VGroup(words, banner).arrange(DOWN)
|
|
200
|
+
|
|
201
|
+
turn_animation_into_updater(Write(words, run_time=0.9))
|
|
202
|
+
self.add(words)
|
|
203
|
+
self.wait(0.5)
|
|
204
|
+
self.play(banner.expand(), run_time=0.5)
|
|
87
205
|
"""
|
|
88
206
|
mobject = animation.mobject
|
|
89
207
|
animation.suspend_mobject_updating = False
|
|
90
208
|
animation.begin()
|
|
91
209
|
animation.total_time = 0
|
|
92
210
|
|
|
93
|
-
def update(m, dt):
|
|
211
|
+
def update(m: Mobject, dt: float):
|
|
94
212
|
run_time = animation.get_run_time()
|
|
95
213
|
time_ratio = animation.total_time / run_time
|
|
96
214
|
if cycle:
|
|
@@ -109,5 +227,5 @@ def turn_animation_into_updater(animation, cycle=False, **kwargs):
|
|
|
109
227
|
return mobject
|
|
110
228
|
|
|
111
229
|
|
|
112
|
-
def cycle_animation(animation, **kwargs):
|
|
230
|
+
def cycle_animation(animation: Animation, **kwargs) -> Mobject:
|
|
113
231
|
return turn_animation_into_updater(animation, cycle=True, **kwargs)
|
manim/camera/camera.py
CHANGED
|
@@ -9,7 +9,6 @@ import copy
|
|
|
9
9
|
import itertools as it
|
|
10
10
|
import operator as op
|
|
11
11
|
import pathlib
|
|
12
|
-
import time
|
|
13
12
|
from functools import reduce
|
|
14
13
|
from typing import Any, Callable, Iterable
|
|
15
14
|
|
|
@@ -24,7 +23,7 @@ from ..mobject.mobject import Mobject
|
|
|
24
23
|
from ..mobject.types.image_mobject import AbstractImageMobject
|
|
25
24
|
from ..mobject.types.point_cloud_mobject import PMobject
|
|
26
25
|
from ..mobject.types.vectorized_mobject import VMobject
|
|
27
|
-
from ..utils.color import color_to_int_rgba
|
|
26
|
+
from ..utils.color import ManimColor, ParsableManimColor, color_to_int_rgba
|
|
28
27
|
from ..utils.family import extract_mobject_family_members
|
|
29
28
|
from ..utils.images import get_full_raster_image_path
|
|
30
29
|
from ..utils.iterables import list_difference_update
|
|
@@ -75,6 +74,8 @@ class Camera:
|
|
|
75
74
|
frame_height: float | None = None,
|
|
76
75
|
frame_width: float | None = None,
|
|
77
76
|
frame_rate: float | None = None,
|
|
77
|
+
background_color: ParsableManimColor | None = None,
|
|
78
|
+
background_opacity: float | None = None,
|
|
78
79
|
**kwargs,
|
|
79
80
|
):
|
|
80
81
|
self.background_image = background_image
|
|
@@ -106,9 +107,14 @@ class Camera:
|
|
|
106
107
|
frame_rate = config["frame_rate"]
|
|
107
108
|
self.frame_rate = frame_rate
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
if background_color is None:
|
|
111
|
+
self._background_color = ManimColor.parse(config["background_color"])
|
|
112
|
+
else:
|
|
113
|
+
self._background_color = ManimColor.parse(background_color)
|
|
114
|
+
if background_opacity is None:
|
|
115
|
+
self._background_opacity = config["background_opacity"]
|
|
116
|
+
else:
|
|
117
|
+
self._background_opacity = background_opacity
|
|
112
118
|
|
|
113
119
|
# This one is in the same boat as the above, but it doesn't have the
|
|
114
120
|
# same name as the corresponding key so it has to be handled on its own
|
|
@@ -886,8 +892,10 @@ class Camera:
|
|
|
886
892
|
thickness: float,
|
|
887
893
|
pixel_array: np.ndarray,
|
|
888
894
|
):
|
|
889
|
-
"""Displays a PMobject by modifying the
|
|
895
|
+
"""Displays a PMobject by modifying the pixel array suitably.
|
|
896
|
+
|
|
890
897
|
TODO: Write a description for the rgbas argument.
|
|
898
|
+
|
|
891
899
|
Parameters
|
|
892
900
|
----------
|
|
893
901
|
pmobject
|
|
@@ -957,7 +965,7 @@ class Camera:
|
|
|
957
965
|
The Pixel array to put the imagemobject in.
|
|
958
966
|
"""
|
|
959
967
|
corner_coords = self.points_to_pixel_coords(image_mobject, image_mobject.points)
|
|
960
|
-
ul_coords, ur_coords, dl_coords = corner_coords
|
|
968
|
+
ul_coords, ur_coords, dl_coords, _ = corner_coords
|
|
961
969
|
right_vect = ur_coords - ul_coords
|
|
962
970
|
down_vect = dl_coords - ul_coords
|
|
963
971
|
center_coords = ul_coords + (right_vect + down_vect) / 2
|
|
@@ -1122,17 +1130,19 @@ class Camera:
|
|
|
1122
1130
|
],
|
|
1123
1131
|
)
|
|
1124
1132
|
|
|
1125
|
-
def adjusted_thickness(self, thickness: float):
|
|
1126
|
-
"""
|
|
1133
|
+
def adjusted_thickness(self, thickness: float) -> float:
|
|
1134
|
+
"""Computes the adjusted stroke width for a zoomed camera.
|
|
1127
1135
|
|
|
1128
1136
|
Parameters
|
|
1129
1137
|
----------
|
|
1130
1138
|
thickness
|
|
1139
|
+
The stroke width of a mobject.
|
|
1131
1140
|
|
|
1132
1141
|
Returns
|
|
1133
1142
|
-------
|
|
1134
1143
|
float
|
|
1135
|
-
|
|
1144
|
+
The adjusted stroke width that reflects zooming in with
|
|
1145
|
+
the camera.
|
|
1136
1146
|
"""
|
|
1137
1147
|
# TODO: This seems...unsystematic
|
|
1138
1148
|
big_sum = op.add(config["pixel_height"], config["pixel_width"])
|
|
@@ -1141,7 +1151,8 @@ class Camera:
|
|
|
1141
1151
|
return 1 + (thickness - 1) * factor
|
|
1142
1152
|
|
|
1143
1153
|
def get_thickening_nudges(self, thickness: float):
|
|
1144
|
-
"""
|
|
1154
|
+
"""Determine a list of vectors used to nudge
|
|
1155
|
+
two-dimensional pixel coordinates.
|
|
1145
1156
|
|
|
1146
1157
|
Parameters
|
|
1147
1158
|
----------
|
|
@@ -1215,13 +1226,16 @@ class Camera:
|
|
|
1215
1226
|
# NOTE: The methods of the following class have not been mentioned outside of their definitions.
|
|
1216
1227
|
# Their DocStrings are not as detailed as preferred.
|
|
1217
1228
|
class BackgroundColoredVMobjectDisplayer:
|
|
1229
|
+
"""Auxiliary class that handles displaying vectorized mobjects with
|
|
1230
|
+
a set background image.
|
|
1231
|
+
|
|
1232
|
+
Parameters
|
|
1233
|
+
----------
|
|
1234
|
+
camera
|
|
1235
|
+
Camera object to use.
|
|
1236
|
+
"""
|
|
1237
|
+
|
|
1218
1238
|
def __init__(self, camera: Camera):
|
|
1219
|
-
"""
|
|
1220
|
-
Parameters
|
|
1221
|
-
----------
|
|
1222
|
-
camera
|
|
1223
|
-
Camera object to use.
|
|
1224
|
-
"""
|
|
1225
1239
|
self.camera = camera
|
|
1226
1240
|
self.file_name_to_pixel_array_map = {}
|
|
1227
1241
|
self.pixel_array = np.array(camera.pixel_array)
|
|
File without changes
|