jeertmans / manim-slides

Tool for live presentations using manim
https://manim-slides.eertmans.be
MIT License
419 stars 46 forks source link

[BUG] ZoomedScene is not supported in manim-slides #396

Closed semikernel closed 3 months ago

semikernel commented 3 months ago

Description

I want to use ZoomedScene in manim-slides.

https://docs.manim.community/en/stable/reference/manim.scene.zoomed_scene.html

I tried to use:

class ZoomedSlide(Slide, ZoomedScene):
    pass

But it can't render, the terminal output: AttributeError: 'P9' object has no attribute '_current_animation'


╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/cli/render/comman │
│ ds.py:115 in render                                                          │
│                                                                              │
│   112 │   │   │   try:                                                       │
│   113 │   │   │   │   with tempconfig({}):                                   │
│   114 │   │   │   │   │   scene = SceneClass()                               │
│ ❱ 115 │   │   │   │   │   scene.render()                                     │
│   116 │   │   │   except Exception:                                          │
│   117 │   │   │   │   error_console.print_exception()                        │
│   118 │   │   │   │   sys.exit(1)                                            │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim_slides/slide/mani │
│ m.py:93 in render                                                            │
│                                                                              │
│    90 │   │   max_files_cached = config["max_files_cached"]                  │
│    91 │   │   config["max_files_cached"] = float("inf")                      │
│    92 │   │                                                                  │
│ ❱  93 │   │   super().render(*args, **kwargs)                                │
│    94 │   │                                                                  │
│    95 │   │   config["max_files_cached"] = max_files_cached                  │
│    96                                                                        │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/scene/scene.py:22 │
│ 3 in render                                                                  │
│                                                                              │
│    220 │   │   """                                                           │
│    221 │   │   self.setup()                                                  │
│    222 │   │   try:                                                          │
│ ❱  223 │   │   │   self.construct()                                          │
│    224 │   │   except EndSceneEarlyException:                                │
│    225 │   │   │   pass                                                      │
│    226 │   │   except RerunSceneException as e:                              │
│                                                                              │
│ /home/semikernel/Tiktok/ReportSlides/report411.py:804 in construct           │
│                                                                              │
│   801 │   │   dot = Dot().set_color(GREEN)                                   │
│   802 │   │   sq = Circle(fill_opacity=1, radius=0.2).next_to(dot, RIGHT)    │
│   803 │   │   self.add(dot, sq)                                              │
│ ❱ 804 │   │   self.wait(1)                                                   │
│   805 │   │   self.activate_zooming(animate=False)                           │
│   806 │   │   self.wait(1)                                                   │
│   807 │   │   self.play(dot.animate.shift(LEFT * 0.3))                       │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/scene/scene.py:11 │
│ 22 in wait                                                                   │
│                                                                              │
│   1119 │   │   --------                                                      │
│   1120 │   │   :class:`.Wait`, :meth:`.should_mobjects_update`               │
│   1121 │   │   """                                                           │
│ ❱ 1122 │   │   self.play(                                                    │
│   1123 │   │   │   Wait(                                                     │
│   1124 │   │   │   │   run_time=duration,                                    │
│   1125 │   │   │   │   stop_condition=stop_condition,                        │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim_slides/slide/base │
│ .py:263 in play                                                              │
│                                                                              │
│   260 │   def play(self, *args: Any, **kwargs: Any) -> None:                 │
│   261 │   │   """Overload `self.play` and increment animation count."""      │
│   262 │   │   super().play(*args, **kwargs)  # type: ignore[misc]            │
│ ❱ 263 │   │   self._current_animation += 1                                   │
│   264 │                                                                      │
│   265 │   @BaseSlideConfig.wrapper("base_slide_config")                      │
│   266 │   def next_slide(                                                    │
╰──────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'P9' object has no attribute '_current_animation'

Screenshots

No response

Additional information

No response

jeertmans commented 3 months ago

Hello! Can you share a minimal working example here? The error message looks weird, but I don't know what 'P9' is referring to.

semikernel commented 3 months ago

Hello! Can you share a minimal working example here? The error message looks weird, but I don't know what 'P9' is referring to.

P9 is a class ZoomedCameraScene created by me, it doesn't matter what P9 is, because the second code in manim doc can't run, too. I tested that the following code can run in manim-slides:

class ZoomedSlide(Slide, ZoomedScene):
    pass
class UseZoomedScene(ZoomedSlide):
    def construct(self):
        dot = Dot().set_color(GREEN)
        self.add(dot)
        self.wait(1)
        self.activate_zooming(animate=False)
        self.wait(1)
        self.play(dot.animate.shift(LEFT))

However, the following code in manim doc can't run:

class ChangingZoomScale(ZoomedSlide):
    def __init__(self, **kwargs):
        ZoomedScene.__init__(
            self,
            zoom_factor=0.3,
            zoomed_display_height=1,
            zoomed_display_width=3,
            image_frame_stroke_width=20,
            zoomed_camera_config={
                "default_frame_stroke_width": 3,
            },
            **kwargs
        )

    def construct(self):
        dot = Dot().set_color(GREEN)
        sq = Circle(fill_opacity=1, radius=0.2).next_to(dot, RIGHT)
        self.add(dot, sq)
        self.wait(1)
        self.activate_zooming(animate=False)
        self.wait(1)
        self.play(dot.animate.shift(LEFT * 0.3))

        self.play(self.zoomed_camera.frame.animate.scale(4))
        self.play(self.zoomed_camera.frame.animate.shift(0.5 * DOWN))

The terminal prompt outputs:

[04/04/24 17:53:57] INFO     Animation 0 : Using cached     cairo_renderer.py:78
                             data (hash :                                       
                             1172816777_4205520711_22093568                     
                             1)                                                 
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/cli/render/comman │
│ ds.py:115 in render                                                          │
│                                                                              │
│   112 │   │   │   try:                                                       │
│   113 │   │   │   │   with tempconfig({}):                                   │
│   114 │   │   │   │   │   scene = SceneClass()                               │
│ ❱ 115 │   │   │   │   │   scene.render()                                     │
│   116 │   │   │   except Exception:                                          │
│   117 │   │   │   │   error_console.print_exception()                        │
│   118 │   │   │   │   sys.exit(1)                                            │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim_slides/slide/mani │
│ m.py:93 in render                                                            │
│                                                                              │
│    90 │   │   max_files_cached = config["max_files_cached"]                  │
│    91 │   │   config["max_files_cached"] = float("inf")                      │
│    92 │   │                                                                  │
│ ❱  93 │   │   super().render(*args, **kwargs)                                │
│    94 │   │                                                                  │
│    95 │   │   config["max_files_cached"] = max_files_cached                  │
│    96                                                                        │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/scene/scene.py:22 │
│ 3 in render                                                                  │
│                                                                              │
│    220 │   │   """                                                           │
│    221 │   │   self.setup()                                                  │
│    222 │   │   try:                                                          │
│ ❱  223 │   │   │   self.construct()                                          │
│    224 │   │   except EndSceneEarlyException:                                │
│    225 │   │   │   pass                                                      │
│    226 │   │   except RerunSceneException as e:                              │
│                                                                              │
│ /home/semikernel/Tiktok/ReportSlides/report411.py:81 in construct            │
│                                                                              │
│     78 │   │   dot = Dot().set_color(GREEN)                                  │
│     79 │   │   sq = Circle(fill_opacity=1, radius=0.2).next_to(dot, RIGHT)   │
│     80 │   │   self.add(dot, sq)                                             │
│ ❱   81 │   │   self.wait(1)                                                  │
│     82 │   │   self.activate_zooming(animate=False)                          │
│     83 │   │   self.wait(1)                                                  │
│     84 │   │   self.play(dot.animate.shift(LEFT * 0.3))                      │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/scene/scene.py:11 │
│ 22 in wait                                                                   │
│                                                                              │
│   1119 │   │   --------                                                      │
│   1120 │   │   :class:`.Wait`, :meth:`.should_mobjects_update`               │
│   1121 │   │   """                                                           │
│ ❱ 1122 │   │   self.play(                                                    │
│   1123 │   │   │   Wait(                                                     │
│   1124 │   │   │   │   run_time=duration,                                    │
│   1125 │   │   │   │   stop_condition=stop_condition,                        │
│                                                                              │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim_slides/slide/base │
│ .py:263 in play                                                              │
│                                                                              │
│   260 │   def play(self, *args: Any, **kwargs: Any) -> None:                 │
│   261 │   │   """Overload `self.play` and increment animation count."""      │
│   262 │   │   super().play(*args, **kwargs)  # type: ignore[misc]            │
│ ❱ 263 │   │   self._current_animation += 1                                   │
│   264 │                                                                      │
│   265 │   @BaseSlideConfig.wrapper("base_slide_config")                      │
│   266 │   def next_slide(                                                    │
╰──────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'ChangingZoomScale' object has no attribute '_current_animation
jeertmans commented 3 months ago

The error is caused by your __init__ method, because it does not call Slide.__init__.

Just change:

class ChangingZoomScale(ZoomedSlide):
    def __init__(self, **kwargs):
-       ZoomedScene.__init__(
+       ZoomedSlide.__init__(
            self,
            zoom_factor=0.3,
            zoomed_display_height=1,
            zoomed_display_width=3,
            image_frame_stroke_width=20,
            zoomed_camera_config={
                "default_frame_stroke_width": 3,
            },
            **kwargs
        )

and this should work as expected :-)

semikernel commented 3 months ago
ZoomedSlide.__init__

What a nicety point, now it works!

jeertmans commented 3 months ago

Happy I solved your issue :D

Closing this now.