mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Merge pull request #1379 from friedkeenan/3b1b-animate
Add .animate syntax
This commit is contained in:
commit
4ff876b536
10 changed files with 223 additions and 133 deletions
|
@ -12,11 +12,11 @@ class SquareToCircle(Scene):
|
||||||
self.play(ReplacementTransform(square, circle))
|
self.play(ReplacementTransform(square, circle))
|
||||||
self.wait()
|
self.wait()
|
||||||
# Try typing the following lines
|
# Try typing the following lines
|
||||||
# self.play(circle.stretch, 4, {"dim": 0})
|
# self.play(circle.animate.stretch(4, dim=0))
|
||||||
# self.play(Rotate(circle, TAU / 4))
|
# self.play(Rotate(circle, TAU / 4))
|
||||||
# self.play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
# self.play(circle.animate.shift(2 * RIGHT), circle.animate.scale(0.25))
|
||||||
# circle.insert_n_curves(10)
|
# circle.insert_n_curves(10)
|
||||||
# self.play(circle.apply_complex_function, lambda z: z**2)
|
# self.play(circle.animate.apply_complex_function(lambda z: z**2))
|
||||||
|
|
||||||
class SquareToCircleEmbed(Scene):
|
class SquareToCircleEmbed(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -26,12 +26,12 @@ class SquareToCircleEmbed(Scene):
|
||||||
|
|
||||||
self.add(circle)
|
self.add(circle)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(circle.stretch, 4, {"dim": 0})
|
self.play(circle.animate.stretch(4, dim=0))
|
||||||
self.wait(1.5)
|
self.wait(1.5)
|
||||||
self.play(Rotate(circle, TAU / 4))
|
self.play(Rotate(circle, TAU / 4))
|
||||||
self.wait(1.5)
|
self.wait(1.5)
|
||||||
self.play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
self.play(circle.animate.shift(2 * RIGHT), circle.animate.scale(0.25))
|
||||||
self.wait(1.5)
|
self.wait(1.5)
|
||||||
circle.insert_n_curves(10)
|
circle.insert_n_curves(10)
|
||||||
self.play(circle.apply_complex_function, lambda z: z**2)
|
self.play(circle.animate.apply_complex_function(lambda z: z**2))
|
||||||
self.wait(2)
|
self.wait(2)
|
||||||
|
|
Binary file not shown.
|
@ -1,8 +1,8 @@
|
||||||
Example Scenes
|
Example Scenes
|
||||||
==============
|
==============
|
||||||
|
|
||||||
After understanding the previous knowledge, we can understand more scenes.
|
After understanding the previous knowledge, we can understand more scenes.
|
||||||
Many example scenes are given in ``example_scenes.py``, let's start with
|
Many example scenes are given in ``example_scenes.py``, let's start with
|
||||||
the simplest and one by one.
|
the simplest and one by one.
|
||||||
|
|
||||||
InteractiveDevlopment
|
InteractiveDevlopment
|
||||||
|
@ -33,9 +33,9 @@ InteractiveDevlopment
|
||||||
# the interactive shell
|
# the interactive shell
|
||||||
self.play(ReplacementTransform(square, circle))
|
self.play(ReplacementTransform(square, circle))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(circle.stretch, 4, 0)
|
self.play(circle.animate.stretch(4, 0))
|
||||||
self.play(Rotate(circle, 90 * DEGREES))
|
self.play(Rotate(circle, 90 * DEGREES))
|
||||||
self.play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
self.play(circle.animate.shift(2 * RIGHT), circle.animate.scale(0.25))
|
||||||
|
|
||||||
text = Text("""
|
text = Text("""
|
||||||
In general, using the interactive shell
|
In general, using the interactive shell
|
||||||
|
@ -73,43 +73,52 @@ AnimatingMethods
|
||||||
grid = Tex(r"\pi").get_grid(10, 10, height=4)
|
grid = Tex(r"\pi").get_grid(10, 10, height=4)
|
||||||
self.add(grid)
|
self.add(grid)
|
||||||
|
|
||||||
# If you pass in a mobject method to the scene's "play" function,
|
# You can animate the application of mobject methods with the
|
||||||
# it will apply an animation interpolating between the mobject's
|
# ".animate" syntax:
|
||||||
# initial state and whatever happens when you apply that method.
|
self.play(grid.animate.shift(LEFT))
|
||||||
# For example, calling grid.shift(2 * LEFT) would shift it two units
|
|
||||||
# to the left, but the following line animates that motion.
|
# Alternatively, you can use the older syntax by passing the
|
||||||
self.play(grid.shift, 2 * LEFT)
|
# method and then the arguments to the scene's "play" function:
|
||||||
|
self.play(grid.shift, LEFT)
|
||||||
|
|
||||||
|
# Both of those will interpolate between the mobject's initial
|
||||||
|
# state and whatever happens when you apply that method.
|
||||||
|
# For this example, calling grid.shift(LEFT) would shift the
|
||||||
|
# grid one unit to the left, but both of the previous calls to
|
||||||
|
# "self.play" animate that motion.
|
||||||
|
|
||||||
# The same applies for any method, including those setting colors.
|
# The same applies for any method, including those setting colors.
|
||||||
self.play(grid.set_color, YELLOW)
|
self.play(grid.animate.set_color(YELLOW))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(grid.set_submobject_colors_by_gradient, BLUE, GREEN)
|
self.play(grid.animate.set_submobject_colors_by_gradient(BLUE, GREEN))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(grid.set_height, TAU - MED_SMALL_BUFF)
|
self.play(grid.animate.set_height(TAU - MED_SMALL_BUFF))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# The method Mobject.apply_complex_function lets you apply arbitrary
|
# The method Mobject.apply_complex_function lets you apply arbitrary
|
||||||
# complex functions, treating the points defining the mobject as
|
# complex functions, treating the points defining the mobject as
|
||||||
# complex numbers.
|
# complex numbers.
|
||||||
self.play(grid.apply_complex_function, np.exp, run_time=5)
|
self.play(grid.animate.apply_complex_function(np.exp), run_time=5)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Even more generally, you could apply Mobject.apply_function,
|
# Even more generally, you could apply Mobject.apply_function,
|
||||||
# which takes in functions form R^3 to R^3
|
# which takes in functions form R^3 to R^3
|
||||||
self.play(
|
self.play(
|
||||||
grid.apply_function,
|
grid.animate.apply_function(
|
||||||
lambda p: [
|
lambda p: [
|
||||||
p[0] + 0.5 * math.sin(p[1]),
|
p[0] + 0.5 * math.sin(p[1]),
|
||||||
p[1] + 0.5 * math.sin(p[0]),
|
p[1] + 0.5 * math.sin(p[0]),
|
||||||
p[2]
|
p[2]
|
||||||
],
|
]
|
||||||
|
),
|
||||||
run_time=5,
|
run_time=5,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
The new usage in this scene is ``.get_grid()`` and ``self.play(mob.method, args)``.
|
The new usage in this scene is ``.get_grid()`` and ``self.play(mob.animate.method(args))``.
|
||||||
|
|
||||||
- ``.get_grid()`` method will return a new mobject containing multiple copies of this one arranged in a grid.
|
- ``.get_grid()`` method will return a new mobject containing multiple copies of this one arranged in a grid.
|
||||||
- ``self.play(mob.method, args)`` animate the method, and the details are in the comments above.
|
- ``self.play(mob.animate.method(args))`` animates the method, and the details are in the comments above.
|
||||||
|
|
||||||
TextExample
|
TextExample
|
||||||
-----------
|
-----------
|
||||||
|
@ -328,18 +337,18 @@ UpdatersExample
|
||||||
|
|
||||||
# Notice that the brace and label track with the square
|
# Notice that the brace and label track with the square
|
||||||
self.play(
|
self.play(
|
||||||
square.scale, 2,
|
square.animate.scale(2),
|
||||||
rate_func=there_and_back,
|
rate_func=there_and_back,
|
||||||
run_time=2,
|
run_time=2,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(
|
self.play(
|
||||||
square.set_width, 5, {"stretch": True},
|
square.set_width(5, stretch=True),
|
||||||
run_time=3,
|
run_time=3,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(
|
self.play(
|
||||||
square.set_width, 2,
|
square.animate.set_width(2),
|
||||||
run_time=3
|
run_time=3
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
@ -355,7 +364,7 @@ UpdatersExample
|
||||||
)
|
)
|
||||||
self.wait(4 * PI)
|
self.wait(4 * PI)
|
||||||
|
|
||||||
The new classes and usage in this scene are ``always_redraw()``, ``DecimalNumber``, ``.to_edge()``,
|
The new classes and usage in this scene are ``always_redraw()``, ``DecimalNumber``, ``.to_edge()``,
|
||||||
``.center()``, ``always()``, ``f_always()``, ``.set_y()`` and ``.add_updater()``.
|
``.center()``, ``always()``, ``f_always()``, ``.set_y()`` and ``.add_updater()``.
|
||||||
|
|
||||||
- ``always_redraw()`` function create a new mobject every frame.
|
- ``always_redraw()`` function create a new mobject every frame.
|
||||||
|
@ -412,9 +421,9 @@ CoordinateSystemExample
|
||||||
dot = Dot(color=RED)
|
dot = Dot(color=RED)
|
||||||
dot.move_to(axes.c2p(0, 0))
|
dot.move_to(axes.c2p(0, 0))
|
||||||
self.play(FadeIn(dot, scale=0.5))
|
self.play(FadeIn(dot, scale=0.5))
|
||||||
self.play(dot.move_to, axes.c2p(3, 2))
|
self.play(dot.animate.move_to(axes.c2p(3, 2)))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(dot.move_to, axes.c2p(5, 0.5))
|
self.play(dot.animate.move_to(axes.c2p(5, 0.5)))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Similarly, you can call axes.point_to_coords, or axes.p2c
|
# Similarly, you can call axes.point_to_coords, or axes.p2c
|
||||||
|
@ -431,9 +440,9 @@ CoordinateSystemExample
|
||||||
ShowCreation(h_line),
|
ShowCreation(h_line),
|
||||||
ShowCreation(v_line),
|
ShowCreation(v_line),
|
||||||
)
|
)
|
||||||
self.play(dot.move_to, axes.c2p(3, -2))
|
self.play(dot.animate.move_to(axes.c2p(3, -2)))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(dot.move_to, axes.c2p(1, 1))
|
self.play(dot.animate.move_to(axes.c2p(1, 1)))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# If we tie the dot to a particular set of coordinates, notice
|
# If we tie the dot to a particular set of coordinates, notice
|
||||||
|
@ -441,8 +450,8 @@ CoordinateSystemExample
|
||||||
# system defined by them.
|
# system defined by them.
|
||||||
f_always(dot.move_to, lambda: axes.c2p(1, 1))
|
f_always(dot.move_to, lambda: axes.c2p(1, 1))
|
||||||
self.play(
|
self.play(
|
||||||
axes.scale, 0.75,
|
axes.animate.scale(0.75),
|
||||||
axes.to_corner, UL,
|
axes.animate.to_corner(UL),
|
||||||
run_time=2,
|
run_time=2,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
@ -534,8 +543,8 @@ GraphExample
|
||||||
lambda: axes.i2gp(x_tracker.get_value(), parabola)
|
lambda: axes.i2gp(x_tracker.get_value(), parabola)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.play(x_tracker.set_value, 4, run_time=3)
|
self.play(x_tracker.animate.set_value(4), run_time=3)
|
||||||
self.play(x_tracker.set_value, -2, run_time=3)
|
self.play(x_tracker.animate.set_value(-2), run_time=3)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
SurfaceExample
|
SurfaceExample
|
||||||
|
@ -608,8 +617,8 @@ SurfaceExample
|
||||||
self.play(
|
self.play(
|
||||||
Transform(surface, surfaces[2]),
|
Transform(surface, surfaces[2]),
|
||||||
# Move camera frame during the transition
|
# Move camera frame during the transition
|
||||||
frame.increment_phi, -10 * DEGREES,
|
frame.animate.increment_phi(-10 * DEGREES),
|
||||||
frame.increment_theta, -20 * DEGREES,
|
frame.animate.increment_theta(-20 * DEGREES),
|
||||||
run_time=3
|
run_time=3
|
||||||
)
|
)
|
||||||
# Add ambient rotation
|
# Add ambient rotation
|
||||||
|
@ -624,8 +633,8 @@ SurfaceExample
|
||||||
light = self.camera.light_source
|
light = self.camera.light_source
|
||||||
self.add(light)
|
self.add(light)
|
||||||
light.save_state()
|
light.save_state()
|
||||||
self.play(light.move_to, 3 * IN, run_time=5)
|
self.play(light.animate.move_to(3 * IN), run_time=5)
|
||||||
self.play(light.shift, 10 * OUT, run_time=5)
|
self.play(light.animate.shift(10 * OUT), run_time=5)
|
||||||
|
|
||||||
drag_text = Text("Try moving the mouse while pressing d or s")
|
drag_text = Text("Try moving the mouse while pressing d or s")
|
||||||
drag_text.move_to(light_text)
|
drag_text.move_to(light_text)
|
||||||
|
@ -634,7 +643,7 @@ SurfaceExample
|
||||||
self.play(FadeTransform(light_text, drag_text))
|
self.play(FadeTransform(light_text, drag_text))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
This scene shows an example of using a three-dimensional surface, and
|
This scene shows an example of using a three-dimensional surface, and
|
||||||
the related usage has been briefly described in the notes.
|
the related usage has been briefly described in the notes.
|
||||||
|
|
||||||
- ``.fix_in_frame()`` makes the object not change with the view angle of the screen, and is always displayed at a fixed position on the screen.
|
- ``.fix_in_frame()`` makes the object not change with the view angle of the screen, and is always displayed at a fixed position on the screen.
|
||||||
|
@ -675,7 +684,7 @@ OpeningManimExample
|
||||||
FadeTransform(intro_words, linear_transform_words)
|
FadeTransform(intro_words, linear_transform_words)
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(grid.apply_matrix, matrix, run_time=3)
|
self.play(grid.animate.apply_matrix(matrix), run_time=3)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Complex map
|
# Complex map
|
||||||
|
@ -699,12 +708,12 @@ OpeningManimExample
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(
|
self.play(
|
||||||
moving_c_grid.apply_complex_function, lambda z: z**2,
|
moving_c_grid.animate.apply_complex_function(lambda z: z**2),
|
||||||
run_time=6,
|
run_time=6,
|
||||||
)
|
)
|
||||||
self.wait(2)
|
self.wait(2)
|
||||||
|
|
||||||
This scene is a comprehensive application of a two-dimensional scene.
|
This scene is a comprehensive application of a two-dimensional scene.
|
||||||
|
|
||||||
After seeing these scenes, you have already understood part of the
|
After seeing these scenes, you have already understood part of the
|
||||||
usage of manim. For more examples, see `the video code of 3b1b <https://github.com/3b1b/videos>`_.
|
usage of manim. For more examples, see `the video code of 3b1b <https://github.com/3b1b/videos>`_.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
Quick Start
|
Quick Start
|
||||||
===========
|
===========
|
||||||
|
|
||||||
After installing the manim environment according to the instructions on the
|
After installing the manim environment according to the instructions on the
|
||||||
:doc:`installation` page, you can try to make a scene yourself from scratch.
|
:doc:`installation` page, you can try to make a scene yourself from scratch.
|
||||||
|
|
||||||
First, create a new ``.py`` file (such as ``start.py``) according to the following
|
First, create a new ``.py`` file (such as ``start.py``) according to the following
|
||||||
directory structure:
|
directory structure:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
@ -45,7 +45,7 @@ A window will pop up on the screen. And then you can :
|
||||||
- scroll the middle mouse button to move the screen up and down
|
- scroll the middle mouse button to move the screen up and down
|
||||||
- hold down the :kbd:`z` on the keyboard while scrolling the middle mouse button to zoom the screen
|
- hold down the :kbd:`z` on the keyboard while scrolling the middle mouse button to zoom the screen
|
||||||
- hold down the :kbd:`s` key on the keyboard and move the mouse to pan the screen
|
- hold down the :kbd:`s` key on the keyboard and move the mouse to pan the screen
|
||||||
- hold down the :kbd:`d` key on the keyboard and move the mouse to change the three-dimensional perspective.
|
- hold down the :kbd:`d` key on the keyboard and move the mouse to change the three-dimensional perspective.
|
||||||
|
|
||||||
Finally, you can close the window and exit the program by pressing :kbd:`q`.
|
Finally, you can close the window and exit the program by pressing :kbd:`q`.
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ Run this command again:
|
||||||
|
|
||||||
python manim.py start.py SquareToCircle -os
|
python manim.py start.py SquareToCircle -os
|
||||||
|
|
||||||
At this time, no window will pop up. When the program is finished, this rendered
|
At this time, no window will pop up. When the program is finished, this rendered
|
||||||
image will be automatically opened (saved in the subdirectory ``images/`` of the same
|
image will be automatically opened (saved in the subdirectory ``images/`` of the same
|
||||||
level directory of ``start.py`` by default):
|
level directory of ``start.py`` by default):
|
||||||
|
|
||||||
.. image:: ../_static/quickstart/SquareToCircle.png
|
.. image:: ../_static/quickstart/SquareToCircle.png
|
||||||
|
@ -67,36 +67,36 @@ Make an image
|
||||||
|
|
||||||
Next, let's take a detailed look at what each row does.
|
Next, let's take a detailed look at what each row does.
|
||||||
|
|
||||||
**Line 1**:
|
**Line 1**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from manimlib.imports import *
|
from manimlib.imports import *
|
||||||
|
|
||||||
This will import all the classes that may be used when using manim.
|
This will import all the classes that may be used when using manim.
|
||||||
|
|
||||||
**Line 3**:
|
**Line 3**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
class SquareToCircle(Scene):
|
class SquareToCircle(Scene):
|
||||||
|
|
||||||
Create a :class:`Scene` subclass ``SquareToCircle``, which will be
|
Create a :class:`Scene` subclass ``SquareToCircle``, which will be
|
||||||
the scene you write and render.
|
the scene you write and render.
|
||||||
|
|
||||||
**Line 4**:
|
**Line 4**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
|
||||||
Write the ``construct()`` method, the content of which will determine
|
Write the ``construct()`` method, the content of which will determine
|
||||||
how to create the mobjects in the screen and what operations need to be performed.
|
how to create the mobjects in the screen and what operations need to be performed.
|
||||||
|
|
||||||
**Line 5**:
|
**Line 5**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
circle = Circle()
|
circle = Circle()
|
||||||
|
|
||||||
Create a circle (an instance of the :class:`Circle` class), called ``circle``
|
Create a circle (an instance of the :class:`Circle` class), called ``circle``
|
||||||
|
@ -104,7 +104,7 @@ Create a circle (an instance of the :class:`Circle` class), called ``circle``
|
||||||
**Line 6~7**:
|
**Line 6~7**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
circle.set_fill(BLUE, opacity=0.5)
|
circle.set_fill(BLUE, opacity=0.5)
|
||||||
circle.set_stroke(BLUE_E, width=4)
|
circle.set_stroke(BLUE_E, width=4)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ Set the circle style by calling the circle's method.
|
||||||
**Line 9**:
|
**Line 9**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
self.add(circle)
|
self.add(circle)
|
||||||
|
|
||||||
Add this circle to the screen through the ``.add()`` method of :class:`Scene`.
|
Add this circle to the screen through the ``.add()`` method of :class:`Scene`.
|
||||||
|
@ -137,7 +137,7 @@ Let's change some codes and add some animations to make videos instead of just p
|
||||||
circle.set_fill(BLUE, opacity=0.5)
|
circle.set_fill(BLUE, opacity=0.5)
|
||||||
circle.set_stroke(BLUE_E, width=4)
|
circle.set_stroke(BLUE_E, width=4)
|
||||||
square = Square()
|
square = Square()
|
||||||
|
|
||||||
self.play(ShowCreation(square))
|
self.play(ShowCreation(square))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(ReplacementTransform(square, circle))
|
self.play(ReplacementTransform(square, circle))
|
||||||
|
@ -149,51 +149,51 @@ Run this command this time:
|
||||||
|
|
||||||
python manim.py start.py SquareToCircle
|
python manim.py start.py SquareToCircle
|
||||||
|
|
||||||
The pop-up window will play animations of drawing a square and transforming
|
The pop-up window will play animations of drawing a square and transforming
|
||||||
it into a circle. If you want to save this video, run:
|
it into a circle. If you want to save this video, run:
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
python manim.py start.py SquareToCircle -ow
|
python manim.py start.py SquareToCircle -ow
|
||||||
|
|
||||||
This time there will be no pop-up window, but the video file (saved in the subdirectory
|
This time there will be no pop-up window, but the video file (saved in the subdirectory
|
||||||
``videos/`` of the same level directory of ``start.py`` by default) will be automatically
|
``videos/`` of the same level directory of ``start.py`` by default) will be automatically
|
||||||
opened after the operation is over:
|
opened after the operation is over:
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
<video class="manim-video" controls loop autoplay src="../_static/quickstart/SquareToCircle.mp4"></video>
|
<video class="manim-video" controls loop autoplay src="../_static/quickstart/SquareToCircle.mp4"></video>
|
||||||
|
|
||||||
Let's take a look at the code this time. The first 7 lines are the same as the previous
|
Let's take a look at the code this time. The first 7 lines are the same as the previous
|
||||||
ones, and the 8th line is similar to the 5th line, which creates an instance of the
|
ones, and the 8th line is similar to the 5th line, which creates an instance of the
|
||||||
:class:`Square` class and named it ``square``.
|
:class:`Square` class and named it ``square``.
|
||||||
|
|
||||||
**Line 10**:
|
**Line 10**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
self.play(ShowCreation(square))
|
self.play(ShowCreation(square))
|
||||||
|
|
||||||
An animation is played through :class:`Scene`'s ``.play()`` method. :class:`ShowCreation`
|
An animation is played through :class:`Scene`'s ``.play()`` method. :class:`ShowCreation`
|
||||||
is an animation that shows the process of creating a given mobject.
|
is an animation that shows the process of creating a given mobject.
|
||||||
``self.play(ShowCreation(square))`` is to play the animation of creating ``square``.
|
``self.play(ShowCreation(square))`` is to play the animation of creating ``square``.
|
||||||
|
|
||||||
**Line 11**:
|
**Line 11**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
Use :class:`Scene`'s ``.wait()`` method to pause (default 1s), you can pass in
|
Use :class:`Scene`'s ``.wait()`` method to pause (default 1s), you can pass in
|
||||||
parameters to indicate the pause time (for example, ``self.wait(3)`` means pause for 3s).
|
parameters to indicate the pause time (for example, ``self.wait(3)`` means pause for 3s).
|
||||||
|
|
||||||
**Line 12**:
|
**Line 12**:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
self.play(ReplacementTransform(square, circle))
|
self.play(ReplacementTransform(square, circle))
|
||||||
|
|
||||||
Play the animation that transforms ``square`` into ``circle``.
|
Play the animation that transforms ``square`` into ``circle``.
|
||||||
``ReplacementTransform(A, B)`` means to transform A into B's pattern and replace A with B.
|
``ReplacementTransform(A, B)`` means to transform A into B's pattern and replace A with B.
|
||||||
|
|
||||||
**Line 13**: Same as line 11, pause for 1s.
|
**Line 13**: Same as line 11, pause for 1s.
|
||||||
|
@ -202,34 +202,34 @@ Play the animation that transforms ``square`` into ``circle``.
|
||||||
Enable interaction
|
Enable interaction
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Interaction is a new feature of the new version. You can add the following line
|
Interaction is a new feature of the new version. You can add the following line
|
||||||
at the end of the code to enable interaction:
|
at the end of the code to enable interaction:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
self.embed()
|
self.embed()
|
||||||
|
|
||||||
Then run ``python manim.py start.py SquareToCircle``.
|
Then run ``python manim.py start.py SquareToCircle``.
|
||||||
|
|
||||||
After the previous animation is executed, the ipython terminal will be opened on
|
After the previous animation is executed, the ipython terminal will be opened on
|
||||||
the command line. After that, you can continue to write code in it, and the statement
|
the command line. After that, you can continue to write code in it, and the statement
|
||||||
you entered will be executed immediately after pressing :kbd:`Enter`.
|
you entered will be executed immediately after pressing :kbd:`Enter`.
|
||||||
|
|
||||||
For example: input the following lines (without comment lines) into it respectively
|
For example: input the following lines (without comment lines) into it respectively
|
||||||
(``self.play`` can be abbreviated as ``play`` in this mode):
|
(``self.play`` can be abbreviated as ``play`` in this mode):
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# Stretched 4 times in the vertical direction
|
# Stretched 4 times in the vertical direction
|
||||||
play(circle.stretch, 4, {"dim": 0})
|
play(circle.animate.stretch(4, dim=0}))
|
||||||
# Rotate the ellipse 90°
|
# Rotate the ellipse 90°
|
||||||
play(Rotate(circle, TAU / 4))
|
play(Rotate(circle, TAU / 4))
|
||||||
# Move 2 units to the right and shrink to 1/4 of the original
|
# Move 2 units to the right and shrink to 1/4 of the original
|
||||||
play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
play(circle.animate.shift(2 * RIGHT), circle.animate.scale(0.25))
|
||||||
# Insert 10 curves into circle for non-linear transformation (no animation will play)
|
# Insert 10 curves into circle for non-linear transformation (no animation will play)
|
||||||
circle.insert_n_curves(10)
|
circle.insert_n_curves(10)
|
||||||
# Apply a complex transformation of f(z)=z^2 to all points on the circle
|
# Apply a complex transformation of f(z)=z^2 to all points on the circle
|
||||||
play(circle.apply_complex_function, lambda z: z**2)
|
play(circle.animate.apply_complex_function(lambda z: z**2))
|
||||||
# Close the window and exit the program
|
# Close the window and exit the program
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
@ -239,8 +239,8 @@ You will get an animation similar to the following:
|
||||||
|
|
||||||
<video class="manim-video" controls loop autoplay src="../_static/quickstart/SquareToCircleEmbed.mp4"></video>
|
<video class="manim-video" controls loop autoplay src="../_static/quickstart/SquareToCircleEmbed.mp4"></video>
|
||||||
|
|
||||||
If you want to enter the interactive mode directly, you don't have to write an
|
If you want to enter the interactive mode directly, you don't have to write an
|
||||||
empty scene containing only ``self.embed()``, you can directly run the following command
|
empty scene containing only ``self.embed()``, you can directly run the following command
|
||||||
(this will enter the ipython terminal while the window pops up):
|
(this will enter the ipython terminal while the window pops up):
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
@ -250,7 +250,7 @@ empty scene containing only ``self.embed()``, you can directly run the following
|
||||||
You succeeded!
|
You succeeded!
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
After reading the above content, you already know how to use manim.
|
After reading the above content, you already know how to use manim.
|
||||||
Below you can see some examples, in the :doc:`example_scenes` page.
|
Below you can see some examples, in the :doc:`example_scenes` page.
|
||||||
But before that, you'd better have a look at the :doc:`configuration` of manim.
|
But before that, you'd better have a look at the :doc:`configuration` of manim.
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class OpeningManimExample(Scene):
|
||||||
FadeTransform(intro_words, linear_transform_words)
|
FadeTransform(intro_words, linear_transform_words)
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(grid.apply_matrix, matrix, run_time=3)
|
self.play(grid.animate.apply_matrix(matrix), run_time=3)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Complex map
|
# Complex map
|
||||||
|
@ -61,7 +61,7 @@ class OpeningManimExample(Scene):
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(
|
self.play(
|
||||||
moving_c_grid.apply_complex_function, lambda z: z**2,
|
moving_c_grid.animate.apply_complex_function(lambda z: z**2),
|
||||||
run_time=6,
|
run_time=6,
|
||||||
)
|
)
|
||||||
self.wait(2)
|
self.wait(2)
|
||||||
|
@ -72,35 +72,44 @@ class AnimatingMethods(Scene):
|
||||||
grid = Tex(r"\pi").get_grid(10, 10, height=4)
|
grid = Tex(r"\pi").get_grid(10, 10, height=4)
|
||||||
self.add(grid)
|
self.add(grid)
|
||||||
|
|
||||||
# If you pass in a mobject method to the scene's "play" function,
|
# You can animate the application of mobject methods with the
|
||||||
# it will apply an animation interpolating between the mobject's
|
# ".animate" syntax:
|
||||||
# initial state and whatever happens when you apply that method.
|
self.play(grid.animate.shift(LEFT))
|
||||||
# For example, calling grid.shift(2 * LEFT) would shift it two units
|
|
||||||
# to the left, but the following line animates that motion.
|
# Alternatively, you can use the older syntax by passing the
|
||||||
self.play(grid.shift, 2 * LEFT)
|
# method and then the arguments to the scene's "play" function:
|
||||||
|
self.play(grid.shift, LEFT)
|
||||||
|
|
||||||
|
# Both of those will interpolate between the mobject's initial
|
||||||
|
# state and whatever happens when you apply that method.
|
||||||
|
# For this example, calling grid.shift(LEFT) would shift the
|
||||||
|
# grid one unit to the left, but both of the previous calls to
|
||||||
|
# "self.play" animate that motion.
|
||||||
|
|
||||||
# The same applies for any method, including those setting colors.
|
# The same applies for any method, including those setting colors.
|
||||||
self.play(grid.set_color, YELLOW)
|
self.play(grid.animate.set_color(YELLOW))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(grid.set_submobject_colors_by_gradient, BLUE, GREEN)
|
self.play(grid.animate.set_submobject_colors_by_gradient(BLUE, GREEN))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(grid.set_height, TAU - MED_SMALL_BUFF)
|
self.play(grid.animate.set_height(TAU - MED_SMALL_BUFF))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# The method Mobject.apply_complex_function lets you apply arbitrary
|
# The method Mobject.apply_complex_function lets you apply arbitrary
|
||||||
# complex functions, treating the points defining the mobject as
|
# complex functions, treating the points defining the mobject as
|
||||||
# complex numbers.
|
# complex numbers.
|
||||||
self.play(grid.apply_complex_function, np.exp, run_time=5)
|
self.play(grid.animate.apply_complex_function(np.exp), run_time=5)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Even more generally, you could apply Mobject.apply_function,
|
# Even more generally, you could apply Mobject.apply_function,
|
||||||
# which takes in functions form R^3 to R^3
|
# which takes in functions form R^3 to R^3
|
||||||
self.play(
|
self.play(
|
||||||
grid.apply_function,
|
grid.animate.apply_function(
|
||||||
lambda p: [
|
lambda p: [
|
||||||
p[0] + 0.5 * math.sin(p[1]),
|
p[0] + 0.5 * math.sin(p[1]),
|
||||||
p[1] + 0.5 * math.sin(p[0]),
|
p[1] + 0.5 * math.sin(p[0]),
|
||||||
p[2]
|
p[2]
|
||||||
],
|
]
|
||||||
|
),
|
||||||
run_time=5,
|
run_time=5,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
@ -294,18 +303,18 @@ class UpdatersExample(Scene):
|
||||||
|
|
||||||
# Notice that the brace and label track with the square
|
# Notice that the brace and label track with the square
|
||||||
self.play(
|
self.play(
|
||||||
square.scale, 2,
|
square.animate.scale(2),
|
||||||
rate_func=there_and_back,
|
rate_func=there_and_back,
|
||||||
run_time=2,
|
run_time=2,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(
|
self.play(
|
||||||
square.set_width, 5, {"stretch": True},
|
square.set_width(5, stretch=True),
|
||||||
run_time=3,
|
run_time=3,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(
|
self.play(
|
||||||
square.set_width, 2,
|
square.animate.set_width(2),
|
||||||
run_time=3
|
run_time=3
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
@ -361,9 +370,9 @@ class CoordinateSystemExample(Scene):
|
||||||
dot = Dot(color=RED)
|
dot = Dot(color=RED)
|
||||||
dot.move_to(axes.c2p(0, 0))
|
dot.move_to(axes.c2p(0, 0))
|
||||||
self.play(FadeIn(dot, scale=0.5))
|
self.play(FadeIn(dot, scale=0.5))
|
||||||
self.play(dot.move_to, axes.c2p(3, 2))
|
self.play(dot.animate.move_to(axes.c2p(3, 2)))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(dot.move_to, axes.c2p(5, 0.5))
|
self.play(dot.animate.move_to(axes.c2p(5, 0.5)))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# Similarly, you can call axes.point_to_coords, or axes.p2c
|
# Similarly, you can call axes.point_to_coords, or axes.p2c
|
||||||
|
@ -380,9 +389,9 @@ class CoordinateSystemExample(Scene):
|
||||||
ShowCreation(h_line),
|
ShowCreation(h_line),
|
||||||
ShowCreation(v_line),
|
ShowCreation(v_line),
|
||||||
)
|
)
|
||||||
self.play(dot.move_to, axes.c2p(3, -2))
|
self.play(dot.animate.move_to(axes.c2p(3, -2)))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(dot.move_to, axes.c2p(1, 1))
|
self.play(dot.animate.move_to(axes.c2p(1, 1)))
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
# If we tie the dot to a particular set of coordinates, notice
|
# If we tie the dot to a particular set of coordinates, notice
|
||||||
|
@ -390,8 +399,8 @@ class CoordinateSystemExample(Scene):
|
||||||
# system defined by them.
|
# system defined by them.
|
||||||
f_always(dot.move_to, lambda: axes.c2p(1, 1))
|
f_always(dot.move_to, lambda: axes.c2p(1, 1))
|
||||||
self.play(
|
self.play(
|
||||||
axes.scale, 0.75,
|
axes.animate.scale(0.75),
|
||||||
axes.to_corner, UL,
|
axes.animate.to_corner(UL),
|
||||||
run_time=2,
|
run_time=2,
|
||||||
)
|
)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
@ -477,8 +486,8 @@ class GraphExample(Scene):
|
||||||
lambda: axes.i2gp(x_tracker.get_value(), parabola)
|
lambda: axes.i2gp(x_tracker.get_value(), parabola)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.play(x_tracker.set_value, 4, run_time=3)
|
self.play(x_tracker.animate.set_value(4), run_time=3)
|
||||||
self.play(x_tracker.set_value, -2, run_time=3)
|
self.play(x_tracker.animate.set_value(-2), run_time=3)
|
||||||
self.wait()
|
self.wait()
|
||||||
|
|
||||||
|
|
||||||
|
@ -546,8 +555,8 @@ class SurfaceExample(Scene):
|
||||||
self.play(
|
self.play(
|
||||||
Transform(surface, surfaces[2]),
|
Transform(surface, surfaces[2]),
|
||||||
# Move camera frame during the transition
|
# Move camera frame during the transition
|
||||||
frame.increment_phi, -10 * DEGREES,
|
frame.animate.increment_phi(-10 * DEGREES),
|
||||||
frame.increment_theta, -20 * DEGREES,
|
frame.animate.increment_theta(-20 * DEGREES),
|
||||||
run_time=3
|
run_time=3
|
||||||
)
|
)
|
||||||
# Add ambient rotation
|
# Add ambient rotation
|
||||||
|
@ -562,8 +571,8 @@ class SurfaceExample(Scene):
|
||||||
light = self.camera.light_source
|
light = self.camera.light_source
|
||||||
self.add(light)
|
self.add(light)
|
||||||
light.save_state()
|
light.save_state()
|
||||||
self.play(light.move_to, 3 * IN, run_time=5)
|
self.play(light.animate.move_to(3 * IN), run_time=5)
|
||||||
self.play(light.shift, 10 * OUT, run_time=5)
|
self.play(light.animate.shift(10 * OUT), run_time=5)
|
||||||
|
|
||||||
drag_text = Text("Try moving the mouse while pressing d or s")
|
drag_text = Text("Try moving the mouse while pressing d or s")
|
||||||
drag_text.move_to(light_text)
|
drag_text.move_to(light_text)
|
||||||
|
@ -593,9 +602,9 @@ class InteractiveDevlopment(Scene):
|
||||||
# the interactive shell
|
# the interactive shell
|
||||||
self.play(ReplacementTransform(square, circle))
|
self.play(ReplacementTransform(square, circle))
|
||||||
self.wait()
|
self.wait()
|
||||||
self.play(circle.stretch, 4, 0)
|
self.play(circle.animate.stretch(4, 0))
|
||||||
self.play(Rotate(circle, 90 * DEGREES))
|
self.play(Rotate(circle, 90 * DEGREES))
|
||||||
self.play(circle.shift, 2 * RIGHT, circle.scale, 0.25)
|
self.play(circle.animate.shift(2 * RIGHT), circle.animate.scale(0.25))
|
||||||
|
|
||||||
text = Text("""
|
text = Text("""
|
||||||
In general, using the interactive shell
|
In general, using the interactive shell
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
from manimlib.mobject.mobject import Mobject
|
from manimlib.mobject.mobject import Mobject, _AnimationBuilder
|
||||||
from manimlib.utils.config_ops import digest_config
|
from manimlib.utils.config_ops import digest_config
|
||||||
from manimlib.utils.rate_functions import smooth
|
from manimlib.utils.rate_functions import smooth
|
||||||
from manimlib.utils.simple_functions import clip
|
from manimlib.utils.simple_functions import clip
|
||||||
|
@ -159,3 +159,13 @@ class Animation(object):
|
||||||
|
|
||||||
def is_remover(self):
|
def is_remover(self):
|
||||||
return self.remover
|
return self.remover
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_animation(anim):
|
||||||
|
if isinstance(anim, _AnimationBuilder):
|
||||||
|
return anim.build()
|
||||||
|
|
||||||
|
if isinstance(anim, Animation):
|
||||||
|
return anim
|
||||||
|
|
||||||
|
raise TypeError(f"Object {anim} cannot be converted to an animation")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from manimlib.animation.animation import Animation
|
from manimlib.animation.animation import Animation, prepare_animation
|
||||||
from manimlib.mobject.mobject import Group
|
from manimlib.mobject.mobject import Group
|
||||||
from manimlib.utils.bezier import integer_interpolate
|
from manimlib.utils.bezier import integer_interpolate
|
||||||
from manimlib.utils.bezier import interpolate
|
from manimlib.utils.bezier import interpolate
|
||||||
|
@ -29,7 +29,7 @@ class AnimationGroup(Animation):
|
||||||
|
|
||||||
def __init__(self, *animations, **kwargs):
|
def __init__(self, *animations, **kwargs):
|
||||||
digest_config(self, kwargs)
|
digest_config(self, kwargs)
|
||||||
self.animations = animations
|
self.animations = [prepare_animation(anim) for anim in animations]
|
||||||
if self.group is None:
|
if self.group is None:
|
||||||
self.group = Group(*remove_list_redundancies(
|
self.group = Group(*remove_list_redundancies(
|
||||||
[anim.mobject for anim in animations]
|
[anim.mobject for anim in animations]
|
||||||
|
|
|
@ -149,6 +149,12 @@ class MoveToTarget(Transform):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _MethodAnimation(MoveToTarget):
|
||||||
|
def __init__(self, mobject, methods):
|
||||||
|
self.methods = methods
|
||||||
|
super().__init__(mobject)
|
||||||
|
|
||||||
|
|
||||||
class ApplyMethod(Transform):
|
class ApplyMethod(Transform):
|
||||||
def __init__(self, method, *args, **kwargs):
|
def __init__(self, method, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -80,6 +80,11 @@ class Mobject(object):
|
||||||
if self.depth_test:
|
if self.depth_test:
|
||||||
self.apply_depth_test()
|
self.apply_depth_test()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def animate(self):
|
||||||
|
# Borrowed from https://github.com/ManimCommunity/manim/
|
||||||
|
return _AnimationBuilder(self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
@ -1573,3 +1578,51 @@ class Point(Mobject):
|
||||||
|
|
||||||
def set_location(self, new_loc):
|
def set_location(self, new_loc):
|
||||||
self.set_points(np.array(new_loc, ndmin=2, dtype=float))
|
self.set_points(np.array(new_loc, ndmin=2, dtype=float))
|
||||||
|
|
||||||
|
|
||||||
|
class _AnimationBuilder:
|
||||||
|
def __init__(self, mobject):
|
||||||
|
self.mobject = mobject
|
||||||
|
self.overridden_animation = None
|
||||||
|
self.mobject.generate_target()
|
||||||
|
self.is_chaining = False
|
||||||
|
self.methods = []
|
||||||
|
|
||||||
|
def __getattr__(self, method_name):
|
||||||
|
method = getattr(self.mobject.target, method_name)
|
||||||
|
self.methods.append(method)
|
||||||
|
has_overridden_animation = hasattr(method, "_override_animate")
|
||||||
|
|
||||||
|
if (self.is_chaining and has_overridden_animation) or self.overridden_animation:
|
||||||
|
raise NotImplementedError(
|
||||||
|
"Method chaining is currently not supported for "
|
||||||
|
"overridden animations"
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_target(*method_args, **method_kwargs):
|
||||||
|
if has_overridden_animation:
|
||||||
|
self.overridden_animation = method._override_animate(
|
||||||
|
self.mobject, *method_args, **method_kwargs
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
method(*method_args, **method_kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
|
self.is_chaining = True
|
||||||
|
return update_target
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
from manimlib.animation.transform import _MethodAnimation
|
||||||
|
|
||||||
|
if self.overridden_animation:
|
||||||
|
return self.overridden_animation
|
||||||
|
|
||||||
|
return _MethodAnimation(self.mobject, self.methods)
|
||||||
|
|
||||||
|
|
||||||
|
def override_animate(method):
|
||||||
|
def decorator(animation_method):
|
||||||
|
method._override_animate = animation_method
|
||||||
|
return animation_method
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
|
@ -10,7 +10,7 @@ import numpy as np
|
||||||
import time
|
import time
|
||||||
from IPython.terminal.embed import InteractiveShellEmbed
|
from IPython.terminal.embed import InteractiveShellEmbed
|
||||||
|
|
||||||
from manimlib.animation.animation import Animation
|
from manimlib.animation.animation import prepare_animation
|
||||||
from manimlib.animation.transform import MoveToTarget
|
from manimlib.animation.transform import MoveToTarget
|
||||||
from manimlib.mobject.mobject import Point
|
from manimlib.mobject.mobject import Point
|
||||||
from manimlib.camera.camera import Camera
|
from manimlib.camera.camera import Camera
|
||||||
|
@ -348,10 +348,7 @@ class Scene(object):
|
||||||
state["method_args"] = []
|
state["method_args"] = []
|
||||||
|
|
||||||
for arg in args:
|
for arg in args:
|
||||||
if isinstance(arg, Animation):
|
if inspect.ismethod(arg):
|
||||||
compile_method(state)
|
|
||||||
animations.append(arg)
|
|
||||||
elif inspect.ismethod(arg):
|
|
||||||
compile_method(state)
|
compile_method(state)
|
||||||
state["curr_method"] = arg
|
state["curr_method"] = arg
|
||||||
elif state["curr_method"] is not None:
|
elif state["curr_method"] is not None:
|
||||||
|
@ -362,7 +359,13 @@ class Scene(object):
|
||||||
you meant to pass in as a Scene.play argument
|
you meant to pass in as a Scene.play argument
|
||||||
""")
|
""")
|
||||||
else:
|
else:
|
||||||
raise Exception("Invalid play arguments")
|
try:
|
||||||
|
anim = prepare_animation(arg)
|
||||||
|
except TypeError:
|
||||||
|
raise TypeError(f"Unexpected argument {arg} passed to Scene.play()")
|
||||||
|
|
||||||
|
compile_method(state)
|
||||||
|
animations.append(anim)
|
||||||
compile_method(state)
|
compile_method(state)
|
||||||
|
|
||||||
for animation in animations:
|
for animation in animations:
|
||||||
|
|
Loading…
Add table
Reference in a new issue