diff --git a/CHANGELOG.md b/CHANGELOG.md index 596db15..24717d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 (unreleased)= ## [Unreleased](https://github.com/jeertmans/manim-slides/compare/v5.4.0...HEAD) +(unreleased-added)= +### Added + +- Added `start_skip_animations` and `stop_skip_animations` methods. + [#523](https://github.com/jeertmans/manim-slides/pull/523) + (v5.4.0)= ## [v5.4.0](https://github.com/jeertmans/manim-slides/compare/v5.3.1...v5.4.0) diff --git a/docs/source/reference/api.md b/docs/source/reference/api.md index 3a70793..25d2ae1 100644 --- a/docs/source/reference/api.md +++ b/docs/source/reference/api.md @@ -18,6 +18,8 @@ use, not the methods used internally when rendering. next_section, next_slide, remove_from_canvas, + start_skip_animations, + stop_skip_animations, wait_time_between_slides, wipe, zoom, diff --git a/manim_slides/slide/base.py b/manim_slides/slide/base.py index cc728de..64f2399 100644 --- a/manim_slides/slide/base.py +++ b/manim_slides/slide/base.py @@ -49,6 +49,7 @@ class BaseSlide: self._start_animation = 0 self._canvas: MutableMapping[str, Mobject] = {} self._wait_time_between_slides = 0.0 + self._skip_animations = False @property @abstractmethod @@ -304,6 +305,11 @@ class BaseSlide: If `manim` is used, this is also passed to `:meth:`Scene.next_section`, which will avoid rendering the corresponding animations. + + .. seealso:: + + :meth:`start_skip_animations` + :meth:`stop_skip_animations` :param loop: If set, next slide will be looping. :param auto_next: @@ -463,6 +469,9 @@ class BaseSlide: self._current_slide += 1 + if self._skip_animations: + base_slide_config.skip_animations = True + self._base_slide_config = base_slide_config self._start_animation = self._current_animation @@ -572,6 +581,24 @@ class BaseSlide: f"Slide '{scene_name}' configuration written in '{slide_path.absolute()}'" ) + def start_skip_animations(self) -> None: + """ + Start skipping animations. + + This automatically applies ``skip_animations=True`` + to all subsequent calls to :meth:`next_slide`. + + This is useful when you want to skip animations from multiple slides in a row, + without having to manually set ``skip_animations=True``. + """ + self._skip_animations = True + + def stop_skip_animations(self) -> None: + """ + Stop skipping animations. + """ + self._skip_animations = False + def wipe( self, *args: Any, diff --git a/tests/test_base_slide.py b/tests/test_base_slide.py index 7119fbc..6ece844 100644 --- a/tests/test_base_slide.py +++ b/tests/test_base_slide.py @@ -86,6 +86,15 @@ class TestBaseSlide: assert base_slide.wait_time_between_slides == 0.0 + def test_skip_animations(self, base_slide: BaseSlide) -> None: + assert base_slide._skip_animations == False + + def test_start_and_stop_skip_animations(self, base_slide: BaseSlide) -> None: + base_slide.start_skip_animations() + assert base_slide._skip_animations == True + base_slide.stop_skip_animations() + assert base_slide._skip_animations == False + def test_play(self) -> None: pass # This method should be tested in test_slide.py diff --git a/tests/test_slide.py b/tests/test_slide.py index 1a6ccf6..c4baeba 100644 --- a/tests/test_slide.py +++ b/tests/test_slide.py @@ -527,9 +527,25 @@ class TestSlide: assert not self._base_slide_config.skip_animations self.play(GrowFromCenter(square)) + class Baz(CESlide): + def construct(self) -> None: + circle = Circle(color=BLUE) + self.play(GrowFromCenter(circle)) + assert not self._base_slide_config.skip_animations + self.start_skip_animations() + self.next_slide() + square = Square(color=BLUE) + self.play(GrowFromCenter(square)) + assert self._base_slide_config.skip_animations + self.next_slide() + assert self._base_slide_config.skip_animations + self.play(GrowFromCenter(square)) + self.stop_skip_animations() + with tmp_cwd() as tmp_dir: init_slide(Foo).render() init_slide(Bar).render() + init_slide(Baz).render() slides_folder = Path(tmp_dir) / "slides" @@ -547,6 +563,12 @@ class TestSlide: assert len(config.slides) == 3 + slide_file = slides_folder / "Baz.json" + + config = PresentationConfig.from_file(slide_file) + + assert len(config.slides) == 1 + def test_canvas(self) -> None: @assert_constructs class _(CESlide):