-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Description
Description of bug / unexpected behavior
Using always_redraw
with SVGMobject
raises
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
when it tries to interpolate the colors of the current and next object it seems.
Expected behavior
Like for other Mobjects, it should just replace the old one with the next. Tbh I'm not entirely sure why it even calls the become
method on the mobject. Is there a specific reason for that? I would assume always_redraw
just inserts the object generated by func()
for a single frame and removes it afterwards.
How to reproduce the issue
The following code is just an example of how to get the relevant error. In this specific case the desired output could also be achieved by animating the scale change differently.
An example where the code would be necessary (as far as I know) is when one has different SVGs for each frame. But this would make the code to reproduce more complex.
Code for reproducing the problem
class SvgRedrawIssue(Scene):
def construct(self):
value = ValueTracker(1)
object = always_redraw(lambda: SVGMobject("something.svg").scale(value.get_value()))
self.add(object)
self.play(value.animate.set_value(2), rate_func=rate_functions.linear)
Additional media files
There isn't any output but I have attached the SVG file that is used in the code, even though any other file will probably produce the same error.
Logs
Terminal output
Manim Community v0.19.0
[06/24/25 19:26:52] DEBUG Hashing ... hashing.py:352
DEBUG Hashing done in 0.002095 s. hashing.py:364
DEBUG Hash generated : 1457378895_2436127281_1583890234 hashing.py:367
DEBUG List of the first few animation hashes of the scene: ['1457378895_2436127281_1583890234'] cairo_renderer.py:98
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/cli/render/commands.py: │
│ 125 in render │
│ │
│ 122 │ │ │ try: │
│ 123 │ │ │ │ with tempconfig({}): │
│ 124 │ │ │ │ │ scene = SceneClass() │
│ ❱ 125 │ │ │ │ │ scene.render() │
│ 126 │ │ │ except Exception: │
│ 127 │ │ │ │ error_console.print_exception() │
│ 128 │ │ │ │ sys.exit(1) │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/scene/scene.py:237 in │
│ render │
│ │
│ 234 │ │ """ │
│ 235 │ │ self.setup() │
│ 236 │ │ try: │
│ ❱ 237 │ │ │ self.construct() │
│ 238 │ │ except EndSceneEarlyException: │
│ 239 │ │ │ pass │
│ 240 │ │ except RerunSceneException: │
│ │
│ [redacted].py:246 in construct │
│ │
│ 243 │ │ value = ValueTracker(1) │
│ 244 │ │ object = always_redraw(lambda: SVGMobject("something.svg").scale(value.get_value │
│ 245 │ │ self.add(object) │
│ ❱ 246 │ │ self.play(value.animate.set_value(2), rate_func=rate_functions.linear) │
│ 247 │
│ 248 │
│ 249 class SvgIssue2(Scene): │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/scene/scene.py:1125 in │
│ play │
│ │
│ 1122 │ │ │ return │
│ 1123 │ │ │
│ 1124 │ │ start_time = self.time │
│ ❱ 1125 │ │ self.renderer.play(self, *args, **kwargs) │
│ 1126 │ │ run_time = self.time - start_time │
│ 1127 │ │ if subcaption: │
│ 1128 │ │ │ if subcaption_duration is None: │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/renderer/cairo_renderer │
│ .py:115 in play │
│ │
│ 112 │ │ │ # In this case, as there is only a wait, it will be the length of the wait. │
│ 113 │ │ │ self.freeze_current_frame(scene.duration) │
│ 114 │ │ else: │
│ ❱ 115 │ │ │ scene.play_internal() │
│ 116 │ │ self.file_writer.end_animation(not self.skip_animations) │
│ 117 │ │ │
│ 118 │ │ self.num_plays += 1 │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/scene/scene.py:1295 in │
│ play_internal │
│ │
│ 1292 │ │ │ self.duration, │
│ 1293 │ │ ) │
│ 1294 │ │ for t in self.time_progression: │
│ ❱ 1295 │ │ │ self.update_to_time(t) │
│ 1296 │ │ │ if not skip_rendering and not self.skip_animation_preview: │
│ 1297 │ │ │ │ self.renderer.render(self, t, self.moving_mobjects) │
│ 1298 │ │ │ if self.stop_condition is not None and self.stop_condition(): │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/scene/scene.py:1535 in │
│ update_to_time │
│ │
│ 1532 │ │ │ animation.update_mobjects(dt) │
│ 1533 │ │ │ alpha = t / animation.run_time │
│ 1534 │ │ │ animation.interpolate(alpha) │
│ ❱ 1535 │ │ self.update_mobjects(dt) │
│ 1536 │ │ self.update_meshes(dt) │
│ 1537 │ │ self.update_self(dt) │
│ 1538 │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/scene/scene.py:356 in │
│ update_mobjects │
│ │
│ 353 │ │ │ Change in time between updates. Defaults (mostly) to 1/frames_per_second │
│ 354 │ │ """ │
│ 355 │ │ for mobject in self.mobjects: │
│ ❱ 356 │ │ │ mobject.update(dt) │
│ 357 │ │
│ 358 │ def update_meshes(self, dt): │
│ 359 │ │ for obj in self.meshes: │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/mobject/mobject.py:902 │
│ in update │
│ │
│ 899 │ │ │ if "dt" in inspect.signature(updater).parameters: │
│ 900 │ │ │ │ updater(self, dt) │
│ 901 │ │ │ else: │
│ ❱ 902 │ │ │ │ updater(self) │
│ 903 │ │ if recursive: │
│ 904 │ │ │ for submob in self.submobjects: │
│ 905 │ │ │ │ submob.update(dt, recursive) │
│ │
│ [redacted].py:10 in <lambda> │
│ │
│ 7 │
│ 8 def always_redraw(func: Callable[[], Mobject]) -> Mobject: │
│ 9 │ mob = func() │
│ ❱ 10 │ mob.add_updater(lambda _: mob.become(func())) │
│ 11 │ return mob │
│ 12 │
│ 13 @dataclass │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/mobject/mobject.py:2941 │
│ in become │
│ │
│ 2938 │ │ self.align_data(mobject, skip_point_alignment=True) │
│ 2939 │ │ for sm1, sm2 in zip(self.get_family(), mobject.get_family()): │
│ 2940 │ │ │ sm1.points = np.array(sm2.points) │
│ ❱ 2941 │ │ │ sm1.interpolate_color(sm1, sm2, 1) │
│ 2942 │ │ return self │
│ 2943 │ │
│ 2944 │ def match_points(self, mobject: Mobject, copy_submobjects: bool = True) -> Self: │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/mobject/types/vectorize │
│ d_mobject.py:1864 in interpolate_color │
│ │
│ 1861 │ │ │ setattr( │
│ 1862 │ │ │ │ self, │
│ 1863 │ │ │ │ attr, │
│ ❱ 1864 │ │ │ │ interpolate(getattr(mobject1, attr), getattr(mobject2, attr), alpha), │
│ 1865 │ │ │ ) │
│ 1866 │ │ │ if alpha == 1.0: │
│ 1867 │ │ │ │ val = getattr(mobject2, attr) │
│ │
│ /opt/homebrew/Caskroom/miniconda/base/lib/python3.12/site-packages/manim/utils/bezier.py:1062 in │
│ interpolate │
│ │
│ 1059 │ │ │ * ``alpha`` is a :class:`float`, the return is another :class:`~.Point3D`. │
│ 1060 │ │ │ * ``alpha`` is a :class:`~.ColVector`, the return is a :class:`~.Point3D_Arr │
│ 1061 │ """ │
│ ❱ 1062 │ return (1 - alpha) * start + alpha * end │
│ 1063 │
│ 1064 │
│ 1065 def integer_interpolate( │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
System specifications
System Details
macOS 15.5Python 3.12.2
LaTeX details
I don't think this is necessary. If it is I'll add it.Metadata
Metadata
Assignees
Labels
Type
Projects
Status