Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2af0403
refactor(lib): change how manim API is imported
jeertmans Oct 13, 2023
e0fdac9
chore(lib): delete old files
jeertmans Oct 13, 2023
01aca2f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 13, 2023
5ebb61c
Merge remote-tracking branch 'origin/refactor-manim' into refactor-manim
jeertmans Oct 13, 2023
f3ff76e
wip: moving all commands
jeertmans Oct 13, 2023
06ff18f
adding animations
jeertmans Oct 13, 2023
9355e3d
fix tests
jeertmans Oct 13, 2023
2211ac6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 13, 2023
dd57527
fix mypy
jeertmans Oct 13, 2023
effcc75
fixes
jeertmans Oct 13, 2023
418f1f7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 13, 2023
f5f60e7
trying to fix docs
jeertmans Oct 14, 2023
d4a6148
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 14, 2023
1b1d6c5
wip: docs
jeertmans Oct 16, 2023
c803d67
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2023
bccff71
make it work
jeertmans Oct 16, 2023
036a796
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2023
2c3e5cc
wip test
jeertmans Oct 16, 2023
927a489
Merge remote-tracking branch 'origin/refactor-manim' into refactor-manim
jeertmans Oct 16, 2023
fb97409
tests are working
jeertmans Oct 16, 2023
946cb11
improving docs
jeertmans Oct 16, 2023
aa8205a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2023
85ff07e
fix index
jeertmans Oct 16, 2023
b79da53
docs: nicer shift
jeertmans Oct 16, 2023
6c14ee2
docs: nicer quickstart example
jeertmans Oct 16, 2023
95f84ef
fix tests
jeertmans Oct 17, 2023
353a7f4
change tests
jeertmans Oct 17, 2023
7b37c2d
move coverage to test workflow
jeertmans Oct 17, 2023
b182e72
fix(tests): remove resolve
jeertmans Oct 17, 2023
ffe8322
strict resolve
jeertmans Oct 17, 2023
90a2909
change local path test
jeertmans Oct 17, 2023
4c1df69
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2023
f8978c2
documented changes
jeertmans Oct 17, 2023
489ea5b
Merge remote-tracking branch 'origin/refactor-manim' into refactor-manim
jeertmans Oct 17, 2023
c010971
cleanup docs
jeertmans Oct 17, 2023
4d166d5
cleanup files
jeertmans Oct 17, 2023
a767aef
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2023
9300811
fix(ci): set type
jeertmans Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip: docs
  • Loading branch information
jeertmans committed Oct 16, 2023
commit 1b1d6c57329de4afc01aa259a18fa23764f46c20
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
templates_path = ["_templates"]
exclude_patterns = []

# Removes the 'package.module' part from package.module.Class
add_module_names = False

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
Expand Down
35 changes: 8 additions & 27 deletions docs/source/reference/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,26 @@

Contents of `example.py`.

Do not forget to import Manim Slides and Manim or ManimGL:
Do not forget to import Manim Slides and Manim[^1]:

```python
from manim import *
from manim_slides import Slide, ThreeDSlide
```

or

```python
from manimlib import *
from manim_slides import Slide, ThreeDSlide
```

Then, each presentation, named `SCENE`, was generated with those two commands:

```bash
manim example.py SCENE # or manimgl example SCENE
manim example.py SCENE
manim-slides convert SCENE scene.html -ccontrols=true
```

where `-ccontrols=true` indicates that we want to display the blue navigation arrows.

[^1]: While Manim Slides is compatible with ManimGL, writing scenes that both
render with Manim and ManimGL has become very hard, so the examples below
are only tested to work with Manim.

## Basic Example

Basic example from quickstart.
Expand All @@ -42,10 +39,7 @@ Basic example from quickstart.

## 3D Example

Example using 3D camera. As Manim and ManimGL handle 3D differently,
definitions are slightly different.

### With Manim
Example using 3D camera.

