Skip to content

Commit 1da3492

Browse files
chore(ci): test builds on multiple oses (#7)
* chore(ci): test builds on multiple oses * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: add tqdm to setup * chore(ci): test builds on multiple oses * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: install deps in two steps * fix(bug): allows shape to be 2 or 3 dims * release new version * chore(ci): test builds on multiple oses * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * chore(ci): test builds on multiple oses * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: install deps in two steps * fix: deps string * fix: ci * fix: single quote strings * fix: choco install manimce * Add pyopengl * Update test_examples.yml * fix: custom 3d example for manimgl * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: virtual frame buffer * fix: add ffmpeg dep * feat(cli): add skip-all option for testing * chore(lint): black fmt * fix: typo in deps * fix: python -m pip install * fix: typo * Update test_examples.yml * fix: try fix * fix: pip install --user * pip install -e * only on windows * fix: tmp fix * fix: typo in int parsing * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update test_examples.yml * Update __version__.py Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 0d97bda commit 1da3492

File tree

5 files changed

+215
-34
lines changed

5 files changed

+215
-34
lines changed

.github/workflows/test_examples.yml

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
on:
2+
pull_request:
3+
paths:
4+
- '**.py'
5+
workflow_dispatch:
6+
7+
name: Test Examples
8+
9+
jobs:
10+
build-examples:
11+
strategy:
12+
matrix:
13+
manim: [manim, manimgl]
14+
os: [macos-latest, ubuntu-latest, windows-latest]
15+
pyversion: ['3.7', '3.8', '3.9', '3.10']
16+
exclude:
17+
# excludes manimgl on Windows because if throws errors
18+
# related to OpenGL, which seems hard to fix:
19+
# Your graphics drivers do not support OpenGL 2.0.
20+
- os: windows-latest
21+
manim: manimgl
22+
# manimgl actually requires Python >= 3.8, see:
23+
# https://github.com/3b1b/manim/issues/1808
24+
- manim: manimgl
25+
pyversion: '3.7'
26+
# We only test Python 3.10 on Windows and MacOS
27+
- os: windows-latest
28+
pyversion: '3.7'
29+
- os: windows-latest
30+
pyversion: '3.8'
31+
- os: windows-latest
32+
pyversion: '3.9'
33+
- os: macos-latest
34+
pyversion: '3.7'
35+
- os: macos-latest
36+
pyversion: '3.8'
37+
- os: macos-latest
38+
pyversion: '3.9'
39+
runs-on: ${{ matrix.os }}
40+
steps:
41+
- name: Checkout repository
42+
uses: actions/checkout@v3
43+
- name: Install Python
44+
uses: actions/setup-python@v4
45+
with:
46+
python-version: ${{ matrix.pyversion }}
47+
- name: Append to Path on MacOS and Ubuntu
48+
if: matrix.os == 'macos-latest' || matrix.os == 'ubuntu-latest'
49+
run: echo "${HOME}/.local/bin" >> $GITHUB_PATH
50+
- name: Append to Path on Windows
51+
if: matrix.os == 'windows-latest'
52+
run: echo "${HOME}/.local/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
53+
- name: Install MacOS dependencies (manim only)
54+
if: matrix.os == 'macos-latest' && matrix.manim == 'manim'
55+
run: brew install py3cairo
56+
- name: Install MacOS dependencies
57+
if: matrix.os == 'macos-latest'
58+
run: brew install ffmpeg
59+
- name: Install Ubuntu dependencies
60+
if: matrix.os == 'ubuntu-latest'
61+
run: sudo apt install libcairo2-dev libpango1.0-dev ffmpeg freeglut3-dev xvfb
62+
- name: Install Windows dependencies
63+
if: matrix.os == 'windows-latest'
64+
run: choco install ffmpeg
65+
- name: Install manim on MacOs
66+
if: matrix.manim == 'manim' && matrix.os == 'macos-latest'
67+
run: pip3 install --user manim
68+
- name: Install manim on Ubuntu and Windows
69+
if: matrix.manim == 'manim' && (matrix.os == 'ubuntu-latest' || matrix.os == 'windows-latest')
70+
run: python -m pip install --user manim
71+
- name: Install manimgl on MacOs
72+
if: matrix.manim == 'manimgl' && matrix.os == 'macos-latest'
73+
run: pip3 install --user manimgl
74+
- name: Install manimgl on Ubuntu and Windows
75+
if: matrix.manim == 'manimgl' && matrix.os != 'macos-latest'
76+
run: python -m pip install --user manimgl
77+
- name: Install manim-slides on MacOS
78+
if: matrix.os == 'macos-latest'
79+
run: pip3 install --user .
80+
- name: Install manim-slides on Ubuntu
81+
if: matrix.os == 'ubuntu-latest'
82+
run: xvfb-run -a -s "-screen 0 1400x900x24" python -m pip install --user .
83+
- name: Install manim-slides on Windows
84+
if: matrix.os == 'windows-latest'
85+
run: pip3 install -e .
86+
- name: Build slides with manim
87+
if: matrix.manim == 'manim'
88+
run: python -m manim -ql example.py Example ThreeDExample
89+
- name: Build slides with manimgl on Ubuntu
90+
if: matrix.manim == 'manimgl' && matrix.os == 'ubuntu-latest'
91+
run: xvfb-run -a -s "-screen 0 1400x900x24" manim-render -l example.py Example ThreeDExample
92+
- name: Build slides with manimgl on MacOS or Windows
93+
if: matrix.manim == 'manimgl' && (matrix.os == 'macos-latest' || matrix.os == 'windows-latest')
94+
run: manimgl -l example.py Example ThreeDExample
95+
- name: Test slides on Ubuntu
96+
if: matrix.os == 'ubuntu-latest'
97+
run: xvfb-run -a -s "-screen 0 1400x900x24" manim-slides Example ThreeDExample --skip-all
98+
- name: Test slides on MacOS or Windows
99+
if: matrix.os == 'macos-latest' || matrix.os == 'windows-latest'
100+
run: manim-slides Example ThreeDExample --skip-all

example.py

+87-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
# If you want to use manimgl, uncomment change
2-
# manim to manimlib
3-
from manimlib import *
1+
import sys
2+
3+
if "manim" in sys.modules:
4+
from manim import *
5+
6+
MANIMGL = False
7+
elif "manimlib" in sys.modules:
8+
from manimlib import *
9+
10+
MANIMGL = True
11+
else:
12+
raise ImportError("This script must be run with either `manim` or `manimgl`")
413

514
from manim_slides import Slide, ThreeDSlide
615

@@ -31,37 +40,88 @@ def construct(self):
3140
self.play(dot.animate.move_to(ORIGIN))
3241

3342

34-
class ThreeDExample(ThreeDSlide):
35-
def construct(self):
36-
axes = ThreeDAxes()
37-
circle = Circle(radius=3, color=BLUE)
38-
dot = Dot(color=RED)
43+
# For ThreeDExample, things are different
3944

40-
self.add(axes)
45+
if not MANIMGL:
4146

42-
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
47+
class ThreeDExample(ThreeDSlide):
48+
def construct(self):
49+
axes = ThreeDAxes()
50+
circle = Circle(radius=3, color=BLUE)
51+
dot = Dot(color=RED)
4352

44-
self.play(GrowFromCenter(circle))
45-
self.begin_ambient_camera_rotation(rate=75 * DEGREES / 4)
53+
self.add(axes)
4654

47-
self.pause()
55+
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)
4856

