ManimCommunity / ManimCommunity/manim

SVGMobject can’t have a Write animation applied to it when using OpenGL as the backend

Open
#3,303 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

issue:bug
Dominant language
Python
Stars
40.9k
Forks
3.1k
Avg merge
3d 12h
Merged PRs (30d)
25

Description

## Description of bug / unexpected behavior

SVGMobject can’t have a **Write** animation applied to it when using **OpenGL as the backend**.

## Expected behavior

Like the animation `Create` on svg, with no error.

## How to reproduce the issue

Code for reproducing the problem

```py
%%manim -v WARNING --disable_caching --renderer=opengl --write_to_movie T

class T(Scene):
def construct(self):
svg = SVGMobject('TEST.svg')
self.play(Write(svg))
```

## Logs
Terminal output

```
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[2], line 1
----> 1 get_ipython().run_cell_magic('manim', '-v WARNING --disable_caching --renderer=opengl --write_to_movie T', "\nclass T(Scene):\n def construct(self):\n svg = SVGMobject('TEST.svg')\n self.play(Write(svg))\n")

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/IPython/core/interactiveshell.py:2478, in InteractiveShell.run_cell_magic(self, magic_name, line, cell)
2476 with self.builtin_trap:
2477 args = (magic_arg_s, cell)
-> 2478 result = fn(*args, **kwargs)
2480 # The code below prevents the output from being displayed
2481 # when using magics with decodator @output_can_be_silenced
2482 # when the last Python token in the expression is a ';'.
2483 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/utils/ipython_magic.py:141, in ManimMagic.manim(self, line, cell, local_ns)
139 SceneClass = local_ns[config["scene_names"][0]]
140 scene = SceneClass(renderer=renderer)
--> 141 scene.render()
142 finally:
143 # Shader cache becomes invalid as the context is destroyed
144 shader_program_cache.clear()

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/scene/scene.py:223, in Scene.render(self, preview)
221 self.setup()
222 try:
--> 223 self.construct()
224 except EndSceneEarlyException:
225 pass

File :5, in construct(self)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/scene/scene.py:1082, in Scene.play(self, subcaption, subcaption_duration, subcaption_offset, *args, **kwargs)
1079 return
1081 start_time = self.renderer.time
-> 1082 self.renderer.play(self, *args, **kwargs)
1083 run_time = self.renderer.time - start_time
1084 if subcaption:

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/utils/caching.py:65, in handle_caching_play..wrapper(self, scene, *args, **kwargs)
60 self.file_writer.add_partial_movie_file(hash_play)
61 logger.debug(
62 "List of the first few animation hashes of the scene: %(h)s",
63 {"h": str(self.animations_hashes[:5])},
64 )
---> 65 func(self, scene, *args, **kwargs)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/renderer/opengl_renderer.py:424, in OpenGLRenderer.play(self, scene, *args, **kwargs)
421 self.file_writer.begin_animation(not self.skip_animations)
423 scene.compile_animation_data(*args, **kwargs)
--> 424 scene.begin_animations()
425 if scene.is_current_animation_frozen_frame():
426 self.update_frame(scene)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/scene/scene.py:1210, in Scene.begin_animations(self)
1208 for animation in self.animations:
1209 animation._setup_scene(self)
-> 1210 animation.begin()
1212 if config.renderer == RendererType.CAIRO:
1213 # Paint all non-moving objects onto the screen, so they don't
1214 # have to be rendered every frame
1215 (
1216 self.moving_mobjects,
1217 self.static_mobjects,
1218 ) = self.get_moving_and_static_mobjects(self.animations)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/animation/creation.py:364, in Write.begin(self)
362 if self.reverse:
363 self.reverse_submobjects()
--> 364 super().begin()

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/animation/creation.py:253, in DrawBorderThenFill.begin(self)
251 def begin(self) -> None:
252 self.outline = self.get_outline()
--> 253 super().begin()

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/animation/animation.py:203, in Animation.begin(self)
195 if self.suspend_mobject_updating:
196 # All calls to self.mobject's internal updaters
197 # during the animation, either from this Animation
(...)
200 # the internal updaters of self.starting_mobject,
201 # or any others among self.get_all_mobjects()
202 self.mobject.suspend_updating()
--> 203 self.interpolate(0)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/animation/animation.py:323, in Animation.interpolate(self, alpha)
312 def interpolate(self, alpha: float) -> None:
313 """Set the animation progress.
314
315 This method gets called for every frame during an animation.
(...)
321 the end.
322 """
--> 323 self.interpolate_mobject(alpha)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/animation/animation.py:338, in Animation.interpolate_mobject(self, alpha)
336 for i, mobs in enumerate(families):
337 sub_alpha = self.get_sub_alpha(alpha, i, len(families))
--> 338 self.interpolate_submobject(*mobs, sub_alpha)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/animation/creation.py:284, in DrawBorderThenFill.interpolate_submobject(self, submobject, starting_submobject, outline, alpha)
282 if index == 0:
283 submobject.pointwise_become_partial(outline, 0, subalpha)
--> 284 submobject.match_style(outline)
285 else:
286 submobject.interpolate(outline, starting_submobject, subalpha)

File ~/miniconda3/envs/manim/lib/python3.11/site-packages/manim/mobject/opengl/opengl_vectorized_mobject.py:313, in OpenGLVMobject.match_style(self, vmobject, recurse)
311 vmobject_style = vmobject.get_style()
312 if config.renderer == RendererType.OPENGL:
--> 313 vmobject_style["stroke_width"] = vmobject_style["stroke_width"][0][0]
314 self.set_style(**vmobject_style, recurse=False)
315 if recurse:
316 # Does its best to match up submobject lists, and
317 # match styles accordingly

TypeError: 'NoneType' object is not subscriptable
```

## System specifications

System Details

- OS: WSL2 Ubuntu 22.04.1 LTS
- Python version: 3.11

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with the provided OpenGL command and inspect manim/animation/creation.py alongside manim/mobject/opengl/opengl_vectorized_mobject.py. Trace Write through DrawBorderThenFill and OpenGLVMobject.match_style, then verify that applying Write to an SVGMobject completes without the reported TypeError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
computer-graphics
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.