Skip to content

Commit 7844c84

Browse files
Implement sections for scenes (#3883)
Reimplement the ManimCE sections API, as well as generic fixes for `Tex`.
1 parent d09b03b commit 7844c84

File tree

82 files changed

+1512
-770
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1512
-770
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ repos:
1818
- id: python-check-blanket-noqa
1919
name: Precision flake ignores
2020
- repo: https://github.com/astral-sh/ruff-pre-commit
21-
rev: v0.5.2
21+
rev: v0.5.5
2222
hooks:
2323
- id: ruff
2424
name: ruff lint
@@ -32,16 +32,13 @@ repos:
3232
- id: flake8
3333
additional_dependencies:
3434
[
35-
flake8-bugbear==21.4.3,
36-
flake8-builtins==1.5.3,
37-
flake8-comprehensions>=3.6.1,
3835
flake8-docstrings==1.6.0,
3936
flake8-pytest-style==1.5.0,
4037
flake8-rst-docstrings==0.2.3,
4138
flake8-simplify==0.14.1,
4239
]
4340
- repo: https://github.com/pre-commit/mirrors-mypy
44-
rev: v1.10.1
41+
rev: v1.11.0
4542
hooks:
4643
- id: mypy
4744
additional_dependencies:

docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
# -- Project information -----------------------------------------------------
2727

2828
project = "Manim"
29-
copyright = f"2020-{datetime.now().year}, The Manim Community Dev Team"
29+
copyright = f"2020-{datetime.now().year}, The Manim Community Dev Team" # noqa: A001
3030
author = "The Manim Community Dev Team"
3131

3232

@@ -63,7 +63,7 @@
6363
alias_name: f"~manim.{module}.{alias_name}"
6464
for module, module_dict in ALIAS_DOCS_DICT.items()
6565
for category_dict in module_dict.values()
66-
for alias_name in category_dict.keys()
66+
for alias_name in category_dict
6767
}
6868
autoclass_content = "both"
6969

docs/source/guides/configuration.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,10 @@ A list of all config options
357357
'log_dir', 'log_to_file', 'max_files_cached', 'media_dir', 'media_width',
358358
'movie_file_extension', 'notify_outdated_version', 'output_file', 'partial_movie_dir',
359359
'pixel_height', 'pixel_width', 'plugins', 'preview',
360-
'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame',
361-
'save_pngs', 'scene_names', 'show_in_file_browser', 'sound', 'tex_dir',
360+
'progress_bar', 'quality', 'right_side', 'save_last_frame',
361+
'scene_names', 'show_in_file_browser', 'sound', 'tex_dir',
362362
'tex_template', 'tex_template_file', 'text_dir', 'top', 'transparent',
363-
'upto_animation_number', 'use_opengl_renderer', 'verbosity', 'video_dir',
363+
'upto_animation_number', 'verbosity', 'video_dir',
364364
'window_position', 'window_monitor', 'window_size', 'write_all', 'write_to_movie',
365365
'enable_wireframe', 'force_window']
366366

docs/source/installation.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ in order for Manim to work properly, some additional system
6868
dependencies need to be installed first. The following pages have
6969
operating system specific instructions for you to follow.
7070

71-
Manim requires Python version ``3.9`` or above to run.
71+
Manim requires Python version ``3.10`` or above to run.
7272

7373
.. hint::
7474

docs/source/installation/linux.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ The installation instructions depend on your particular operating
55
system and package manager. If you happen to know exactly what you are doing,
66
you can also simply ensure that your system has:
77

8-
- a reasonably recent version of Python 3 (3.9 or above),
8+
- a reasonably recent version of Python 3 (3.10 or above),
99
- with working Cairo bindings in the form of
1010
`pycairo <https://cairographics.org/pycairo/>`__,
1111
- and `Pango <https://pango.gnome.org>`__ headers.

docs/source/installation/windows.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ to make one of them available on your system.
1616
Required Dependencies
1717
---------------------
1818

19-
Manim requires a recent version of Python (3.9 or above)
19+
Manim requires a recent version of Python (3.10 or above)
2020
in order to work.
2121

2222
Chocolatey
@@ -35,7 +35,7 @@ Pip
3535
***
3636

