manim-mcp 0.1.0
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.
- package/README.md +104 -0
- package/dist/demo.mp4 +0 -0
- package/dist/index.js +65 -0
- package/dist/mcp-app.html +142 -0
- package/dist/server.js +1492 -0
- package/package.json +67 -0
- package/references/composer/SKILL.md +154 -0
- package/references/composer/references/3b1b-series-patterns.md +217 -0
- package/references/composer/references/domain-planning-guides/calculus-planning.md +188 -0
- package/references/composer/references/domain-planning-guides/linear-algebra-planning.md +169 -0
- package/references/composer/references/domain-planning-guides/ml-planning.md +286 -0
- package/references/composer/references/domain-planning-guides/number-theory-planning.md +187 -0
- package/references/composer/references/domain-planning-guides/physics-planning.md +249 -0
- package/references/composer/references/domain-planning-guides/probability-planning.md +200 -0
- package/references/composer/references/mathematical-storytelling.md +359 -0
- package/references/composer/references/narrative-patterns.md +221 -0
- package/references/composer/references/opening-patterns.md +284 -0
- package/references/composer/references/pacing-guide.md +289 -0
- package/references/composer/references/scene-archetypes.md +534 -0
- package/references/composer/references/scene-examples.md +379 -0
- package/references/composer/references/visual-techniques.md +480 -0
- package/references/composer/templates/scenes-template.md +147 -0
- package/references/manimce/SKILL.md +166 -0
- package/references/manimce/examples/3d_visualization.py +373 -0
- package/references/manimce/examples/basic_animations.py +212 -0
- package/references/manimce/examples/graph_plotting.py +401 -0
- package/references/manimce/examples/lorenz_attractor.py +172 -0
- package/references/manimce/examples/math_visualization.py +315 -0
- package/references/manimce/examples/updater_patterns.py +369 -0
- package/references/manimce/rules/3b1b-translation.md +594 -0
- package/references/manimce/rules/3d.md +254 -0
- package/references/manimce/rules/advanced-animations.md +594 -0
- package/references/manimce/rules/animation-groups.md +212 -0
- package/references/manimce/rules/animations.md +128 -0
- package/references/manimce/rules/api-pitfalls.md +89 -0
- package/references/manimce/rules/axes.md +214 -0
- package/references/manimce/rules/camera.md +208 -0
- package/references/manimce/rules/cli.md +232 -0
- package/references/manimce/rules/color-conventions.md +444 -0
- package/references/manimce/rules/colors.md +199 -0
- package/references/manimce/rules/config.md +264 -0
- package/references/manimce/rules/creation-animations.md +158 -0
- package/references/manimce/rules/graphing.md +233 -0
- package/references/manimce/rules/grouping.md +220 -0
- package/references/manimce/rules/latex.md +202 -0
- package/references/manimce/rules/lines.md +241 -0
- package/references/manimce/rules/long-form-video.md +552 -0
- package/references/manimce/rules/mathematical-domains.md +689 -0
- package/references/manimce/rules/mobjects.md +116 -0
- package/references/manimce/rules/multi-scene-composition.md +112 -0
- package/references/manimce/rules/pedagogy.md +532 -0
- package/references/manimce/rules/physics-simulations.md +610 -0
- package/references/manimce/rules/positioning.md +211 -0
- package/references/manimce/rules/scenes.md +121 -0
- package/references/manimce/rules/shapes.md +300 -0
- package/references/manimce/rules/styling.md +177 -0
- package/references/manimce/rules/text-animations.md +222 -0
- package/references/manimce/rules/text.md +189 -0
- package/references/manimce/rules/timing.md +227 -0
- package/references/manimce/rules/transform-animations.md +157 -0
- package/references/manimce/rules/updaters.md +226 -0
- package/references/manimce/templates/basic_scene.py +64 -0
- package/references/manimce/templates/camera_scene.py +100 -0
- package/references/manimce/templates/threed_scene.py +138 -0
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 3b1b-translation
|
|
3
|
+
description: Comprehensive guide for translating ManimGL (3b1b video code) to ManimCE, with examples from all 407 video files
|
|
4
|
+
metadata:
|
|
5
|
+
tags: manimgl, manimce, translation, migration, porting, conversion, 3b1b, ShowCreation, CONFIG, InteractiveScene
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Translating ManimGL to ManimCE
|
|
9
|
+
|
|
10
|
+
This guide covers every major difference between the ManimGL code used in 3Blue1Brown's video repository and ManimCE (Manim Community Edition). The patterns come from analyzing 407 Python files across the `_2015/` through `_2026/` directories.
|
|
11
|
+
|
|
12
|
+
## Animation Name Changes
|
|
13
|
+
|
|
14
|
+
### ShowCreation to Create
|
|
15
|
+
|
|
16
|
+
The single most common translation. Every 3b1b file uses `ShowCreation`.
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
# ManimGL (3b1b)
|
|
20
|
+
self.play(ShowCreation(circle))
|
|
21
|
+
self.play(ShowCreation(plane, lag_ratio=0.01, run_time=3))
|
|
22
|
+
self.play(ShowCreation(rect))
|
|
23
|
+
|
|
24
|
+
# ManimCE
|
|
25
|
+
self.play(Create(circle))
|
|
26
|
+
self.play(Create(plane, lag_ratio=0.01, run_time=3))
|
|
27
|
+
self.play(Create(rect))
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Other Renamed Animations
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
# ManimGL # ManimCE
|
|
34
|
+
ShowCreation(mob) Create(mob)
|
|
35
|
+
ShowCreation(mob, lag_ratio=0.5) Create(mob, lag_ratio=0.5)
|
|
36
|
+
# Note: Write() works the same in both for text/equations
|
|
37
|
+
|
|
38
|
+
# These are the same in both:
|
|
39
|
+
# FadeIn, FadeOut, Write, GrowArrow, GrowFromCenter, Transform,
|
|
40
|
+
# ReplacementTransform, DrawBorderThenFill, Rotate, MoveToTarget,
|
|
41
|
+
# LaggedStartMap, LaggedStart, Succession, AnimationGroup
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Scene Classes
|
|
45
|
+
|
|
46
|
+
### InteractiveScene to Scene
|
|
47
|
+
|
|
48
|
+
3b1b's base class for most scenes is `InteractiveScene`. ManimCE uses `Scene`.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
# ManimGL (3b1b)
|
|
52
|
+
class MyScene(InteractiveScene):
|
|
53
|
+
def construct(self):
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
# ManimCE
|
|
57
|
+
class MyScene(Scene):
|
|
58
|
+
def construct(self):
|
|
59
|
+
...
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### PiCreatureScene / TeacherStudentsScene
|
|
63
|
+
|
|
64
|
+
These exist in 3b1b's custom directory (`custom/characters/`) and are not part of ManimCE. You can create similar patterns manually or use community plugins.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
# ManimGL (3b1b)
|
|
68
|
+
class AskAboutPosition(TeacherStudentsScene):
|
|
69
|
+
def construct(self):
|
|
70
|
+
self.teacher_says("Think about this...")
|
|
71
|
+
self.student_says("Oh, I see!")
|
|
72
|
+
|
|
73
|
+
# ManimCE: No direct equivalent. Use plain Scene with custom mobjects.
|
|
74
|
+
class AskAboutPosition(Scene):
|
|
75
|
+
def construct(self):
|
|
76
|
+
# Create speech bubbles manually
|
|
77
|
+
teacher_text = Text("Think about this...", font_size=28)
|
|
78
|
+
bubble = SurroundingRectangle(teacher_text, buff=0.3, corner_radius=0.2)
|
|
79
|
+
self.play(Create(bubble), Write(teacher_text))
|
|
80
|
+
self.wait()
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## CONFIG Dict to Class Attributes / __init__ Parameters
|
|
84
|
+
|
|
85
|
+
This is pervasive -- nearly every 3b1b class uses the CONFIG pattern.
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
# ManimGL (3b1b) -- CONFIG dict pattern
|
|
89
|
+
class Pendulum(VGroup):
|
|
90
|
+
CONFIG = {
|
|
91
|
+
"length": 3,
|
|
92
|
+
"gravity": 9.8,
|
|
93
|
+
"weight_diameter": 0.5,
|
|
94
|
+
"initial_theta": 0.3,
|
|
95
|
+
"omega": 0,
|
|
96
|
+
"damping": 0.1,
|
|
97
|
+
"top_point": 2 * UP,
|
|
98
|
+
"n_steps_per_frame": 100,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
def __init__(self, **kwargs):
|
|
102
|
+
super().__init__(**kwargs)
|
|
103
|
+
# self.length, self.gravity etc. are auto-set from CONFIG
|
|
104
|
+
|
|
105
|
+
# ManimCE -- use __init__ parameters
|
|
106
|
+
class Pendulum(VGroup):
|
|
107
|
+
def __init__(
|
|
108
|
+
self,
|
|
109
|
+
length=3,
|
|
110
|
+
gravity=9.8,
|
|
111
|
+
weight_diameter=0.5,
|
|
112
|
+
initial_theta=0.3,
|
|
113
|
+
omega=0,
|
|
114
|
+
damping=0.1,
|
|
115
|
+
top_point=2 * UP,
|
|
116
|
+
n_steps_per_frame=100,
|
|
117
|
+
**kwargs,
|
|
118
|
+
):
|
|
119
|
+
super().__init__(**kwargs)
|
|
120
|
+
self.length = length
|
|
121
|
+
self.gravity = gravity
|
|
122
|
+
self.weight_diameter = weight_diameter
|
|
123
|
+
self.initial_theta = initial_theta
|
|
124
|
+
self.omega = omega
|
|
125
|
+
self.damping = damping
|
|
126
|
+
self.top_point = top_point
|
|
127
|
+
self.n_steps_per_frame = n_steps_per_frame
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For Scene subclasses used as "configuration":
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# ManimGL (3b1b)
|
|
134
|
+
class GaltonBoard(InteractiveScene):
|
|
135
|
+
random_seed = 1
|
|
136
|
+
pegs_per_row = 15
|
|
137
|
+
n_rows = 5
|
|
138
|
+
spacing = 1.0
|
|
139
|
+
bucket_style = dict(fill_color=GREY_D, fill_opacity=1.0)
|
|
140
|
+
|
|
141
|
+
# ManimCE -- exactly the same! Class attributes work fine.
|
|
142
|
+
class GaltonBoard(Scene):
|
|
143
|
+
random_seed = 1
|
|
144
|
+
pegs_per_row = 15
|
|
145
|
+
n_rows = 5
|
|
146
|
+
spacing = 1.0
|
|
147
|
+
bucket_style = dict(fill_color=GREY_D, fill_opacity=1.0)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Camera and Frame Access
|
|
151
|
+
|
|
152
|
+
### self.frame to self.camera.frame
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# ManimGL (3b1b)
|
|
156
|
+
frame = self.frame
|
|
157
|
+
frame.set_height(10)
|
|
158
|
+
self.play(frame.animate.move_to(LEFT))
|
|
159
|
+
self.play(frame.animate.scale(0.5))
|
|
160
|
+
frame.add_updater(lambda m, dt: m.increment_theta(-0.1 * dt))
|
|
161
|
+
|
|
162
|
+
# ManimCE (MovingCameraScene)
|
|
163
|
+
class MyScene(MovingCameraScene):
|
|
164
|
+
def construct(self):
|
|
165
|
+
frame = self.camera.frame
|
|
166
|
+
self.play(frame.animate.set(width=10))
|
|
167
|
+
self.play(frame.animate.move_to(LEFT))
|
|
168
|
+
self.play(frame.animate.scale(0.5))
|
|
169
|
+
frame.add_updater(lambda m, dt: m.rotate(-0.1 * dt))
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### frame.reorient() to set_camera_orientation()
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# ManimGL (3b1b) -- 3D camera
|
|
176
|
+
frame.reorient(20, 70)
|
|
177
|
+
self.play(frame.animate.reorient(-30, 60))
|
|
178
|
+
|
|
179
|
+
# ManimCE (ThreeDScene)
|
|
180
|
+
class MyScene(ThreeDScene):
|
|
181
|
+
def construct(self):
|
|
182
|
+
self.set_camera_orientation(phi=70 * DEGREES, theta=20 * DEGREES)
|
|
183
|
+
self.move_camera(phi=60 * DEGREES, theta=-30 * DEGREES, run_time=2)
|
|
184
|
+
# Or for continuous rotation:
|
|
185
|
+
self.begin_ambient_camera_rotation(rate=0.2)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### fix_in_frame() to add_fixed_in_frame_mobjects()
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
# ManimGL (3b1b)
|
|
192
|
+
equation.fix_in_frame()
|
|
193
|
+
# Or:
|
|
194
|
+
mob.always.fix_in_frame()
|
|
195
|
+
|
|
196
|
+
# ManimCE (ThreeDScene)
|
|
197
|
+
class MyScene(ThreeDScene):
|
|
198
|
+
def construct(self):
|
|
199
|
+
equation = MathTex(r"E = mc^2")
|
|
200
|
+
self.add_fixed_in_frame_mobjects(equation)
|
|
201
|
+
# Now equation stays fixed while 3D camera moves
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## LaTeX / Text Classes
|
|
205
|
+
|
|
206
|
+
### Tex / OldTex / OldTexText to MathTex / Tex
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
# ManimGL (3b1b) -- RECENT code
|
|
210
|
+
formula = Tex(R"\frac{d}{dx} e^x = e^x", t2c={R"e^x": YELLOW})
|
|
211
|
+
label = TexText("Hello World")
|
|
212
|
+
|
|
213
|
+
# ManimGL (3b1b) -- OLDER code (pre-2020)
|
|
214
|
+
formula = OldTex(R"\frac{d}{dx} e^x = e^x")
|
|
215
|
+
label = OldTexText("Hello World")
|
|
216
|
+
|
|
217
|
+
# ManimCE
|
|
218
|
+
formula = MathTex(r"\frac{d}{dx} e^x = e^x", tex_to_color_map={r"e^x": YELLOW})
|
|
219
|
+
label = Tex(r"Hello World")
|
|
220
|
+
# Or for plain text:
|
|
221
|
+
label = Text("Hello World")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Key LaTeX Differences
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
# ManimGL: Uses R"..." raw strings (capital R)
|
|
228
|
+
Tex(R"\pi r^2")
|
|
229
|
+
Tex(R"...", t2c={R"\pi": RED})
|
|
230
|
+
|
|
231
|
+
# ManimCE: Uses r"..." raw strings (lowercase r), different kwarg name
|
|
232
|
+
MathTex(r"\pi r^2")
|
|
233
|
+
MathTex(r"...", tex_to_color_map={r"\pi": RED})
|
|
234
|
+
# Shorthand also works in ManimCE:
|
|
235
|
+
MathTex(r"...", t2c={r"\pi": RED})
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### TexText (styled text in LaTeX) to Tex
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
# ManimGL (3b1b)
|
|
242
|
+
title = TexText(R"Moser's Circle Problem", font_size=72)
|
|
243
|
+
|
|
244
|
+
# ManimCE
|
|
245
|
+
title = Tex(r"Moser's Circle Problem", font_size=72)
|
|
246
|
+
# Or often better:
|
|
247
|
+
title = Text("Moser's Circle Problem", font_size=72)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Updater Patterns
|
|
251
|
+
|
|
252
|
+
### f_always to add_updater
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
# ManimGL (3b1b)
|
|
256
|
+
dot.f_always.move_to(lambda: axes.i2gp(x_tracker.get_value(), graph))
|
|
257
|
+
f_always(counter.set_value, lambda: len(items))
|
|
258
|
+
frac_label.f_always.move_to(rect.get_center)
|
|
259
|
+
|
|
260
|
+
# ManimCE
|
|
261
|
+
dot.add_updater(lambda m: m.move_to(axes.i2gp(x_tracker.get_value(), graph)))
|
|
262
|
+
counter.add_updater(lambda m: m.set_value(len(items)))
|
|
263
|
+
frac_label.add_updater(lambda m: m.move_to(rect.get_center()))
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### mob.always.method() to add_updater
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
# ManimGL (3b1b)
|
|
270
|
+
randy.always.fix_in_frame()
|
|
271
|
+
label.always.next_to(dot, UR, SMALL_BUFF)
|
|
272
|
+
|
|
273
|
+
# ManimCE
|
|
274
|
+
# fix_in_frame doesn't have a direct always equivalent
|
|
275
|
+
# For ThreeDScene: self.add_fixed_in_frame_mobjects(randy)
|
|
276
|
+
label.add_updater(lambda m: m.next_to(dot, UR, SMALL_BUFF))
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### always_redraw (Same in Both!)
|
|
280
|
+
|
|
281
|
+
```python
|
|
282
|
+
# ManimGL (3b1b)
|
|
283
|
+
h_line = always_redraw(lambda: axes.get_h_line(dot.get_left()))
|
|
284
|
+
brace = always_redraw(Brace, square, UP)
|
|
285
|
+
|
|
286
|
+
# ManimCE -- identical!
|
|
287
|
+
h_line = always_redraw(lambda: axes.get_horizontal_line(dot.get_left()))
|
|
288
|
+
# Note: get_h_line -> get_horizontal_line in ManimCE
|
|
289
|
+
brace = always_redraw(lambda: Brace(square, UP))
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Coordinate Systems
|
|
293
|
+
|
|
294
|
+
### Axes Methods
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
# ManimGL (3b1b)
|
|
298
|
+
axes.get_h_line(point)
|
|
299
|
+
axes.get_v_line(point)
|
|
300
|
+
axes.get_graph(func)
|
|
301
|
+
|
|
302
|
+
# ManimCE
|
|
303
|
+
axes.get_horizontal_line(point)
|
|
304
|
+
axes.get_vertical_line(point)
|
|
305
|
+
axes.plot(func)
|
|
306
|
+
# Or for compatibility: axes.get_graph(func) also works in ManimCE
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Specific Mobject Translations
|
|
310
|
+
|
|
311
|
+
### GlowDot
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
# ManimGL (3b1b) -- used in zeta/play.py
|
|
315
|
+
s_dot = Group(TrueDot(), GlowDot())
|
|
316
|
+
s_dot.set_color(YELLOW)
|
|
317
|
+
|
|
318
|
+
# ManimCE -- no GlowDot, approximate with glow effect
|
|
319
|
+
dot = Dot(color=YELLOW, radius=0.08)
|
|
320
|
+
glow = Dot(color=YELLOW, radius=0.3).set_opacity(0.2)
|
|
321
|
+
s_dot = VGroup(glow, dot)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### set_backstroke()
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
# ManimGL (3b1b)
|
|
328
|
+
equations.set_backstroke()
|
|
329
|
+
label.set_backstroke(BLACK, 3)
|
|
330
|
+
|
|
331
|
+
# ManimCE
|
|
332
|
+
equations.set_stroke(BLACK, 5, background=True)
|
|
333
|
+
label.set_stroke(BLACK, 3, background=True)
|
|
334
|
+
|
|
335
|
+
# Or create a helper:
|
|
336
|
+
def set_backstroke(mob, color=BLACK, width=5):
|
|
337
|
+
mob.set_stroke(color, width, background=True)
|
|
338
|
+
return mob
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### make_number_changeable()
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
# ManimGL (3b1b) -- from _2025/zeta/play.py
|
|
345
|
+
exp_const_label = Tex(R"c = 0.0000", t2c={"c": RED})
|
|
346
|
+
c_dec = exp_const_label.make_number_changeable("0.0000")
|
|
347
|
+
c_dec.add_updater(lambda m: m.set_value(get_exp_const()))
|
|
348
|
+
|
|
349
|
+
# ManimCE -- use DecimalNumber explicitly
|
|
350
|
+
prefix = MathTex(r"c = ", color=WHITE)
|
|
351
|
+
c_dec = DecimalNumber(0, num_decimal_places=4, color=RED)
|
|
352
|
+
c_dec.add_updater(lambda m: m.set_value(get_exp_const()))
|
|
353
|
+
c_dec.add_updater(lambda m: m.next_to(prefix, RIGHT, buff=0.1))
|
|
354
|
+
label = VGroup(prefix, c_dec)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### ComplexValueTracker
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
# ManimGL (3b1b)
|
|
361
|
+
s_tracker = ComplexValueTracker(1)
|
|
362
|
+
get_s = s_tracker.get_value
|
|
363
|
+
|
|
364
|
+
# ManimCE -- no ComplexValueTracker, use two ValueTrackers
|
|
365
|
+
s_real = ValueTracker(1)
|
|
366
|
+
s_imag = ValueTracker(0)
|
|
367
|
+
get_s = lambda: complex(s_real.get_value(), s_imag.get_value())
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### NumericEmbedding and Custom Mobjects
|
|
371
|
+
|
|
372
|
+
The transformers series uses custom mobjects (`NumericEmbedding`, `WeightMatrix`, `ContextAnimation`, etc.) that don't exist in ManimCE. These need to be reimplemented.
|
|
373
|
+
|
|
374
|
+
```python
|
|
375
|
+
# ManimGL (3b1b) -- custom helper from transformers/helpers.py
|
|
376
|
+
embedding = NumericEmbedding(length=10).set_width(0.5)
|
|
377
|
+
|
|
378
|
+
# ManimCE -- build from primitives
|
|
379
|
+
def make_embedding(values, width=0.5, font_size=18):
|
|
380
|
+
entries = VGroup()
|
|
381
|
+
for val in values:
|
|
382
|
+
dec = DecimalNumber(val, num_decimal_places=2, font_size=font_size)
|
|
383
|
+
alpha = min(abs(val) / 3, 1)
|
|
384
|
+
color = interpolate_color(BLUE_E, BLUE_B, alpha) if val >= 0 else \
|
|
385
|
+
interpolate_color(RED_E, RED_B, alpha)
|
|
386
|
+
dec.set_color(color)
|
|
387
|
+
entries.add(dec)
|
|
388
|
+
entries.arrange(DOWN, buff=0.1)
|
|
389
|
+
brackets = MathTex(r"\left[ \right]", font_size=36)
|
|
390
|
+
left = brackets[0][:1]
|
|
391
|
+
right = brackets[0][1:]
|
|
392
|
+
left.stretch_to_fit_height(entries.height + 0.3).next_to(entries, LEFT, buff=0.1)
|
|
393
|
+
right.stretch_to_fit_height(entries.height + 0.3).next_to(entries, RIGHT, buff=0.1)
|
|
394
|
+
return VGroup(left, entries, right).set_width(width)
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## 3D-Specific Translations
|
|
398
|
+
|
|
399
|
+
### Camera Euler Angles
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
# ManimGL (3b1b)
|
|
403
|
+
self.camera.frame.set_euler_angles(
|
|
404
|
+
theta=-30 * DEGREES,
|
|
405
|
+
phi=70 * DEGREES,
|
|
406
|
+
)
|
|
407
|
+
self.camera.frame.increment_phi(-10 * DEGREES)
|
|
408
|
+
self.camera.frame.increment_theta(-20 * DEGREES)
|
|
409
|
+
|
|
410
|
+
# ManimCE (ThreeDScene)
|
|
411
|
+
self.set_camera_orientation(phi=70 * DEGREES, theta=-30 * DEGREES)
|
|
412
|
+
self.move_camera(phi=60 * DEGREES, theta=-50 * DEGREES)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Surface and TexturedSurface
|
|
416
|
+
|
|
417
|
+
```python
|
|
418
|
+
# ManimGL (3b1b)
|
|
419
|
+
torus = Torus(r1=1, r2=1)
|
|
420
|
+
sphere = Sphere(radius=3, resolution=torus.resolution)
|
|
421
|
+
earth = TexturedSurface(sphere, "EarthTextureMap", "NightEarthTextureMap")
|
|
422
|
+
mesh = SurfaceMesh(earth)
|
|
423
|
+
|
|
424
|
+
# ManimCE
|
|
425
|
+
torus = Torus(major_radius=1, minor_radius=1)
|
|
426
|
+
sphere = Sphere(radius=3)
|
|
427
|
+
# TexturedSurface not directly available; use Surface with custom func
|
|
428
|
+
# SurfaceMesh: not available, approximate with wireframe
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### Light Source
|
|
432
|
+
|
|
433
|
+
```python
|
|
434
|
+
# ManimGL (3b1b)
|
|
435
|
+
light = self.camera.light_source
|
|
436
|
+
self.play(light.move_to(3 * IN))
|
|
437
|
+
|
|
438
|
+
# ManimCE -- lighting is handled differently
|
|
439
|
+
# ManimCE uses ThreeDScene lighting config, not a movable light object
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
## Syntax Differences
|
|
443
|
+
|
|
444
|
+
### set_anim_args (ManimGL Only)
|
|
445
|
+
|
|
446
|
+
```python
|
|
447
|
+
# ManimGL (3b1b)
|
|
448
|
+
rect.animate.next_to(tale, RIGHT, buff=LARGE_BUFF).set_anim_args(rate_func=linear)
|
|
449
|
+
|
|
450
|
+
# ManimCE
|
|
451
|
+
# Pass rate_func to self.play() instead
|
|
452
|
+
self.play(
|
|
453
|
+
rect.animate.next_to(tale, RIGHT, buff=LARGE_BUFF),
|
|
454
|
+
rate_func=linear,
|
|
455
|
+
)
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### VGroup Generator Syntax
|
|
459
|
+
|
|
460
|
+
```python
|
|
461
|
+
# ManimGL (3b1b) -- generator inside VGroup (recent ManimGL feature)
|
|
462
|
+
embeddings = VGroup(
|
|
463
|
+
NumericEmbedding(length=10).set_width(0.5).next_to(rect, DOWN, buff=1.5)
|
|
464
|
+
for rect in all_rects
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
# ManimCE -- must use * unpacking or explicit list
|
|
468
|
+
embeddings = VGroup(*[
|
|
469
|
+
make_embedding([0]*10).next_to(rect, DOWN, buff=1.5)
|
|
470
|
+
for rect in all_rects
|
|
471
|
+
])
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### time_span in Animations
|
|
475
|
+
|
|
476
|
+
```python
|
|
477
|
+
# ManimGL (3b1b)
|
|
478
|
+
self.play(
|
|
479
|
+
FadeIn(elements, time_span=(1, 2)),
|
|
480
|
+
Write(text),
|
|
481
|
+
run_time=3,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
# ManimCE -- no time_span, use AnimationGroup or separate plays
|
|
485
|
+
self.play(Write(text), run_time=1)
|
|
486
|
+
self.play(FadeIn(elements), run_time=1)
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Import Translations
|
|
490
|
+
|
|
491
|
+
```python
|
|
492
|
+
# ManimGL (3b1b)
|
|
493
|
+
from manim_imports_ext import * # Their universal import
|
|
494
|
+
from manimlib import * # Direct manimlib import
|
|
495
|
+
from manimlib.animation.creation import ShowCreation
|
|
496
|
+
from manimlib.scene.interactive_scene import InteractiveScene
|
|
497
|
+
|
|
498
|
+
# ManimCE
|
|
499
|
+
from manim import * # Everything you need
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Complete Translation Example
|
|
503
|
+
|
|
504
|
+
### ManimGL Original (from codebase)
|
|
505
|
+
|
|
506
|
+
```python
|
|
507
|
+
from manim_imports_ext import *
|
|
508
|
+
|
|
509
|
+
class CircumferenceToArea(InteractiveScene):
|
|
510
|
+
def construct(self):
|
|
511
|
+
t2c = {"{r}": BLUE}
|
|
512
|
+
circum_formula = Tex(R"\text{Circumference} = 2 \pi {r}", t2c=t2c)
|
|
513
|
+
radius = 3
|
|
514
|
+
circle = Circle(radius=radius)
|
|
515
|
+
circle.set_stroke(YELLOW, 5)
|
|
516
|
+
r_group = VGroup(
|
|
517
|
+
Line(ORIGIN, radius * RIGHT).set_stroke(WHITE, 3),
|
|
518
|
+
Tex(R"r", font_size=72).set_color(BLUE),
|
|
519
|
+
)
|
|
520
|
+
self.add(circle, r_group)
|
|
521
|
+
self.play(
|
|
522
|
+
ShowCreation(circle),
|
|
523
|
+
Rotate(r_group, TAU, about_point=ORIGIN),
|
|
524
|
+
run_time=3,
|
|
525
|
+
)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### ManimCE Translation
|
|
529
|
+
|
|
530
|
+
```python
|
|
531
|
+
from manim import *
|
|
532
|
+
|
|
533
|
+
class CircumferenceToArea(Scene):
|
|
534
|
+
def construct(self):
|
|
535
|
+
t2c = {"{r}": BLUE}
|
|
536
|
+
circum_formula = MathTex(
|
|
537
|
+
r"\text{Circumference} = 2 \pi {r}",
|
|
538
|
+
tex_to_color_map=t2c,
|
|
539
|
+
)
|
|
540
|
+
radius = 3
|
|
541
|
+
circle = Circle(radius=radius)
|
|
542
|
+
circle.set_stroke(YELLOW, 5)
|
|
543
|
+
r_group = VGroup(
|
|
544
|
+
Line(ORIGIN, radius * RIGHT).set_stroke(WHITE, 3),
|
|
545
|
+
MathTex(r"r", font_size=72).set_color(BLUE),
|
|
546
|
+
)
|
|
547
|
+
self.add(circle, r_group)
|
|
548
|
+
self.play(
|
|
549
|
+
Create(circle),
|
|
550
|
+
Rotate(r_group, TAU, about_point=ORIGIN),
|
|
551
|
+
run_time=3,
|
|
552
|
+
)
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
## Quick Reference Table
|
|
556
|
+
|
|
557
|
+
| ManimGL (3b1b) | ManimCE | Frequency |
|
|
558
|
+
|-----------------|---------|-----------|
|
|
559
|
+
| `ShowCreation(mob)` | `Create(mob)` | Very high |
|
|
560
|
+
| `InteractiveScene` | `Scene` | Very high |
|
|
561
|
+
| `Tex(R"...", t2c={})` | `MathTex(r"...", tex_to_color_map={})` | Very high |
|
|
562
|
+
| `OldTex(R"...")` | `MathTex(r"...")` | High (older files) |
|
|
563
|
+
| `OldTexText("...")` | `Tex("...")` or `Text("...")` | High (older files) |
|
|
564
|
+
| `TexText("...")` | `Tex("...")` or `Text("...")` | High |
|
|
565
|
+
| `CONFIG = {...}` | `__init__` parameters | Very high |
|
|
566
|
+
| `self.frame` | `self.camera.frame` (MovingCameraScene) | High |
|
|
567
|
+
| `frame.reorient(th, ph)` | `self.set_camera_orientation(phi, theta)` | Medium |
|
|
568
|
+
| `mob.fix_in_frame()` | `self.add_fixed_in_frame_mobjects(mob)` | Medium |
|
|
569
|
+
| `mob.f_always.method(func)` | `mob.add_updater(lambda m: m.method(func()))` | Medium |
|
|
570
|
+
| `f_always(mob.set_value, func)` | `mob.add_updater(lambda m: m.set_value(func()))` | Medium |
|
|
571
|
+
| `mob.always.fix_in_frame()` | `self.add_fixed_in_frame_mobjects(mob)` | Low |
|
|
572
|
+
| `set_backstroke(color, w)` | `set_stroke(color, w, background=True)` | Medium |
|
|
573
|
+
| `make_number_changeable()` | Use `DecimalNumber` with updater | Low |
|
|
574
|
+
| `GlowDot` | `Dot` with transparent larger `Dot` behind | Low |
|
|
575
|
+
| `ComplexValueTracker` | Two `ValueTracker`s (real, imag) | Low |
|
|
576
|
+
| `axes.get_h_line()` | `axes.get_horizontal_line()` | Medium |
|
|
577
|
+
| `axes.get_v_line()` | `axes.get_vertical_line()` | Medium |
|
|
578
|
+
| `axes.get_graph()` | `axes.plot()` | Medium |
|
|
579
|
+
| `.set_anim_args(rate_func=...)` | Pass `rate_func` to `self.play()` | Low |
|
|
580
|
+
| `VGroup(x for x in items)` | `VGroup(*[x for x in items])` | Medium |
|
|
581
|
+
| `time_span=(0, 1)` in anim | Not available; restructure animations | Low |
|
|
582
|
+
|
|
583
|
+
## Best Practices for Translation
|
|
584
|
+
|
|
585
|
+
1. **Start with imports**: Replace `from manim_imports_ext import *` with `from manim import *`
|
|
586
|
+
2. **Find-replace animations**: `ShowCreation` to `Create` globally
|
|
587
|
+
3. **Find-replace scene classes**: `InteractiveScene` to `Scene`
|
|
588
|
+
4. **Convert CONFIG dicts**: Move to `__init__` parameters
|
|
589
|
+
5. **Fix LaTeX classes**: `Tex(R"...")` to `MathTex(r"...")`, `OldTex` to `MathTex`
|
|
590
|
+
6. **Fix camera access**: `self.frame` to `self.camera.frame` and use proper scene type
|
|
591
|
+
7. **Fix updater patterns**: `f_always` to `add_updater`
|
|
592
|
+
8. **Test incrementally**: Translate one scene at a time, render to verify
|
|
593
|
+
9. **Skip custom mobjects**: Reimplement 3b1b-specific helpers from scratch
|
|
594
|
+
10. **Check coordinate system methods**: Many method names differ slightly
|