ManimCommunity / ManimCommunity/manim
Playing an `AnimationGroup` changes the order of `self.mobjects`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 40.9k
- Forks
- 3.1k
- Avg merge
- 3d 12h
- Merged PRs (30d)
- 25
Description
## Description of bug / unexpected behavior
Overlapping objects on a screen are drawn in front of one another. This is a fact of life. As an animator, this must be taken into account. In manim, this layering is, as far as I can tell, decided by the order of `Scene.mobjects`. Initializing an `AnimationGroup` doesn't change this order, but `play()`ing it does. This results in difficulties animating things that are supposed to be layered behind other objects.
Note the two print statements in the below code example, and their output in the terminal.
## Expected behavior
I would expect that
```
a = AnimationGroup(animation)
self.play(a)
```
did not change `scene.mobjects`, and specifically that it was visually indiscernible from `scene.play(animation)`.
I am not particularly against implementation details such as `mobject.copy()`ing and replacing the involved `Mobject`s as part of `scene.play()`ing an `AnimationGroup`, if that's what is going on under the hood. But it should then reorder `scene.mobjects` to reflect the old ordering of things.
## How to reproduce the issue
Code for reproducing the problem
```py
import manim as m
class Test(m.Scene):
def construct(self):
s1 = m.Square()
s1.shift(2*m.LEFT + 1.1*m.UP)
s1.set_fill(m.WHITE, opacity=1)
s2 = s1.copy()
s2.shift(2.2*m.DOWN)
self.add(s1, s2)
t1 = m.Square()
t1.shift(1.1*m.UP)
t1.set_fill(m.RED, opacity=1)
t2 = t1.copy()
t2.shift(2.2*m.DOWN)
self.add(t1, t2)
# The white squares are behind the red squares,
# because they were added to the scene first
self.play(
s1.animate.shift(4*m.RIGHT),
s2.animate.shift(4*m.RIGHT),
run_time=3)
# The upper white square is still behind the upper red square,
# but now the lower white square is in front of the lower red.
a1 = s1.animate.shift(4*m.LEFT)
a2 = m.AnimationGroup(s2.animate.shift(4*m.LEFT))
print(*[mob.get_color() for mob in self.mobjects])
self.play(a1, a2, run_time=3)
print(*[mob.get_color() for mob in self.mobjects])
```
## Additional media files
GIF

## Logs
Terminal output
```
Manim Community v0.15.2
[05/07/22 08:44:55] DEBUG Hashing ... hashing.py:343
DEBUG Hashing done in 0.012204 s. hashing.py:355
DEBUG Hash generated : hashing.py:358
3163782288_2346739728_856931009
DEBUG List of the first few cairo_renderer.py:84
animation hashes of the scene:
['3163782288_2346739728_856931
009']
INFO Animation 0 : Partial scene_file_writer.py:504
movie file written in '/Us
ers/uname/python/test
/media/videos/test
/480p15/partial_movie_fi
les/Test/3163782288_234673
9728_856931009.mp4'
white white #fc6255 #fc6255
DEBUG Hashing ... hashing.py:343
DEBUG Hashing done in 0.011929 s. hashing.py:355
DEBUG Hash generated : hashing.py:358
2201830969_3981890268_883942231
DEBUG List of the first few cairo_renderer.py:84
animation hashes of the scene:
['3163782288_2346739728_856931
009', '2201830969_3981890268_8
83942231']
[05/07/22 08:44:56] INFO Animation 1 : Partial scene_file_writer.py:504
movie file written in '/Us
ers/uname/python/test
/media/videos/test
/480p15/partial_movie_fi
les/Test/2201830969_398189
0268_883942231.mp4'
white #fc6255 #fc6255 white
INFO Combining to Movie file. scene_file_writer.py:597
DEBUG Partial movie files to scene_file_writer.py:538
combine (2 files): ['/User
s/uname/python/test
/media/videos/test
/480p15/partial_movie_file
s/Test/3163782288_23467397
28_856931009.mp4', '/Users
/uname/python/test
/media/videos/test/
480p15/partial_movie_files
/Test/2201830969_398189026
8_883942231.mp4']
INFO scene_file_writer.py:718
File ready at '/Users/uname
/python/test/me
dia/videos/test/480p1
5/Test_ManimCE_v0.15.2.gif
'
INFO Rendered Test scene.py:240
Played 2 animations
INFO Previewed File at: '/Users/test file_ops.py:213
/python/test/media/videos/test
/480p15/Test_ManimCE_v0.15.2
.gif'
```
## System specifications
System Details
- OS (with version, e.g., Windows 10 v2004 or macOS 10.15 (Catalina)): macOS 12.3.1
- RAM: 8GB
- Python version (`python/py/python3 --version`): 3.10.0
- Installed modules (provide output from `pip list`):
```
Package Version
------------------------- -----------
backports.cached-property 1.0.1
certifi 2021.10.8
charset-normalizer 2.0.12
click 8.0.4
click-default-group 1.2.2
cloup 0.13.0
colour 0.1.5
commonmark 0.9.1
Cython 0.29.28
decorator 5.1.1
glcontext 2.3.5
idna 3.3
isosurfaces 0.1.0
manim 0.15.2
ManimPango 0.4.0.post2
mapbox-earcut 0.12.11
moderngl 5.6.4
moderngl-window 2.4.1
multipledispatch 0.6.0
networkx 2.7.1
numpy 1.22.2
Pillow 9.0.1
pip 22.0.4
pycairo 1.21.0
pydub 0.25.1
pyglet 1.5.23
Pygments 2.11.2
pyobjc-core 8.4.1
pyobjc-framework-Cocoa 8.4.1
pyrr 0.10.3
requests 2.27.1
rich 12.3.0
scipy 1.8.0
screeninfo 0.8
setuptools 57.4.0
six 1.16.0
skia-pathops 0.7.2
srt 3.5.2
tqdm 4.63.0
urllib3 1.26.9
watchdog 2.1.6
```
FFMPEG
Output of `ffmpeg -version`:
```
ffmpeg version 5.0.1 Copyright (c) 2000-2022 the FFmpeg developers
built with Apple clang version 13.0.0 (clang-1300.0.29.30)
configuration: --prefix=/usr/local/Cellar/ffmpeg/5.0.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100
```
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the Scene.play and AnimationGroup entry points, then trace how Scene.mobjects is updated while running the reproducer in the issue. Compare the AnimationGroup path with direct scene.play(animation) behavior. Done means playing the group preserves the existing mobject order and layering, as shown by the reproducer's output and rendering.
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
- Clearly specified
- Newbie friendliness
- 45/100