-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Port ManimGL's Mobject family memoization #3742
base: main
Are you sure you want to change the base?
Conversation
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some questions/typing stuff, but overall the changes look good to me!
Would also be great to have some tests.
manim/mobject/mobject.py
Outdated
@@ -106,7 +115,9 @@ def __init__( | |||
self.target = target | |||
self.z_index = z_index | |||
self.point_hash = None | |||
self.submobjects = [] | |||
self._submobjects = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self._submobjects = [] | |
self._submobjects: list[Mobject] = [] |
This way we also get static analysis on this.
manim/mobject/mobject.py
Outdated
def submobjects(self, new_submobjects) -> None: | ||
self._submobjects = new_submobjects |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def submobjects(self, new_submobjects) -> None: | |
self._submobjects = new_submobjects | |
def submobjects(self, new_submobjects: list[Mobject]) -> None: | |
self._submobjects = new_submobjects |
So that the type of self._submobjects
is never weird.
Would it cause a significant performance disadvantage to also add some sort of type validation here?
manim/mobject/mobject.py
Outdated
e.g. any other parents of a submobject | ||
""" | ||
ancestors = [] | ||
to_process = list(self.get_family(recurse=extended)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you calling list
to make a shallow copy of the family? In that case it might be better to simply call self.get_family(...).copy()
I addressed the changes you requested. self.play(
Transform(title, transform_title),
# ...
) For some reason the amount of points don't match, leading to this error:
I'll be taking a look at this bug, any help is appreciated. |
from ..utils.paths import straight_path | ||
from ..utils.space_ops import angle_between_vectors, normalize, rotation_matrix | ||
from manim.utils.exceptions import MultiAnimationOverrideException | ||
from manim.utils.iterables import list_update, remove_list_redundancies, tuplify |
Check notice
Code scanning / CodeQL
Unused import Note
UPDATE (still in draft)I managed to solve the error I mentioned.
self.play(Write(on_screen_var)) This is because the
So this PR is kept as a draft. This issue with
|
Related issue: #373
Although I like the proposal described in the issue, ManimGL already implemented something different: family memoization. So it's easier to port that, at least for now.
Essentially, when we call
Mobject.get_family()
, instead of recomputing the whole family recursively and from scratch, we memoize it as in ManimGL. Every time a method like.add()
or.remove()
is called, which alters the submobjects and therefore the family, we delete the previous memo by setting it asNone
, to signal that it must be recalculated. The same must be done for all the parents of the Mobject, which this PR also ports from ManimGL.This is an important step in calculating bounding boxes more efficiently.
Some points for discussion:
Mobject.submobjects
a property, because if you set it manually, the family must be altered. It works, but I don't like thatsubmobjects.setter
hides the deletion of the family behind the scenes. @JasonGrace2282 proposed makingsubmobjects
a read-only property, and only allowing it to be directly changed through aMobject.set_submobjects()
method:I like the proposal, although it's a slightly breaking change and it might be done in a subsequent PR. Please share your opinions about this. I'd be glad to make that change if we agree on that.
There were some methods, like
Mobject.insert()
orMobject.shuffle()
, which returned None instead of Self like other similar methods. I think they should also return Self, but it definitely should be another PR.There are some methods which we could optimize if we reaaaally wanted to, such as
Mobject.add()
, which instead of voiding the entire family for the current Mobject, it could append the submobjects' subfamilies to this family and filter redundancies, and only void the parents' families depending on the position of the Mobject. It would get more complex, however, and it doesn't seem to be really justified for now. Plus, I tried that before, and didn't manage to get it working because of the complexity. I decided to simply stick to the ManimGL implementation as-is, as much as possible.Links to added or changed documentation pages
Further Information and Comments
Profiling with this test scene with a huge amount of nested Mobjects:
Reviewer Checklist