Skip to content

Commit ffd8b42

Browse files
authored
Add .animate attribute to mobjects (#881)
Adds a .animate attribute to mobjects to be used to animate methods.
1 parent 33f20f4 commit ffd8b42

File tree

16 files changed

+120
-143
lines changed

16 files changed

+120
-143
lines changed

docs/source/examples.rst

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,10 @@ Animations
204204
def construct(self):
205205
square = Square(color=BLUE, fill_opacity=1)
206206

207-
self.play(square.shift, LEFT)
208-
self.play(square.set_fill, ORANGE)
209-
self.play(square.scale, 0.3)
210-
self.play(square.rotate, 0.4)
207+
self.play(square.animate.shift(LEFT))
208+
self.play(square.animate.set_fill(ORANGE))
209+
self.play(square.animate.scale(0.3))
210+
self.play(square.animate.rotate(0.4))
211211

212212
.. manim:: MovingFrameBox
213213
:ref_modules: manim.mobject.svg.tex_mobject
@@ -268,8 +268,8 @@ Animations
268268
self.add(path, dot)
269269
self.play(Rotating(dot, radians=PI, about_point=RIGHT, run_time=2))
270270
self.wait()
271-
self.play(dot.shift, UP)
272-
self.play(dot.shift, LEFT)
271+
self.play(dot.animate.shift(UP))
272+
self.play(dot.animate.shift(LEFT))
273273
self.wait()
274274

275275

@@ -394,9 +394,9 @@ Special Camera Settings
394394
moving_dot = Dot().move_to(graph.points[0]).set_color(ORANGE)
395395

396396
dot_at_start_graph = Dot().move_to(graph.points[0])
397-
dot_at_end_grap = Dot().move_to(graph.points[-1])
398-
self.add(graph, dot_at_end_grap, dot_at_start_graph, moving_dot)
399-
self.play( self.camera_frame.scale,0.5,self.camera_frame.move_to,moving_dot)
397+
dot_at_end_graph = Dot().move_to(graph.points[-1])
398+
self.add(graph, dot_at_end_graph, dot_at_start_graph, moving_dot)
399+
self.play(self.camera_frame.animate.scale(0.5),self.camera_frame.animate.move_to(moving_dot))
400400

401401
def update_curve(mob):
402402
mob.move_to(moving_dot.get_center())
@@ -462,15 +462,15 @@ Special Camera Settings
462462
# Scale in x y z
463463
scale_factor = [0.5, 1.5, 0]
464464
self.play(
465-
frame.scale, scale_factor,
466-
zoomed_display.scale, scale_factor,
465+
frame.animate.scale(scale_factor),
466+
zoomed_display.animate.scale(scale_factor),
467467
FadeOut(zoomed_camera_text),
468468
FadeOut(frame_text)
469469
)
470470
self.wait()
471471
self.play(ScaleInPlace(zoomed_display, 2))
472472
self.wait()
473-
self.play(frame.shift, 2.5 * DOWN)
473+
self.play(frame.animate.shift(2.5 * DOWN))
474474
self.wait()
475475
self.play(self.get_zoomed_display_pop_out_animation(), unfold_camera, rate_func=lambda t: smooth(1 - t))
476476
self.play(Uncreate(zoomed_display_frame), FadeOut(frame))
@@ -640,14 +640,15 @@ Advanced Projects
640640
grid_transform_title.move_to(grid_title, UL)
641641
grid.prepare_for_nonlinear_transform()
642642
self.play(
643-
grid.apply_function,
644-
lambda p: p
645-
+ np.array(
646-
[
647-
np.sin(p[1]),
648-
np.sin(p[0]),
649-
0,
650-
]
643+
grid.animate.apply_function(
644+
lambda p: p
645+
+ np.array(
646+
[
647+
np.sin(p[1]),
648+
np.sin(p[0]),
649+
0,
650+
]
651+
)
651652
),
652653
run_time=3,
653654
)

example_scenes/basic.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,15 @@ def construct(self):
5252
grid_transform_title.move_to(grid_title, UL)
5353
grid.prepare_for_nonlinear_transform()
5454
self.play(
55-
grid.apply_function,
56-
lambda p: p
57-
+ np.array(
58-
[
59-
np.sin(p[1]),
60-
np.sin(p[0]),
61-
0,
62-
]
55+
grid.animate.apply_function(
56+
lambda p: p
57+
+ np.array(
58+
[
59+
np.sin(p[1]),
60+
np.sin(p[0]),
61+
0,
62+
]
63+
)
6364
),
6465
run_time=3,
6566
)
@@ -121,8 +122,7 @@ def construct(self):
121122
decimal.add_updater(lambda d: d.set_value(square.get_center()[1]))
122123
self.add(square, decimal)
123124
self.play(
124-
square.to_edge,
125-
DOWN,
125+
square.animate.to_edge(DOWN),
126126
rate_func=there_and_back,
127127
run_time=5,
128128
)

manim/animation/animation.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,6 @@ def get_all_mobjects_to_update(self) -> list:
128128
def copy(self) -> "Animation":
129129
return deepcopy(self)
130130

131-
def update_config(self, **kwargs: typing.Dict[str, typing.Any]) -> "Animation":
132-
self.__dict__.update(kwargs)
133-
return self
134-
135131
# Methods for interpolation, the mean of an Animation
136132
def interpolate(self, alpha: float) -> None:
137133
alpha = np.clip(alpha, 0, 1)

manim/animation/transform.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ def check_validity_of_input(self, mobject: Mobject) -> None:
188188
)
189189

190190

191+
class _MethodAnimation(MoveToTarget):
192+
def __init__(self, mobject):
193+
super().__init__(mobject)
194+
195+
191196
class ApplyMethod(Transform):
192197
def __init__(
193198
self, method: types.MethodType, *args, **kwargs

manim/mobject/changing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def construct(self):
104104
trace = TracedPath(circ.get_start)
105105
rolling_circle.add_updater(lambda m: m.rotate(-0.3))
106106
self.add(trace, rolling_circle)
107-
self.play(rolling_circle.shift, 8*RIGHT, run_time=4, rate_func=linear)
107+
self.play(rolling_circle.animate.shift(8*RIGHT), run_time=4, rate_func=linear)
108108
109109
"""
110110

manim/mobject/mobject.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ def __init__(self, color=WHITE, name=None, dim=3, target=None, z_index=0, **kwar
5757
self.init_colors()
5858
Container.__init__(self, **kwargs)
5959

60+
@property
61+
def animate(self):
62+
"""
63+
Used to animate the application of a method.
64+
65+
Examples
66+
--------
67+
self.play(mobject.animate.shift(RIGHT))
68+
"""
69+
return _AnimationBuilder(self)
70+
6071
def __repr__(self):
6172
return str(self.name)
6273

@@ -1295,3 +1306,19 @@ class Group(Mobject):
12951306
def __init__(self, *mobjects, **kwargs):
12961307
Mobject.__init__(self, **kwargs)
12971308
self.add(*mobjects)
1309+
1310+
1311+
class _AnimationBuilder:
1312+
def __init__(self, mobject):
1313+
self.mobject = mobject
1314+
1315+
def __getattr__(self, method_name):
1316+
from ..animation.transform import _MethodAnimation
1317+
1318+
self.method = getattr(self.mobject.generate_target(), method_name)
1319+
1320+
def build(*method_args, **method_kwargs):
1321+
self.method(*method_args, **method_kwargs)
1322+
return _MethodAnimation(self.mobject)
1323+
1324+
return build

manim/mobject/numbers.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ def construct(self):
3131
decimal.add_updater(lambda d: d.set_value(square.get_center()[1]))
3232
self.add(square, decimal)
3333
self.play(
34-
square.to_edge,
35-
DOWN,
34+
square.animate.to_edge(DOWN),
3635
rate_func=there_and_back,
3736
run_time=5,
3837
)
@@ -261,7 +260,7 @@ def construct(self):
261260
self.wait()
262261
var_tracker = on_screen_var.tracker
263262
var = 10.5
264-
self.play(var_tracker.set_value, var)
263+
self.play(var_tracker.animate.set_value(var))
265264
self.wait()
266265
267266
int_var = 0
@@ -275,7 +274,7 @@ def construct(self):
275274
self.wait()
276275
var_tracker = on_screen_int_var.tracker
277276
var = 10.5
278-
self.play(var_tracker.set_value, var)
277+
self.play(var_tracker.animate.set_value(var))
279278
self.wait()
280279
281280
# If you wish to have a somewhat more complicated label for your

manim/mobject/types/vectorized_mobject.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,18 +1063,18 @@ def construct(self):
10631063
self.wait()
10641064
gr += gr2 # Add group to another
10651065
self.play(
1066-
gr.shift, DOWN,
1066+
gr.animate.shift(DOWN),
10671067
)
10681068
gr -= gr2 # Remove group
10691069
self.play( # Animate groups separately
1070-
gr.shift, LEFT,
1071-
gr2.shift, UP,
1070+
gr.animate.shift(LEFT),
1071+
gr2.animate.shift(UP),
10721072
)
10731073
self.play( #Animate groups without modification
1074-
(gr+gr2).shift, RIGHT
1074+
(gr+gr2).animate.shift(RIGHT)
10751075
)
10761076
self.play( # Animate group without component
1077-
(gr-circle_red).shift, RIGHT
1077+
(gr-circle_red).animate.shift(RIGHT)
10781078
)
10791079
"""
10801080
if not all(isinstance(m, VMobject) for m in vmobjects):
@@ -1156,7 +1156,7 @@ def construct(self):
11561156
11571157
# access submobjects like a python dict
11581158
my_dict["t"].set_color(PURPLE)
1159-
self.play(my_dict["t"].scale, 3)
1159+
self.play(my_dict["t"].animate.scale(3))
11601160
self.wait()
11611161
11621162
# also supports python dict styled reassignment

manim/mobject/value_tracker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ def construct(self):
3636
)
3737
)
3838
self.add(number_line, pointer,label)
39-
self.play(pointer_value.set_value, 5)
39+
self.play(pointer_value.animate.set_value(5)),
4040
self.wait()
41-
self.play(pointer_value.set_value, 3)
41+
self.play(pointer_value.animate.set_value(3))
4242
4343
"""
4444

manim/scene/moving_camera_scene.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def construct(self):
1515
text = Text("Hello World").set_color(BLUE)
1616
self.add(text)
1717
self.camera_frame.save_state()
18-
self.play(self.camera_frame.set_width, text.get_width() * 1.2)
18+
self.play(self.camera_frame.animate.set_width(text.get_width() * 1.2))
1919
self.wait(0.3)
2020
self.play(Restore(self.camera_frame))
2121
@@ -28,9 +28,9 @@ def construct(self):
2828
t = Triangle(color=GREEN, fill_opacity=0.5).move_to(2 * RIGHT)
2929
self.wait(0.3)
3030
self.add(s, t)
31-
self.play(self.camera_frame.move_to, s)
31+
self.play(self.camera_frame.animate.move_to(s))
3232
self.wait(0.3)
33-
self.play(self.camera_frame.move_to, t)
33+
self.play(self.camera_frame.animate.move_to(t))
3434
3535
3636
.. manim:: MovingAndZoomingCamera
@@ -40,14 +40,14 @@ def construct(self):
4040
s = Square(color=BLUE, fill_opacity=0.5).move_to(2 * LEFT)
4141
t = Triangle(color=YELLOW, fill_opacity=0.5).move_to(2 * RIGHT)
4242
self.add(s, t)
43-
self.play(self.camera_frame.move_to, s,
44-
self.camera_frame.set_width,s.get_width()*2)
43+
self.play(self.camera_frame.animate.move_to(s),
44+
self.camera_frame.animate.set_width(s.get_width()*2))
4545
self.wait(0.3)
46-
self.play(self.camera_frame.move_to, t,
47-
self.camera_frame.set_width,t.get_width()*2)
46+
self.play(self.camera_frame.animate.move_to(t),
47+
self.camera_frame.animate.set_width(t.get_width()*2))
4848
49-
self.play(self.camera_frame.move_to, ORIGIN,
50-
self.camera_frame.set_width,14)
49+
self.play(self.camera_frame.animate.move_to(ORIGIN),
50+
self.camera_frame.animate.set_width(14))
5151
5252
.. manim:: MovingCameraOnGraph
5353
@@ -64,10 +64,10 @@ def construct(self):
6464
x_max=3 * PI
6565
)
6666
dot_at_start_graph = Dot().move_to(graph.points[0])
67-
dot_at_end_grap = Dot().move_to(graph.points[-1])
68-
self.add(graph, dot_at_end_grap, dot_at_start_graph)
69-
self.play(self.camera_frame.scale, 0.5, self.camera_frame.move_to, dot_at_start_graph)
70-
self.play(self.camera_frame.move_to, dot_at_end_grap)
67+
dot_at_end_graph = Dot().move_to(graph.points[-1])
68+
self.add(graph, dot_at_end_graph, dot_at_start_graph)
69+
self.play(self.camera_frame.animate.scale(0.5), self.camera_frame.animate.move_to(dot_at_start_graph))
70+
self.play(self.camera_frame.animate.move_to(dot_at_end_graph))
7171
self.play(Restore(self.camera_frame))
7272
self.wait()
7373

0 commit comments

Comments
 (0)