49-
self.start_loop()
50-
self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
51-
self.end_loop()
57+
self.play(GrowFromCenter(circle))
58+
self.begin_ambient_camera_rotation(rate=75 * DEGREES / 4)
5259

53-
self.stop_ambient_camera_rotation()
54-
self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)
60+
self.pause()
5561

56-
self.play(dot.animate.move_to(ORIGIN))
57-
self.pause()
62+
self.start_loop()
63+
self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
64+
self.end_loop()
5865

59-
self.play(dot.animate.move_to(RIGHT * 3))
60-
self.pause()
66+
self.stop_ambient_camera_rotation()
67+
self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)
6168

62-
self.start_loop()
63-
self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
64-
self.end_loop()
69+
self.play(dot.animate.move_to(ORIGIN))
70+
self.pause()
6571

66-
# Each slide MUST end with an animation (a self.wait is considered an animation)
67-
self.play(dot.animate.move_to(ORIGIN))
72+
self.play(dot.animate.move_to(RIGHT * 3))
73+
self.pause()
74+
75+
self.start_loop()
76+
self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
77+
self.end_loop()
78+
79+
# Each slide MUST end with an animation (a self.wait is considered an animation)
80+
self.play(dot.animate.move_to(ORIGIN))
81+
82+
else:
83+
# WARNING: 3b1b's manim change how ThreeDScene work,
84+
# this is why things have to be managed differently.
85+
class ThreeDExample(Slide):
86+
CONFIG = {
87+
"camera_class": ThreeDCamera,
88+
}
89+
90+
def construct(self):
91+
axes = ThreeDAxes()
92+
circle = Circle(radius=3, color=BLUE)
93+
dot = Dot(color=RED)
94+
95+
self.add(axes)
96+
97+
frame = self.camera.frame
98+
frame.set_euler_angles(
99+
theta=30 * DEGREES,
100+
phi=75 * DEGREES,
101+
gamma=0,
102+
)
103+
104+
self.play(GrowFromCenter(circle))
105+
updater = lambda m, dt: m.increment_theta((75 * DEGREES / 4) * dt)
106+
frame.add_updater(updater)
107+
108+
self.pause()
109+
110+
self.start_loop()
111+
self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
112+
self.end_loop()
113+
114+
frame.remove_updater(updater)
115+
self.play(frame.animate.set_theta(30 * DEGREES))
116+
self.play(dot.animate.move_to(ORIGIN))
117+
self.pause()
118+
119+
self.play(dot.animate.move_to(RIGHT * 3))
120+
self.pause()
121+
122+
self.start_loop()
123+
self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
124+
self.end_loop()
125+
126+
# Each slide MUST end with an animation (a self.wait is considered an animation)
127+
self.play(dot.animate.move_to(ORIGIN))