3737
As mentioned above, Manim needs a reasonably recent version of
38-
Python 3 (3.9 or above).
38+
Python 3 (3.10 or above).
3939

4040
**Python:** Head over to https://www.python.org, download an installer
4141
for a recent version of Python, and follow its instructions to get Python

docs/source/reference.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ Cameras
3838
*******
3939

4040
.. inheritance-diagram::
41-
manim.camera.cairo_camera
41+
manim.camera.camera
4242
:parts: 1
43-
:top-classes: manim.camera.camera.Camera, manim.mobject.mobject.Mobject
43+
:top-classes: manim.camera.camera.Camera, manim.mobject.opengl.opengl_mobject.OpenGLMobject
4444

4545
Mobjects
4646
********

docs/source/tutorials/output_and_config.rst

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ At this point, you have just executed the following command.
1818
1919
Let's dissect what just happened step by step. First, this command executes
2020
manim on the file ``scene.py``, which contains our animation code. Further,
21-
this command tells manim exactly which ``Scene`` is to be rendered, in this case,
21+
this command tells manim exactly which :class:`.Scene` is to be rendered, in this case,
2222
it is ``SquareToCircle``. This is necessary because a single scene file may
2323
contain more than one scene. Next, the flag `-p` tells manim to play the scene
2424
once it's rendered, and the `-ql` flag tells manim to render the scene in low
@@ -140,44 +140,73 @@ resolutions, e.g. ``-s -ql``, ``-s -qh``
140140
Sections
141141
********
142142

143-
In addition to the movie output file one can use sections. Each section produces
144-
its own output video. The cuts between two sections can be set like this:
143+
In addition to the movie output file one can use sections. If :attr:`ManimConfig.save_sections` is ``True``,
144+
each section produces its own output video. In order to use sections, set :attr:`~Scene.sections_api` to ``True``.
145145

146146
.. code-block:: python
147147
148-
def construct(self):
149-
# play the first animations...
150-
# you don't need a section in the very beginning as it gets created automatically
151-
self.next_section()
152-
# play more animations...
153-
self.next_section("this is an optional name that doesn't have to be unique")
154-
# play even more animations...
155-
self.next_section("this is a section without any animations, it will be removed")
148+
class MyScene(Scene):
149+
sections_api = True
150+
151+
@section
152+
def introduction(self):
153+
# play the first animations...
154+
# the default name of this section is the name of the method
155+
...
156+
157+
@section(name="this is an optional name that doesn't have to be unique")
158+
def second_section(self):
159+
# play more animations...
160+
...
161+
162+
@section(skip=True)
163+
def finale(self):
164+
# play even more animations...
165+
# however, they won't be included in the final output video
166+
...
156167
157168
All the animations between two of these cuts get concatenated into a single output
158169
video file.
159170
Be aware that you need at least one animation in each section. For example this wouldn't create an output video:
160171

161172
.. code-block:: python
162173
163-
def construct(self):
164-
self.next_section()
165-
# this section doesn't have any animations and will be removed
166-
# but no error will be thrown
167-
# feel free to tend your flock of empty sections if you so desire
168-
self.add(Circle())
169-
self.next_section()
174+
class SectionsExampleWithNoAnimations(Scene):
175+
sections_api = True
176+
177+
@section
178+
def first(self):
179+
self.next_section()
180+
# this section doesn't have any animations and will be removed
181+
# but no error will be thrown
182+
# feel free to tend your flock of empty sections if you so desire
183+
self.add(Circle())
184+
185+
@section
186+
def next(self):
187+
# play some animations
188+
...
170189
171190
One way of fixing this is to wait a little:
172191

173192
.. code-block:: python
174193
175-
def construct(self):
176-
self.next_section()
177-
self.add(Circle())
178-
# now we wait 1sec and have an animation to satisfy the section
179-
self.wait()
180-
self.next_section()
194+
class SectionsExampleWithNoAnimations(Scene):
195+
sections_api = True
196+
197+
@section
198+
def first(self):
199+
self.next_section()
200+
# this section doesn't have any animations and will be removed
201+
# but no error will be thrown
202+
# feel free to tend your flock of empty sections if you so desire
203+
self.add(Circle())
204+
self.wait()
205+
206+
@section
207+
def next(self):
208+
# play some animations
209+
...
181210
182211
For videos to be created for each section you have to add the ``--save_sections`` flag to the Manim call like this:
183212

