manim 0.18.0.post0__py3-none-any.whl → 0.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of manim might be problematic. Click here for more details.
- manim/__init__.py +3 -6
- manim/__main__.py +61 -20
- manim/_config/__init__.py +6 -3
- manim/_config/cli_colors.py +16 -8
- manim/_config/default.cfg +1 -3
- manim/_config/logger_utils.py +14 -8
- manim/_config/utils.py +651 -472
- manim/animation/animation.py +152 -5
- manim/animation/composition.py +80 -39
- manim/animation/creation.py +196 -14
- manim/animation/fading.py +5 -9
- manim/animation/indication.py +103 -47
- manim/animation/movement.py +22 -5
- manim/animation/rotation.py +3 -2
- manim/animation/specialized.py +4 -6
- manim/animation/speedmodifier.py +10 -5
- manim/animation/transform.py +4 -5
- manim/animation/transform_matching_parts.py +1 -1
- manim/animation/updaters/mobject_update_utils.py +17 -14
- manim/camera/camera.py +15 -6
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +70 -44
- manim/cli/checkhealth/checks.py +93 -75
- manim/cli/checkhealth/commands.py +14 -5
- manim/cli/default_group.py +157 -25
- manim/cli/init/commands.py +32 -24
- manim/cli/plugins/commands.py +16 -3
- manim/cli/render/commands.py +72 -60
- manim/cli/render/ease_of_access_options.py +4 -3
- manim/cli/render/global_options.py +51 -15
- manim/cli/render/output_options.py +6 -5
- manim/cli/render/render_options.py +97 -32
- manim/constants.py +65 -19
- manim/gui/gui.py +2 -0
- manim/mobject/frame.py +0 -1
- manim/mobject/geometry/arc.py +112 -78
- manim/mobject/geometry/boolean_ops.py +32 -25
- manim/mobject/geometry/labeled.py +300 -77
- manim/mobject/geometry/line.py +132 -64
- manim/mobject/geometry/polygram.py +126 -30
- manim/mobject/geometry/shape_matchers.py +35 -15
- manim/mobject/geometry/tips.py +38 -29
- manim/mobject/graph.py +414 -133
- manim/mobject/graphing/coordinate_systems.py +126 -64
- manim/mobject/graphing/functions.py +25 -15
- manim/mobject/graphing/number_line.py +24 -10
- manim/mobject/graphing/probability.py +2 -10
- manim/mobject/graphing/scale.py +6 -5
- manim/mobject/matrix.py +17 -19
- manim/mobject/mobject.py +314 -165
- manim/mobject/opengl/opengl_compatibility.py +2 -0
- manim/mobject/opengl/opengl_geometry.py +30 -9
- manim/mobject/opengl/opengl_image_mobject.py +2 -0
- manim/mobject/opengl/opengl_mobject.py +509 -343
- manim/mobject/opengl/opengl_point_cloud_mobject.py +5 -7
- manim/mobject/opengl/opengl_surface.py +3 -2
- manim/mobject/opengl/opengl_three_dimensions.py +2 -0
- manim/mobject/opengl/opengl_vectorized_mobject.py +46 -79
- manim/mobject/svg/brace.py +63 -13
- manim/mobject/svg/svg_mobject.py +4 -3
- manim/mobject/table.py +11 -13
- manim/mobject/text/code_mobject.py +186 -548
- manim/mobject/text/numbers.py +9 -7
- manim/mobject/text/tex_mobject.py +23 -14
- manim/mobject/text/text_mobject.py +70 -24
- manim/mobject/three_d/polyhedra.py +98 -1
- manim/mobject/three_d/three_d_utils.py +4 -4
- manim/mobject/three_d/three_dimensions.py +62 -34
- manim/mobject/types/image_mobject.py +42 -24
- manim/mobject/types/point_cloud_mobject.py +105 -67
- manim/mobject/types/vectorized_mobject.py +496 -228
- manim/mobject/value_tracker.py +5 -4
- manim/mobject/vector_field.py +5 -5
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +14 -1
- manim/plugins/plugins_flags.py +14 -8
- manim/renderer/cairo_renderer.py +20 -10
- manim/renderer/opengl_renderer.py +21 -23
- manim/renderer/opengl_renderer_window.py +2 -0
- manim/renderer/shader.py +2 -3
- manim/renderer/shader_wrapper.py +5 -2
- manim/renderer/vectorized_mobject_rendering.py +5 -0
- manim/scene/moving_camera_scene.py +23 -0
- manim/scene/scene.py +90 -43
- manim/scene/scene_file_writer.py +316 -165
- manim/scene/section.py +17 -15
- manim/scene/three_d_scene.py +13 -21
- manim/scene/vector_space_scene.py +22 -9
- manim/typing.py +830 -70
- manim/utils/bezier.py +1667 -399
- manim/utils/caching.py +13 -5
- manim/utils/color/AS2700.py +2 -0
- manim/utils/color/BS381.py +3 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +3 -0
- manim/utils/color/XKCD.py +3 -0
- manim/utils/color/__init__.py +8 -5
- manim/utils/color/core.py +844 -309
- manim/utils/color/manim_colors.py +7 -9
- manim/utils/commands.py +48 -20
- manim/utils/config_ops.py +18 -13
- manim/utils/debug.py +8 -7
- manim/utils/deprecation.py +90 -40
- manim/utils/docbuild/__init__.py +17 -0
- manim/utils/docbuild/autoaliasattr_directive.py +234 -0
- manim/utils/docbuild/autocolor_directive.py +21 -17
- manim/utils/docbuild/manim_directive.py +50 -35
- manim/utils/docbuild/module_parsing.py +245 -0
- manim/utils/exceptions.py +6 -0
- manim/utils/family.py +5 -3
- manim/utils/family_ops.py +17 -4
- manim/utils/file_ops.py +26 -16
- manim/utils/hashing.py +9 -7
- manim/utils/images.py +10 -4
- manim/utils/ipython_magic.py +14 -8
- manim/utils/iterables.py +161 -119
- manim/utils/module_ops.py +57 -19
- manim/utils/opengl.py +83 -24
- manim/utils/parameter_parsing.py +32 -0
- manim/utils/paths.py +21 -23
- manim/utils/polylabel.py +168 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +74 -39
- manim/utils/simple_functions.py +24 -15
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +125 -69
- manim/utils/testing/__init__.py +17 -0
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +33 -18
- manim/utils/testing/frames_comparison.py +27 -19
- manim/utils/tex.py +127 -197
- manim/utils/tex_file_writing.py +47 -45
- manim/utils/tex_templates.py +2 -1
- manim/utils/unit.py +6 -5
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE.community +1 -1
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/METADATA +40 -39
- manim-0.19.0.dist-info/RECORD +221 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
- manim/cli/new/__init__.py +0 -0
- manim/cli/new/group.py +0 -189
- manim/plugins/import_plugins.py +0 -43
- manim-0.18.0.post0.dist-info/RECORD +0 -217
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
- {manim-0.18.0.post0.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
manim/scene/scene.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from manim.utils.parameter_parsing import flatten_iterable_parameters
|
|
6
|
+
|
|
5
7
|
__all__ = ["Scene"]
|
|
6
8
|
|
|
7
9
|
import copy
|
|
@@ -13,7 +15,6 @@ import threading
|
|
|
13
15
|
import time
|
|
14
16
|
import types
|
|
15
17
|
from queue import Queue
|
|
16
|
-
from typing import Callable
|
|
17
18
|
|
|
18
19
|
import srt
|
|
19
20
|
|
|
@@ -25,6 +26,8 @@ try:
|
|
|
25
26
|
dearpygui_imported = True
|
|
26
27
|
except ImportError:
|
|
27
28
|
dearpygui_imported = False
|
|
29
|
+
from typing import TYPE_CHECKING
|
|
30
|
+
|
|
28
31
|
import numpy as np
|
|
29
32
|
from tqdm import tqdm
|
|
30
33
|
from watchdog.events import FileSystemEventHandler
|
|
@@ -48,6 +51,12 @@ from ..utils.family_ops import restructure_list_to_exclude_certain_family_member
|
|
|
48
51
|
from ..utils.file_ops import open_media_file
|
|
49
52
|
from ..utils.iterables import list_difference_update, list_update
|
|
50
53
|
|
|
54
|
+
if TYPE_CHECKING:
|
|
55
|
+
from collections.abc import Sequence
|
|
56
|
+
from typing import Callable
|
|
57
|
+
|
|
58
|
+
from manim.mobject.mobject import _AnimationBuilder
|
|
59
|
+
|
|
51
60
|
|
|
52
61
|
class RerunSceneHandler(FileSystemEventHandler):
|
|
53
62
|
"""A class to handle rerunning a Scene after the input file is modified."""
|
|
@@ -93,12 +102,12 @@ class Scene:
|
|
|
93
102
|
|
|
94
103
|
def __init__(
|
|
95
104
|
self,
|
|
96
|
-
renderer=None,
|
|
97
|
-
camera_class=Camera,
|
|
98
|
-
always_update_mobjects=False,
|
|
99
|
-
random_seed=None,
|
|
100
|
-
skip_animations=False,
|
|
101
|
-
):
|
|
105
|
+
renderer: CairoRenderer | OpenGLRenderer | None = None,
|
|
106
|
+
camera_class: type[Camera] = Camera,
|
|
107
|
+
always_update_mobjects: bool = False,
|
|
108
|
+
random_seed: int | None = None,
|
|
109
|
+
skip_animations: bool = False,
|
|
110
|
+
) -> None:
|
|
102
111
|
self.camera_class = camera_class
|
|
103
112
|
self.always_update_mobjects = always_update_mobjects
|
|
104
113
|
self.random_seed = random_seed
|
|
@@ -151,6 +160,11 @@ class Scene:
|
|
|
151
160
|
def camera(self):
|
|
152
161
|
return self.renderer.camera
|
|
153
162
|
|
|
163
|
+
@property
|
|
164
|
+
def time(self) -> float:
|
|
165
|
+
"""The time since the start of the scene."""
|
|
166
|
+
return self.renderer.time
|
|
167
|
+
|
|
154
168
|
def __deepcopy__(self, clone_from_id):
|
|
155
169
|
cls = self.__class__
|
|
156
170
|
result = cls.__new__(cls)
|
|
@@ -223,7 +237,7 @@ class Scene:
|
|
|
223
237
|
self.construct()
|
|
224
238
|
except EndSceneEarlyException:
|
|
225
239
|
pass
|
|
226
|
-
except RerunSceneException
|
|
240
|
+
except RerunSceneException:
|
|
227
241
|
self.remove(*self.mobjects)
|
|
228
242
|
self.renderer.clear_screen()
|
|
229
243
|
self.renderer.num_plays = 0
|
|
@@ -281,7 +295,7 @@ class Scene:
|
|
|
281
295
|
Examples
|
|
282
296
|
--------
|
|
283
297
|
A typical manim script includes a class derived from :class:`Scene` with an
|
|
284
|
-
overridden :meth:`Scene.
|
|
298
|
+
overridden :meth:`Scene.construct` method:
|
|
285
299
|
|
|
286
300
|
.. code-block:: python
|
|
287
301
|
|
|
@@ -301,14 +315,14 @@ class Scene:
|
|
|
301
315
|
def next_section(
|
|
302
316
|
self,
|
|
303
317
|
name: str = "unnamed",
|
|
304
|
-
|
|
318
|
+
section_type: str = DefaultSectionType.NORMAL,
|
|
305
319
|
skip_animations: bool = False,
|
|
306
320
|
) -> None:
|
|
307
321
|
"""Create separation here; the last section gets finished and a new one gets created.
|
|
308
322
|
``skip_animations`` skips the rendering of all animations in this section.
|
|
309
323
|
Refer to :doc:`the documentation</tutorials/output_and_config>` on how to use sections.
|
|
310
324
|
"""
|
|
311
|
-
self.renderer.file_writer.next_section(name,
|
|
325
|
+
self.renderer.file_writer.next_section(name, section_type, skip_animations)
|
|
312
326
|
|
|
313
327
|
def __str__(self):
|
|
314
328
|
return self.__class__.__name__
|
|
@@ -474,7 +488,7 @@ class Scene:
|
|
|
474
488
|
self.moving_mobjects += mobjects
|
|
475
489
|
return self
|
|
476
490
|
|
|
477
|
-
def add_mobjects_from_animations(self, animations):
|
|
491
|
+
def add_mobjects_from_animations(self, animations: list[Animation]) -> None:
|
|
478
492
|
curr_mobjects = self.get_mobject_family_members()
|
|
479
493
|
for animation in animations:
|
|
480
494
|
if animation.is_introducer():
|
|
@@ -613,7 +627,7 @@ class Scene:
|
|
|
613
627
|
|
|
614
628
|
def restructure_mobjects(
|
|
615
629
|
self,
|
|
616
|
-
to_remove: Mobject,
|
|
630
|
+
to_remove: Sequence[Mobject],
|
|
617
631
|
mobject_list_name: str = "mobjects",
|
|
618
632
|
extract_families: bool = True,
|
|
619
633
|
):
|
|
@@ -673,7 +687,6 @@ class Scene:
|
|
|
673
687
|
list
|
|
674
688
|
The list of mobjects with the mobjects to remove removed.
|
|
675
689
|
"""
|
|
676
|
-
|
|
677
690
|
new_mobjects = []
|
|
678
691
|
|
|
679
692
|
def add_safe_mobjects_from_list(list_to_examine, set_to_remove):
|
|
@@ -865,7 +878,11 @@ class Scene:
|
|
|
865
878
|
)
|
|
866
879
|
return all_moving_mobject_families, static_mobjects
|
|
867
880
|
|
|
868
|
-
def compile_animations(
|
|
881
|
+
def compile_animations(
|
|
882
|
+
self,
|
|
883
|
+
*args: Animation | Mobject | _AnimationBuilder,
|
|
884
|
+
**kwargs,
|
|
885
|
+
):
|
|
869
886
|
"""
|
|
870
887
|
Creates _MethodAnimations from any _AnimationBuilders and updates animation
|
|
871
888
|
kwargs with kwargs passed to play().
|
|
@@ -883,19 +900,21 @@ class Scene:
|
|
|
883
900
|
Animations to be played.
|
|
884
901
|
"""
|
|
885
902
|
animations = []
|
|
886
|
-
|
|
903
|
+
arg_anims = flatten_iterable_parameters(args)
|
|
904
|
+
# Allow passing a generator to self.play instead of comma separated arguments
|
|
905
|
+
for arg in arg_anims:
|
|
887
906
|
try:
|
|
888
907
|
animations.append(prepare_animation(arg))
|
|
889
|
-
except TypeError:
|
|
908
|
+
except TypeError as e:
|
|
890
909
|
if inspect.ismethod(arg):
|
|
891
910
|
raise TypeError(
|
|
892
911
|
"Passing Mobject methods to Scene.play is no longer"
|
|
893
912
|
" supported. Use Mobject.animate instead.",
|
|
894
|
-
)
|
|
913
|
+
) from e
|
|
895
914
|
else:
|
|
896
915
|
raise TypeError(
|
|
897
916
|
f"Unexpected argument {arg} passed to Scene.play().",
|
|
898
|
-
)
|
|
917
|
+
) from e
|
|
899
918
|
|
|
900
919
|
for animation in animations:
|
|
901
920
|
for k, v in kwargs.items():
|
|
@@ -1003,6 +1022,35 @@ class Scene:
|
|
|
1003
1022
|
)
|
|
1004
1023
|
return time_progression
|
|
1005
1024
|
|
|
1025
|
+
@classmethod
|
|
1026
|
+
def validate_run_time(
|
|
1027
|
+
cls,
|
|
1028
|
+
run_time: float,
|
|
1029
|
+
method: Callable[[Any, ...], Any],
|
|
1030
|
+
parameter_name: str = "run_time",
|
|
1031
|
+
) -> float:
|
|
1032
|
+
method_name = f"{cls.__name__}.{method.__name__}()"
|
|
1033
|
+
if run_time <= 0:
|
|
1034
|
+
raise ValueError(
|
|
1035
|
+
f"{method_name} has a {parameter_name} of "
|
|
1036
|
+
f"{run_time:g} <= 0 seconds which Manim cannot render. "
|
|
1037
|
+
f"The {parameter_name} must be a positive number."
|
|
1038
|
+
)
|
|
1039
|
+
|
|
1040
|
+
# config.frame_rate holds the number of frames per second
|
|
1041
|
+
fps = config.frame_rate
|
|
1042
|
+
seconds_per_frame = 1 / fps
|
|
1043
|
+
if run_time < seconds_per_frame:
|
|
1044
|
+
logger.warning(
|
|
1045
|
+
f"The original {parameter_name} of {method_name}, "
|
|
1046
|
+
f"{run_time:g} seconds, is too short for the current frame "
|
|
1047
|
+
f"rate of {fps:g} FPS. Rendering with the shortest possible "
|
|
1048
|
+
f"{parameter_name} of {seconds_per_frame:g} seconds instead."
|
|
1049
|
+
)
|
|
1050
|
+
run_time = seconds_per_frame
|
|
1051
|
+
|
|
1052
|
+
return run_time
|
|
1053
|
+
|
|
1006
1054
|
def get_run_time(self, animations: list[Animation]):
|
|
1007
1055
|
"""
|
|
1008
1056
|
Gets the total run time for a list of animations.
|
|
@@ -1018,16 +1066,13 @@ class Scene:
|
|
|
1018
1066
|
float
|
|
1019
1067
|
The total ``run_time`` of all of the animations in the list.
|
|
1020
1068
|
"""
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
else:
|
|
1026
|
-
return np.max([animation.run_time for animation in animations])
|
|
1069
|
+
run_time = max(animation.run_time for animation in animations)
|
|
1070
|
+
run_time = self.validate_run_time(run_time, self.play, "total run_time")
|
|
1071
|
+
return run_time
|
|
1027
1072
|
|
|
1028
1073
|
def play(
|
|
1029
1074
|
self,
|
|
1030
|
-
*args,
|
|
1075
|
+
*args: Animation | Mobject | _AnimationBuilder,
|
|
1031
1076
|
subcaption=None,
|
|
1032
1077
|
subcaption_duration=None,
|
|
1033
1078
|
subcaption_offset=0,
|
|
@@ -1076,15 +1121,15 @@ class Scene:
|
|
|
1076
1121
|
)
|
|
1077
1122
|
return
|
|
1078
1123
|
|
|
1079
|
-
start_time = self.
|
|
1124
|
+
start_time = self.time
|
|
1080
1125
|
self.renderer.play(self, *args, **kwargs)
|
|
1081
|
-
run_time = self.
|
|
1126
|
+
run_time = self.time - start_time
|
|
1082
1127
|
if subcaption:
|
|
1083
1128
|
if subcaption_duration is None:
|
|
1084
1129
|
subcaption_duration = run_time
|
|
1085
1130
|
# The start of the subcaption needs to be offset by the
|
|
1086
1131
|
# run_time of the animation because it is added after
|
|
1087
|
-
# the animation has already been played (and Scene.
|
|
1132
|
+
# the animation has already been played (and Scene.time
|
|
1088
1133
|
# has already been updated).
|
|
1089
1134
|
self.add_subcaption(
|
|
1090
1135
|
content=subcaption,
|
|
@@ -1119,6 +1164,7 @@ class Scene:
|
|
|
1119
1164
|
--------
|
|
1120
1165
|
:class:`.Wait`, :meth:`.should_mobjects_update`
|
|
1121
1166
|
"""
|
|
1167
|
+
duration = self.validate_run_time(duration, self.wait, "duration")
|
|
1122
1168
|
self.play(
|
|
1123
1169
|
Wait(
|
|
1124
1170
|
run_time=duration,
|
|
@@ -1142,6 +1188,7 @@ class Scene:
|
|
|
1142
1188
|
--------
|
|
1143
1189
|
:meth:`.wait`, :class:`.Wait`
|
|
1144
1190
|
"""
|
|
1191
|
+
duration = self.validate_run_time(duration, self.pause, "duration")
|
|
1145
1192
|
self.wait(duration=duration, frozen_frame=True)
|
|
1146
1193
|
|
|
1147
1194
|
def wait_until(self, stop_condition: Callable[[], bool], max_time: float = 60):
|
|
@@ -1155,9 +1202,14 @@ class Scene:
|
|
|
1155
1202
|
max_time
|
|
1156
1203
|
The maximum wait time in seconds.
|
|
1157
1204
|
"""
|
|
1205
|
+
max_time = self.validate_run_time(max_time, self.wait_until, "max_time")
|
|
1158
1206
|
self.wait(max_time, stop_condition=stop_condition)
|
|
1159
1207
|
|
|
1160
|
-
def compile_animation_data(
|
|
1208
|
+
def compile_animation_data(
|
|
1209
|
+
self,
|
|
1210
|
+
*animations: Animation | Mobject | _AnimationBuilder,
|
|
1211
|
+
**play_kwargs,
|
|
1212
|
+
):
|
|
1161
1213
|
"""Given a list of animations, compile the corresponding
|
|
1162
1214
|
static and moving mobjects, and gather the animation durations.
|
|
1163
1215
|
|
|
@@ -1189,16 +1241,16 @@ class Scene:
|
|
|
1189
1241
|
self.moving_mobjects = []
|
|
1190
1242
|
self.static_mobjects = []
|
|
1191
1243
|
|
|
1244
|
+
self.duration = self.get_run_time(self.animations)
|
|
1192
1245
|
if len(self.animations) == 1 and isinstance(self.animations[0], Wait):
|
|
1193
1246
|
if self.should_update_mobjects():
|
|
1194
1247
|
self.update_mobjects(dt=0) # Any problems with this?
|
|
1195
1248
|
self.stop_condition = self.animations[0].stop_condition
|
|
1196
1249
|
else:
|
|
1197
|
-
self.duration = self.animations[0].duration
|
|
1198
1250
|
# Static image logic when the wait is static is done by the renderer, not here.
|
|
1199
1251
|
self.animations[0].is_static_wait = True
|
|
1200
1252
|
return None
|
|
1201
|
-
|
|
1253
|
+
|
|
1202
1254
|
return self
|
|
1203
1255
|
|
|
1204
1256
|
def begin_animations(self) -> None:
|
|
@@ -1282,9 +1334,7 @@ class Scene:
|
|
|
1282
1334
|
return True
|
|
1283
1335
|
|
|
1284
1336
|
def interactive_embed(self):
|
|
1285
|
-
"""
|
|
1286
|
-
Like embed(), but allows for screen interaction.
|
|
1287
|
-
"""
|
|
1337
|
+
"""Like embed(), but allows for screen interaction."""
|
|
1288
1338
|
if not self.check_interactive_embed_is_valid():
|
|
1289
1339
|
return
|
|
1290
1340
|
self.interactive_mode = True
|
|
@@ -1492,7 +1542,7 @@ class Scene:
|
|
|
1492
1542
|
r"""Adds an entry in the corresponding subcaption file
|
|
1493
1543
|
at the current time stamp.
|
|
1494
1544
|
|
|
1495
|
-
The current time stamp is obtained from ``Scene.
|
|
1545
|
+
The current time stamp is obtained from ``Scene.time``.
|
|
1496
1546
|
|
|
1497
1547
|
Parameters
|
|
1498
1548
|
----------
|
|
@@ -1522,18 +1572,15 @@ class Scene:
|
|
|
1522
1572
|
|
|
1523
1573
|
# second option: within the call to Scene.play
|
|
1524
1574
|
self.play(
|
|
1525
|
-
Transform(square, circle),
|
|
1526
|
-
subcaption="The square transforms."
|
|
1575
|
+
Transform(square, circle), subcaption="The square transforms."
|
|
1527
1576
|
)
|
|
1528
1577
|
|
|
1529
1578
|
"""
|
|
1530
1579
|
subtitle = srt.Subtitle(
|
|
1531
1580
|
index=len(self.renderer.file_writer.subcaptions),
|
|
1532
1581
|
content=content,
|
|
1533
|
-
start=datetime.timedelta(seconds=float(self.
|
|
1534
|
-
end=datetime.timedelta(
|
|
1535
|
-
seconds=float(self.renderer.time + offset + duration)
|
|
1536
|
-
),
|
|
1582
|
+
start=datetime.timedelta(seconds=float(self.time + offset)),
|
|
1583
|
+
end=datetime.timedelta(seconds=float(self.time + offset + duration)),
|
|
1537
1584
|
)
|
|
1538
1585
|
self.renderer.file_writer.subcaptions.append(subtitle)
|
|
1539
1586
|
|
|
@@ -1581,7 +1628,7 @@ class Scene:
|
|
|
1581
1628
|
"""
|
|
1582
1629
|
if self.renderer.skip_animations:
|
|
1583
1630
|
return
|
|
1584
|
-
time = self.
|
|
1631
|
+
time = self.time + time_offset
|
|
1585
1632
|
self.renderer.file_writer.add_sound(sound_file, time, gain, **kwargs)
|
|
1586
1633
|
|
|
1587
1634
|
def on_mouse_motion(self, point, d_point):
|