manim_slides/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.2.2"
1+
__version__ = "3.2.3"

manim_slides/present.py

+26-5
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,18 @@ def update_state(self, state):
174174

175175

176176
class Display:
177-
def __init__(self, presentations, config, start_paused=False, fullscreen=False):
177+
def __init__(
178+
self,
179+
presentations,
180+
config,
181+
start_paused=False,
182+
fullscreen=False,
183+
skip_all=False,
184+
):
178185
self.presentations = presentations
179186
self.start_paused = start_paused
180187
self.config = config
188+
self.skip_all = skip_all
181189

182190
self.state = State.PLAYING
183191
self.lastframe = None
@@ -206,7 +214,7 @@ def resize_frame_to_screen(self, frame: np.ndarray):
206214

207215
scale = min(scale_height, scale_width)
208216

209-
return cv2.resize(frame, (int(scale * frame_height, scale * frame_width)))
217+
return cv2.resize(frame, (int(scale * frame_height), int(scale * frame_width)))
210218

211219
@property
212220
def current_presentation(self):
@@ -293,7 +301,9 @@ def handle_key(self):
293301
):
294302
self.current_presentation.next()
295303
self.state = State.PLAYING
296-
elif self.state == State.PLAYING and self.config.CONTINUE.match(key):
304+
elif (
305+
self.state == State.PLAYING and self.config.CONTINUE.match(key)
306+
) or self.skip_all:
297307
self.current_presentation.next()
298308
elif self.config.BACK.match(key):
299309
if self.current_presentation.current_slide_i == 0:
@@ -356,8 +366,15 @@ def _list_scenes(folder):
356366
is_flag=True,
357367
help="Show the next animation first frame as last frame (hack).",
358368
)
369+
@click.option(
370+
"--skip-all",
371+
is_flag=True,
372+
help="Skip all slides, useful the test if slides are working.",
373+
)
359374
@click.help_option("-h", "--help")
360-
def present(scenes, config_path, folder, start_paused, fullscreen, last_frame_next):
375+
def present(
376+
scenes, config_path, folder, start_paused, fullscreen, last_frame_next, skip_all
377+
):
361378
"""Present the different scenes."""
362379

363380
if len(scenes) == 0:
@@ -411,6 +428,10 @@ def value_proc(value: str):
411428
config = Config()
412429

413430
display = Display(
414-
presentations, config=config, start_paused=start_paused, fullscreen=fullscreen
431+
presentations,
432+
config=config,
433+
start_paused=start_paused,
434+
fullscreen=fullscreen,
435+
skip_all=skip_all,
415436
)
416437
display.run()

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"numpy>=1.19.3",
3333
"pydantic>=1.9.1",
3434
"opencv-python>=4.6",
35-
"tqdm",
35+
"tqdm>=4.62.3",
3636
],
3737
classifiers=[
3838
"Programming Language :: Python :: 3",

0 commit comments

Comments
 (0)