@@ -258,13 +287,20 @@ You can also skip rendering all animations belonging to a section like this:
258287

259288
.. code-block:: python
260289
261-
def construct(self):
262-
self.next_section(skip_animations=True)
263-
# play some animations that shall be skipped...
264-
self.next_section()
265-
# play some animations that won't get skipped...
290+
class SkippingSections(Scene):
291+
sections_api = True
266292
293+
@section(skip=True)
294+
def first(self):
295+
# play some animations
296+
# things here will execute, but they
297+
# won't be written to the output file
298+
...
267299
300+
@section
301+
def next(self):
302+
# play some animations
303+
...
268304
269305
270306
Some command line flags
@@ -277,9 +313,9 @@ When executing the command
277313
manim -pql scene.py SquareToCircle
278314
279315
it specifies the scene to render. This is not necessary now. When a single
280-
file contains only one ``Scene`` class, it will just render the ``Scene``
281-
class. When a single file contains more than one ``Scene`` class, manim will
282-
let you choose a ``Scene`` class. If your file contains multiple ``Scene``
316+
file contains only one :class:`.Scene` class, it will just render the :class:`.Scene`
317+
class. When a single file contains more than one :class:`.Scene` class, manim will
318+
let you choose a :class:`.Scene` class. If your file contains multiple :class:`.Scene`
283319
classes, and you want to render them all, you can use the ``-a`` flag.
284320

285321
As discussed previously, the ``-ql`` specifies low render quality (854x480
@@ -294,7 +330,7 @@ the file browser at the location of the animation instead of playing it, you
294330
can use the ``-f`` flag. You can also omit these two flags.
295331

296332
Finally, by default manim will output .mp4 files. If you want your animations
297-
in .gif format instead, use the ``--format gif`` flag. The output files will
333+
in .gif format instead, use the ``--format=gif`` flag. The output files will
298334
be in the same folder as the .mp4 files, and with the same name, but a
299335
different file extension.
300336

example_scenes/test_new_rendering.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@
22

33

44
class Test(Scene):
5-
def construct(self) -> None:
6-
self.play(
7-
Create(
8-
t := Tex(
9-
"Hello, world!", stroke_color=RED, fill_color=BLUE, stroke_width=2
10-
)
11-
)
12-
)
13-
self.play(FadeOut(t))
5+
sections_api = True
6+
7+
@section(name="spinning_math")
8+
def first_section(self) -> None:
9+
line = Line()
10+
line.add_updater(lambda m, dt: m.rotate(PI * dt))
11+
t = Tex(r"Math! $\sum e^{i\theta}$").add_updater(lambda m: m.next_to(line, UP))
12+
line.to_edge(LEFT)
13+
self.add(line, t)
1414
s = Square()
15-
self.add(s)
16-
self.play(Rotate(s, PI / 2))
17-
self.wait(7)
15+
t = Tex(
16+
"Hello, world!", stroke_color=RED, fill_color=BLUE, stroke_width=2
17+
).to_edge(RIGHT)
18+
self.add(t)
19+
self.play(Create(t), Rotate(s, PI / 2))
20+
self.wait(1)
1821
self.play(FadeOut(s))
22+
23+
@section
24+
def three_mobjects(self) -> None:
1925
sq = RegularPolygon(6)
2026
c = Circle()
2127
st = Star()
@@ -27,7 +33,11 @@ def construct(self) -> None:
2733
Create(st),
2834
)
2935
)
30-
self.play(FadeOut(VGroup(*self.mobjects)))
36+
self.play(FadeOut(VGroup(sq, c, st)))
37+
38+
@section(skip=True)
39+
def never_run(self) -> None:
40+
self.play(Write(Text("This should never be run")))
3141

3242

3343
if __name__ == "__main__":

manim/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
from manim.mobject.value_tracker import *
7373
from manim.mobject.vector_field import *
7474
from manim.scene.scene import *
75+
from manim.scene.sections import *
7576
from manim.scene.vector_space_scene import *
7677
from manim.utils import color, rate_functions, unit
7778
from manim.utils.bezier import *

0 commit comments

Comments
 (0)