Use overrides of children in family operations
Author: GniLudioCreated Sep 15, 2026Updated Sep 16, 2026
Currently, operations that work on family members don't take overidden methods of children into account. So the result can be quite different when children implement custom logic.
This is quite prominent with the Arrow.scale method:
def construct(self) -> None:
mob1 = VGroup(Arrow().scale(3))
mob2 = VGroup(Arrow()).scale(3)
self.add(VGroup(mob1, mob2).arrange(DOWN))Ideally, when calling an operation on a parent, it should still use the overridden methods of children.
Aditional things to consider:
- the submobject tree can contain loops and/or duplicates
- parents should have control over how the operation is applied to children
- overrides should be able to have custom logic before and/or after the operation
- parents should be able to have custom logic before and/or after the operation is applied to their children
- users should be able to pass (custom) parameters to all members
Some ideas and their ad-/disadvantages were already discussed in #4994. See here
Ideas
Dump recursion
Assumes no duplicates and/or loops.
def some_operation(...):
... # apply to self
for sub in self.submobjects:
sub.some_operation(...)Internal method for self
def some_operation(...):
for mob in self.get_family():
mob._some_operation(...)
def _some_operation(...):
... # apply to selfapply_to_family
def some_operation(..., apply_to_family=True):
... # logic for self
if apply to family:
for mob in self.get_family():
mob.some_operation(..., apply_to_family=False)already_seen
def some_operation(..., already_seen= None):
... # apply to self
if already_seen is None:
already_seen = {self}
for sub in self.submobjects:
if sub not in already_seen:
already_seen.add(sub)
sub.some_operation(..., already_seen=already_seen)apply_to_family internally
def some_operation(...):
return self._some_operation(...)
def _some_operation(..., apply_to_family=True):
... # apply to self
if apply to family:
for mob in self.get_family():
mob.some_operation(..., apply_to_family=False)already_seen internally
def some_operation(...):
return self._some_operation(...)
def _some_operation(..., already_seen= None):
... # apply to self
if already_seen is None:
already_seen = {self}
for sub in self.submobjects:
if sub not in already_seen:
already_seen.add(sub)
sub.some_operation(..., already_seen=already_seen)Source: ManimCommunity/manim