```{eval-rst}
.. manim-slides:: ../../../example.py:ThreeDExample
Expand All @@ -55,20 +49,7 @@ definitions are slightly different.
.. literalinclude:: ../../../example.py
:language: python
:linenos:
:dedent: 4
:start-after: [manim-3d]
:end-before: [manim-3d]
```

### With ManimGL

```{eval-rst}
.. literalinclude:: ../../../example.py
:language: python
:linenos:
:dedent: 4
:start-after: [manimgl-3d]
:end-before: [manimgl-3d]
:pyobject: ThreeDExample
```

## Subclass Custom Scenes
Expand Down
119 changes: 31 additions & 88 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# flake8: noqa: F403, F405
# type: ignore

"""
Examples of Slides generated with Manim and Manim Slides.

The following examples are most likely not going to work with ManimGL,
but Manim Slides still provides support for ManimGL, and should be fully
compatible with it.
"""
from manim import *
from manim_slides import Slide, ThreeDSlide
from manim_slides.slide import MANIM, MANIMGL

if MANIM:
from manim import *
elif MANIMGL:
from manimlib import *


class BasicExample(Slide):
Expand Down Expand Up @@ -258,94 +259,36 @@ def construct(self):

self.play(Transform(square, learn_more_text))

class ThreeDExample(ThreeDSlide):
def construct(self):
axes = ThreeDAxes()
circle = Circle(radius=3, color=BLUE)
dot = Dot(color=RED)

# For ThreeDExample, things are different

if not MANIMGL:
# [manim-3d]
class ThreeDExample(ThreeDSlide):
def construct(self):
axes = ThreeDAxes()
circle = Circle(radius=3, color=BLUE)
dot = Dot(color=RED)

self.add(axes)

self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)

self.play(GrowFromCenter(circle))
self.begin_ambient_camera_rotation(rate=75 * DEGREES / 4)

self.next_slide()

self.start_loop()
self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
self.end_loop()

self.stop_ambient_camera_rotation()
self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)

self.play(dot.animate.move_to(ORIGIN))
self.next_slide()

self.play(dot.animate.move_to(RIGHT * 3))
self.next_slide()

self.start_loop()
self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
self.end_loop()

self.play(dot.animate.move_to(ORIGIN))

# [manim-3d]
else:
# [manimgl-3d]
# WARNING: 3b1b's manim change how ThreeDScene work,
# this is why things have to be managed differently.
class ThreeDExample(Slide):
CONFIG = {
"camera_class": ThreeDCamera,
}

def construct(self):
axes = ThreeDAxes()
circle = Circle(radius=3, color=BLUE)
dot = Dot(color=RED)

self.add(axes)

frame = self.camera.frame
frame.set_euler_angles(
theta=30 * DEGREES,
phi=75 * DEGREES,
gamma=0,
)

self.play(GrowFromCenter(circle))
self.add(axes)

def updater(m, dt):
return m.increment_theta((75 * DEGREES / 4) * dt)
self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)

frame.add_updater(updater)
self.play(GrowFromCenter(circle))
self.begin_ambient_camera_rotation(rate=75 * DEGREES / 4)

self.next_slide()
self.next_slide()

self.start_loop()
self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
self.end_loop()
self.start_loop()
self.play(MoveAlongPath(dot, circle), run_time=4, rate_func=linear)
self.end_loop()

frame.remove_updater(updater)
self.play(frame.animate.set_theta(30 * DEGREES))
self.play(dot.animate.move_to(ORIGIN))
self.next_slide()
self.stop_ambient_camera_rotation()
self.move_camera(phi=75 * DEGREES, theta=30 * DEGREES)

self.play(dot.animate.move_to(RIGHT * 3))
self.next_slide()
self.play(dot.animate.move_to(ORIGIN))
self.next_slide()

self.start_loop()
self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
self.end_loop()
self.play(dot.animate.move_to(RIGHT * 3))
self.next_slide()

