Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions manim/scene/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,8 +994,35 @@ def compile_animations(
for k, v in kwargs.items():
setattr(animation, k, v)

self._warn_if_overlapping_animate_targets(animations)

return animations

@staticmethod
def _warn_if_overlapping_animate_targets(animations: list[Animation]) -> None:
from ..animation.transform import _MethodAnimation

method_anims = [
anim for anim in animations if isinstance(anim, _MethodAnimation)
]
if len(method_anims) < 2:
return

seen: set[int] = set()
for anim in method_anims:
for member in anim.mobject.get_family():
member_id = id(member)
if member_id in seen:
logger.warning(
"Multiple .animate animations in the same play() affect "
"the same mobject (%s). Later animations override earlier "
"ones for unchanged attributes; reorder arguments or "
"animate mobjects individually.",
member.__class__.__name__,
)
return
seen.add(member_id)

def _get_animation_time_progression(
self, animations: list[Animation], duration: float
) -> tqdm[float]:
Expand Down
30 changes: 29 additions & 1 deletion tests/module/scene/test_scene.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
from __future__ import annotations

import datetime
from unittest.mock import patch

import pytest

from manim import Circle, Dot, FadeIn, Group, Mobject, Scene, Square
from manim import (
RIGHT,
Circle,
Dot,
FadeIn,
Group,
Mobject,
Scene,
Square,
VGroup,
logger,
)
from manim.animation.animation import Wait


Expand Down Expand Up @@ -146,3 +158,19 @@ def test_random_color_reproducibility_with_seed(dry_run):

# The interrupted colors should be different (seeded with 999)
assert colors_interrupted != colors_first_run[:3]


def test_warn_overlapping_animate_targets() -> None:
scene = Scene()
square = Square()
circle = Circle()
group = VGroup(square, circle)

with patch.object(logger, "warning") as warn:
scene.compile_animations(
group.animate.shift(RIGHT),
circle.animate.set_opacity(0.5),
)

warn.assert_called_once()
assert "Multiple .animate animations" in warn.call_args[0][0]
Loading