mirror of
https://github.com/jeertmans/manim-slides.git
synced 2025-07-17 16:28:21 +08:00
feat(lib): add return_animation
option (#331)
* feat(lib): add `return_animation` option Allow to return animation instead of playing it. * fix(lib): docs issue * fix(ci): build with Python 3.10
This commit is contained in:
2
.github/workflows/pages.yml
vendored
2
.github/workflows/pages.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
|||||||
- name: Install Python
|
- name: Install Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.10'
|
||||||
cache: poetry
|
cache: poetry
|
||||||
- name: Setup Pages
|
- name: Setup Pages
|
||||||
uses: actions/configure-pages@v3
|
uses: actions/configure-pages@v3
|
||||||
|
@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
This is somewhat a **breaking change**, but changes to the CLI
|
This is somewhat a **breaking change**, but changes to the CLI
|
||||||
API are not considered to be very important.
|
API are not considered to be very important.
|
||||||
[#325](https://github.com/jeertmans/manim-slides/pull/325)
|
[#325](https://github.com/jeertmans/manim-slides/pull/325)
|
||||||
|
- Added `return_animation` option to slide animations `self.wipe`
|
||||||
|
and `self.zoom`.
|
||||||
|
[#331](https://github.com/jeertmans/manim-slides/pull/331)
|
||||||
|
|
||||||
(v5.1-modified)=
|
(v5.1-modified)=
|
||||||
### Modified
|
### Modified
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
# For the full list of built-in configuration values, see the documentation:
|
# For the full list of built-in configuration values, see the documentation:
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
assert sys.version_info >= (3, 10), "Building docs requires Python 3.10"
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
__all__ = ["BaseSlide"]
|
__all__ = ["BaseSlide"]
|
||||||
|
|
||||||
import platform
|
import platform
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, List, MutableMapping, Optional, Sequence, Tuple, ValuesView
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
|
Any,
|
||||||
|
MutableMapping,
|
||||||
|
Sequence,
|
||||||
|
ValuesView,
|
||||||
|
)
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
@ -14,6 +22,9 @@ from ..logger import logger
|
|||||||
from ..utils import concatenate_video_files, merge_basenames, reverse_video_file
|
from ..utils import concatenate_video_files, merge_basenames, reverse_video_file
|
||||||
from . import MANIM
|
from . import MANIM
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .animation import Wipe, Zoom
|
||||||
|
|
||||||
if MANIM:
|
if MANIM:
|
||||||
from manim.mobject.mobject import Mobject
|
from manim.mobject.mobject import Mobject
|
||||||
else:
|
else:
|
||||||
@ -28,7 +39,7 @@ class BaseSlide:
|
|||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._output_folder: Path = output_folder
|
self._output_folder: Path = output_folder
|
||||||
self._slides: List[PreSlideConfig] = []
|
self._slides: list[PreSlideConfig] = []
|
||||||
self._base_slide_config: BaseSlideConfig = BaseSlideConfig()
|
self._base_slide_config: BaseSlideConfig = BaseSlideConfig()
|
||||||
self._current_slide = 1
|
self._current_slide = 1
|
||||||
self._current_animation = 0
|
self._current_animation = 0
|
||||||
@ -61,13 +72,13 @@ class BaseSlide:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _resolution(self) -> Tuple[int, int]:
|
def _resolution(self) -> tuple[int, int]:
|
||||||
"""Return the scene's resolution used during rendering."""
|
"""Return the scene's resolution used during rendering."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _partial_movie_files(self) -> List[Path]:
|
def _partial_movie_files(self) -> list[Path]:
|
||||||
"""Return a list of partial movie files, a.k.a animations."""
|
"""Return a list of partial movie files, a.k.a animations."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -85,7 +96,7 @@ class BaseSlide:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _start_at_animation_number(self) -> Optional[int]:
|
def _start_at_animation_number(self) -> int | None:
|
||||||
"""If set, return the animation number at which rendering start."""
|
"""If set, return the animation number at which rendering start."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@ -453,7 +464,7 @@ class BaseSlide:
|
|||||||
|
|
||||||
scene_files_folder.mkdir(parents=True, exist_ok=True)
|
scene_files_folder.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
files: List[Path] = self._partial_movie_files
|
files: list[Path] = self._partial_movie_files
|
||||||
|
|
||||||
# We must filter slides that end before the animation offset
|
# We must filter slides that end before the animation offset
|
||||||
if offset := self._start_at_animation_number:
|
if offset := self._start_at_animation_number:
|
||||||
@ -464,7 +475,7 @@ class BaseSlide:
|
|||||||
slide.start_animation = max(0, slide.start_animation - offset)
|
slide.start_animation = max(0, slide.start_animation - offset)
|
||||||
slide.end_animation -= offset
|
slide.end_animation -= offset
|
||||||
|
|
||||||
slides: List[SlideConfig] = []
|
slides: list[SlideConfig] = []
|
||||||
|
|
||||||
for pre_slide_config in tqdm(
|
for pre_slide_config in tqdm(
|
||||||
self._slides,
|
self._slides,
|
||||||
@ -513,8 +524,9 @@ class BaseSlide:
|
|||||||
self,
|
self,
|
||||||
*args: Any,
|
*args: Any,
|
||||||
direction: np.ndarray = LEFT,
|
direction: np.ndarray = LEFT,
|
||||||
|
return_animation: bool = False,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> Wipe | None:
|
||||||
"""
|
"""
|
||||||
Play a wipe animation that will shift all the current objects outside of the
|
Play a wipe animation that will shift all the current objects outside of the
|
||||||
current scene's scope, and all the future objects inside.
|
current scene's scope, and all the future objects inside.
|
||||||
@ -522,6 +534,8 @@ class BaseSlide:
|
|||||||
:param args: Positional arguments passed to
|
:param args: Positional arguments passed to
|
||||||
:class:`Wipe<manim_slides.slide.animation.Wipe>`.
|
:class:`Wipe<manim_slides.slide.animation.Wipe>`.
|
||||||
:param direction: The wipe direction, that will be scaled by the scene size.
|
:param direction: The wipe direction, that will be scaled by the scene size.
|
||||||
|
:param return_animation: If set, return the animation instead of
|
||||||
|
playing it. This is useful to combine multiple animations with this one.
|
||||||
:param kwargs: Keyword arguments passed to
|
:param kwargs: Keyword arguments passed to
|
||||||
:class:`Wipe<manim_slides.slide.animation.Wipe>`.
|
:class:`Wipe<manim_slides.slide.animation.Wipe>`.
|
||||||
|
|
||||||
@ -548,7 +562,13 @@ class BaseSlide:
|
|||||||
self.wipe(Group(square, text), beautiful, direction=UP)
|
self.wipe(Group(square, text), beautiful, direction=UP)
|
||||||
self.next_slide()
|
self.next_slide()
|
||||||
|
|
||||||
self.wipe(beautiful, circle, direction=DOWN + RIGHT)
|
anim = self.wipe(
|
||||||
|
beautiful,
|
||||||
|
circle,
|
||||||
|
direction=DOWN + RIGHT,
|
||||||
|
return_animation=True
|
||||||
|
)
|
||||||
|
self.play(anim)
|
||||||
"""
|
"""
|
||||||
from .animation import Wipe
|
from .animation import Wipe
|
||||||
|
|
||||||
@ -563,13 +583,18 @@ class BaseSlide:
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if return_animation:
|
||||||
|
return animation
|
||||||
|
|
||||||
self.play(animation)
|
self.play(animation)
|
||||||
|
return None
|
||||||
|
|
||||||
def zoom(
|
def zoom(
|
||||||
self,
|
self,
|
||||||
*args: Any,
|
*args: Any,
|
||||||
|
return_animation: bool = False,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> Zoom | None:
|
||||||
"""
|
"""
|
||||||
Play a zoom animation that will fade out all the current objects, and fade in
|
Play a zoom animation that will fade out all the current objects, and fade in
|
||||||
all the future objects. Objects are faded in a direction that goes towards the
|
all the future objects. Objects are faded in a direction that goes towards the
|
||||||
@ -577,6 +602,8 @@ class BaseSlide:
|
|||||||
|
|
||||||
:param args: Positional arguments passed to
|
:param args: Positional arguments passed to
|
||||||
:class:`Zoom<manim_slides.slide.animation.Zoom>`.
|
:class:`Zoom<manim_slides.slide.animation.Zoom>`.
|
||||||
|
:param return_animation: If set, return the animation instead of
|
||||||
|
playing it. This is useful to combine multiple animations with this one.
|
||||||
:param kwargs: Keyword arguments passed to
|
:param kwargs: Keyword arguments passed to
|
||||||
:class:`Zoom<manim_slides.slide.animation.Zoom>`.
|
:class:`Zoom<manim_slides.slide.animation.Zoom>`.
|
||||||
|
|
||||||
@ -598,10 +625,21 @@ class BaseSlide:
|
|||||||
self.zoom(circle, square)
|
self.zoom(circle, square)
|
||||||
self.next_slide()
|
self.next_slide()
|
||||||
|
|
||||||
self.zoom(square, circle, out=True, scale=10.0)
|
anim = self.zoom(
|
||||||
|
square,
|
||||||
|
circle,
|
||||||
|
out=True,
|
||||||
|
scale=10.0,
|
||||||
|
return_animation=True
|
||||||
|
)
|
||||||
|
self.play(anim)
|
||||||
"""
|
"""
|
||||||
from .animation import Zoom
|
from .animation import Zoom
|
||||||
|
|
||||||
animation = Zoom(*args, **kwargs)
|
animation = Zoom(*args, **kwargs)
|
||||||
|
|
||||||
|
if return_animation:
|
||||||
|
return animation
|
||||||
|
|
||||||
self.play(animation)
|
self.play(animation)
|
||||||
|
return None
|
||||||
|
Reference in New Issue
Block a user