self.play(dot.animate.move_to(ORIGIN))
self.start_loop()
self.play(MoveAlongPath(dot, circle), run_time=2, rate_func=linear)
self.end_loop()

# [manimgl-3d]
self.play(dot.animate.move_to(ORIGIN))
4 changes: 3 additions & 1 deletion manim_slides/slide/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ def __init__(self) -> None:
raise ManimApiNotFoundError from e
elif MANIMGL:
try:
from .manimgl import Slide, ThreeDSlide
from .manimlib import Slide, ThreeDSlide
except ImportError as e:
raise ManimApiNotFoundError from e
else:
raise ManimApiNotFoundError
21 changes: 12 additions & 9 deletions manim_slides/slide/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
Sequence,
Tuple,
ValuesView,
Protocol
)

import numpy as np
Expand All @@ -26,15 +27,17 @@
Mobject = Any


class Base(ABC):
_output_folder: Path = FOLDER_PATH
_slides: List[PreSlideConfig] = []
_current_slide = 1
_current_animation = 0
_loop_start_animation: Optional[int] = None
_pause_start_animation = 0
_canvas: MutableMapping[str, Mobject] = {}
_wait_time_between_slides = 0.0
class BaseSlide:
def __init__(self, *args: Any, output_folder: Path = FOLDER_PATH, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self._output_folder: Path = output_folder
self._slides: List[PreSlideConfig] = []
self._current_slide = 1
self._current_animation = 0
self._loop_start_animation: Optional[int] = None
self._pause_start_animation = 0
self._canvas: MutableMapping[str, Mobject] = {}
self._wait_time_between_slides = 0.0

@property
def _ffmpeg_bin(self) -> Path:
Expand Down
25 changes: 10 additions & 15 deletions manim_slides/slide/manim.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

from manim import Scene, ThreeDScene, config

from .base import Base
from .base import BaseSlide


class Slide(Base, Scene): # type: ignore[misc]
class Slide(BaseSlide, Scene): # type: ignore[misc]
"""Inherits from :class:`Scene<manim.scene.scene.Scene>` and provide necessary tools
for slides rendering."""

Expand Down Expand Up @@ -110,20 +109,16 @@ def construct(self):
bye = Text("Bye!")

self.start_loop()
self.play(
self.wipe(
self.mobjects_without_canvas,
[bye],
direction=UP
)
self.wipe(
self.mobjects_without_canvas,
[bye],
direction=UP
)
self.wait(.5)
self.play(
self.wipe(
self.mobjects_without_canvas,
[title, sphere],
direction=DOWN
)
self.wipe(
self.mobjects_without_canvas,
[title, sphere],
direction=DOWN
)
self.wait(.5)
self.end_loop()
Expand Down
4 changes: 2 additions & 2 deletions manim_slides/slide/manimgl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from manimlib import Scene, ThreeDCamera
from manimlib.utils.file_ops import get_sorted_integer_files

from .base import Base
from .base import BaseSlide


class Slide(Base, Scene): # type: ignore[misc]
class Slide(BaseSlide, Scene): # type: ignore[misc]
def __init__(self, *args: Any, **kwargs: Any) -> None:
Path("videos").mkdir(exist_ok=True)
kwargs["file_writer_config"].update(
Expand Down
12 changes: 12 additions & 0 deletions tests/test_slide.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from manim_slides.config import PresentationConfig
from manim_slides.slide.manim import Slide
from manim_slides.defaults import FOLDER_PATH


@click.command(
Expand Down Expand Up @@ -79,6 +80,17 @@ def test_render_basic_examples(


class TestSlide:
@assert_construct
class TestDefaultProperties(Slide):
def construct(self) -> None:
assert self._output_folder == FOLDER_PATH
assert len(self._slides) == 0
assert self._current_slide == 1
assert self._loop_start_animation is None
assert self._pause_start_animation == 0
assert len(self._canvas) == 0
assert self._wait_time_between_slides == 0.0

@assert_construct
class TestLoop(Slide):
def construct(self) -> None:
Expand Down