jeertmans / manim-slides

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

[BUG] 'OpenGLCamera' object has no attribute 'background_color' when rendering using manim.opengl #431

Closed semikernel closed 1 week ago

semikernel commented 1 month ago

Description

Hi, there! I have found that the newest V5.1.7 manim-slides can't render manim.opengl scene. The mwe is shown here:

from manim import *
from manim.opengl import *
from manim_slides import Slide, ThreeDSlide
config.renderer = "opengl"

class Test(ThreeDSlide):
    def construct(self):
        cir = Circle()
        self.play(Create(cir))
        self.wait()

The terminal then outputs:

[05/17/24 19:26:03] INFO     Animation 0 : Partial movie file written in                             scene_file_writer.py:527
                             '/home/semikernel/Tiktok/Projects/OneMonthPlan/media/videos/gaza/1920p6                         
                             0/partial_movie_files/Test/2702378517_2531373006_223132457.mp4'                                 
[05/17/24 19:26:04] INFO     Animation 1 : Partial movie file written in                             scene_file_writer.py:527
                             '/home/semikernel/Tiktok/Projects/OneMonthPlan/media/videos/gaza/1920p6                         
                             0/partial_movie_files/Test/1069205256_3146877161_1023450693.mp4'                                
                    INFO     Combining to Movie file.                                                scene_file_writer.py:617
                    INFO                                                                             scene_file_writer.py:735
                             File ready at                                                                                   
                             '/home/semikernel/Tiktok/Projects/OneMonthPlan/media/videos/gaza/1920p6                         
                             0/Test.mp4'                                                                                     

                    INFO     Rendered Test                                                                       scene.py:241
                             Played 2 animations                                                                             
[05/17/24 19:26:05] INFO     Generated 1 slides to                                                                base.py:503
                             '/home/semikernel/Tiktok/Projects/OneMonthPlan/slides/files/Test'                               
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/semikernel/.local/lib/python3.10/site-packages/manim/cli/render/commands.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/manim.py:97 in render    │
│                                                                                                  │
│    94 │   │                                                                                      │
│    95 │   │   config["max_files_cached"] = max_files_cached                                      │
│    96 │   │                                                                                      │
│ ❱  97 │   │   self._save_slides()                                                                │
│    98                                                                                            │
│    99                                                                                            │
│   100 class ThreeDSlide(Slide, ThreeDScene):  # type: ignore[misc]                               │
│                                                                                                  │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim_slides/slide/base.py:512 in           │
│ _save_slides                                                                                     │
│                                                                                                  │
│   509 │   │   PresentationConfig(                                                                │
│   510 │   │   │   slides=slides,                                                                 │
│   511 │   │   │   resolution=self._resolution,                                                   │
│ ❱ 512 │   │   │   background_color=self._background_color,                                       │
│   513 │   │   ).to_file(slide_path)                                                              │
│   514 │   │                                                                                      │
│   515 │   │   logger.info(                                                                       │
│                                                                                                  │
│ /home/semikernel/.local/lib/python3.10/site-packages/manim_slides/slide/manim.py:26 in           │
│ _background_color                                                                                │
│                                                                                                  │
│    23 │                                                                                          │
│    24 │   @property                                                                              │
│    25 │   def _background_color(self) -> str:                                                    │
│ ❱  26 │   │   color = self.camera.background_color                                               │
│    27 │   │   if hex_color := getattr(color, "hex", None):                                       │
│    28 │   │   │   return hex_color  # type: ignore                                               │
│    29 │   │   else:  # manim>=0.18, see https://github.com/ManimCommunity/manim/pull/3020        │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'OpenGLCamera' object has no attribute 'background_color'

Version

manim-slides, version 5.1.7

Platform

ubuntu 22.04

Screenshots

No response

Additional information

Actually in previous manim-slides, everything works well. I am wondering where the error comes from. Thx a lot:) No response

jeertmans commented 1 month ago

Hello, nice catch @semikernel!

I actually never use the OpenGL renderer, but I guess supporting it would be very easy.

Reading the OpenGLCamera class, it looks like I might need to try from config["background_color"] instead. Something similar might also be needed for the other attributes.

I don't have might time for this at the moment, but feel free to give it a try if you feel confident enough :-)

semikernel commented 1 month ago

Hello, nice catch @semikernel!

I actually never use the OpenGL renderer, but I guess supporting it would be very easy.

Reading the OpenGLCamera class, it looks like I might need to try from config["background_color"] instead. Something similar might also be needed for the other attributes.

I don't have might time for this at the moment, but feel free to give it a try if you feel confident enough :-)

Hi,there! I figured it out by creating a ThreeDSlideGL class, it worked. I found it difficult to integrate it to manim-slides whole project. I need to change many all = [ ] stuffs. However, it worked well:)

from manim_slides import Slide, ThreeDSlide
from manim.renderer.opengl_renderer import OpenGLCamera

class ThreeDSlideGL(ThreeDSlide):
    @property
    def _background_color(self) -> str:
        try:
            # Attempt to get the background color for OpenGLCamera
            if isinstance(self.camera, OpenGLCamera):
                # Check for possible attributes
                if hasattr(self.camera, 'background_rgba'):
                    color = self.camera.background_rgba
                elif hasattr(self.camera, 'background_color'):
                    color = self.camera.background_color
                else:
                    # Fallback to default color if none is found
                    color = (0, 0, 0, 1)  # Default to black

                return "#" + "".join(f"{int(c*255):02x}" for c in color[:3])
            else:
                # Handle other camera types
                color = self.camera.background_color
                if hex_color := getattr(color, "hex", None):
                    return hex_color  # type: ignore
                else:
                    return "#000000"  # Default to black if attribute is not found
        except Exception as e:
            # Handle any unexpected errors
            return "#000000"  # Default to black
jeertmans commented 1 month ago

Hello, nice catch @semikernel! I actually never use the OpenGL renderer, but I guess supporting it would be very easy. Reading the OpenGLCamera class, it looks like I might need to try from config["background_color"] instead. Something similar might also be needed for the other attributes. I don't have might time for this at the moment, but feel free to give it a try if you feel confident enough :-)

Hi,there! I figured it out by creating a ThreeDSlideGL class, it worked. I found it difficult to integrate it to manim-slides whole project. I need to change many all = [ ] stuffs. However, it worked well:)

from manim_slides import Slide, ThreeDSlide
from manim.renderer.opengl_renderer import OpenGLCamera

class ThreeDSlideGL(ThreeDSlide):
    @property
    def _background_color(self) -> str:
        try:
            # Attempt to get the background color for OpenGLCamera
            if isinstance(self.camera, OpenGLCamera):
                # Check for possible attributes
                if hasattr(self.camera, 'background_rgba'):
                    color = self.camera.background_rgba
                elif hasattr(self.camera, 'background_color'):
                    color = self.camera.background_color
                else:
                    # Fallback to default color if none is found
                    color = (0, 0, 0, 1)  # Default to black

                return "#" + "".join(f"{int(c*255):02x}" for c in color[:3])
            else:
                # Handle other camera types
                color = self.camera.background_color
                if hex_color := getattr(color, "hex", None):
                    return hex_color  # type: ignore
                else:
                    return "#000000"  # Default to black if attribute is not found
        except Exception as e:
            # Handle any unexpected errors
            return "#000000"  # Default to black

Thanks for sharing your solution, and sorry for the late reply!

The config["background_color"] didn't work? Because, for compatibility with future versions, I would like to prefer to have the simplest solution. And, if multiple cases have to be handled, then documenting why they might exist is very important IMO :-)