mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Small cleanup/reorganizing of Mobject methods
This commit is contained in:
parent
7b67f4556b
commit
f314054081
1 changed files with 116 additions and 121 deletions
|
@ -1,7 +1,5 @@
|
||||||
from functools import reduce
|
|
||||||
import copy
|
import copy
|
||||||
import itertools as it
|
import itertools as it
|
||||||
import operator as op
|
|
||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
import moderngl
|
import moderngl
|
||||||
|
@ -31,9 +29,6 @@ from manimlib.shader_wrapper import ShaderWrapper
|
||||||
from manimlib.shader_wrapper import get_colormap_code
|
from manimlib.shader_wrapper import get_colormap_code
|
||||||
|
|
||||||
|
|
||||||
# TODO: Explain array_attrs
|
|
||||||
# TODO: Incorporate shader defaults
|
|
||||||
|
|
||||||
class Mobject(object):
|
class Mobject(object):
|
||||||
"""
|
"""
|
||||||
Mathematical Object
|
Mathematical Object
|
||||||
|
@ -298,6 +293,84 @@ class Mobject(object):
|
||||||
self.set_submobjects(list_update(self.submobjects, mobject_attrs))
|
self.set_submobjects(list_update(self.submobjects, mobject_attrs))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
# Submobject organization
|
||||||
|
|
||||||
|
def arrange(self, direction=RIGHT, center=True, **kwargs):
|
||||||
|
for m1, m2 in zip(self.submobjects, self.submobjects[1:]):
|
||||||
|
m2.next_to(m1, direction, **kwargs)
|
||||||
|
if center:
|
||||||
|
self.center()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def arrange_in_grid(self, n_rows=None, n_cols=None,
|
||||||
|
buff=None,
|
||||||
|
h_buff=None,
|
||||||
|
v_buff=None,
|
||||||
|
buff_ratio=None,
|
||||||
|
h_buff_ratio=0.5,
|
||||||
|
v_buff_ratio=0.5,
|
||||||
|
aligned_edge=ORIGIN,
|
||||||
|
fill_rows_first=True):
|
||||||
|
submobs = self.submobjects
|
||||||
|
if n_rows is None and n_cols is None:
|
||||||
|
n_rows = int(np.sqrt(len(submobs)))
|
||||||
|
if n_rows is None:
|
||||||
|
n_rows = len(submobs) // n_cols
|
||||||
|
if n_cols is None:
|
||||||
|
n_cols = len(submobs) // n_rows
|
||||||
|
|
||||||
|
if buff is not None:
|
||||||
|
h_buff = buff
|
||||||
|
v_buff = buff
|
||||||
|
else:
|
||||||
|
if buff_ratio is not None:
|
||||||
|
v_buff_ratio = buff_ratio
|
||||||
|
h_buff_ratio = buff_ratio
|
||||||
|
if h_buff is None:
|
||||||
|
h_buff = h_buff_ratio * self[0].get_width()
|
||||||
|
if v_buff is None:
|
||||||
|
v_buff = v_buff_ratio * self[0].get_height()
|
||||||
|
|
||||||
|
x_unit = h_buff + max([sm.get_width() for sm in submobs])
|
||||||
|
y_unit = v_buff + max([sm.get_height() for sm in submobs])
|
||||||
|
|
||||||
|
for index, sm in enumerate(submobs):
|
||||||
|
if fill_rows_first:
|
||||||
|
x, y = index % n_cols, index // n_cols
|
||||||
|
else:
|
||||||
|
x, y = index // n_rows, index % n_rows
|
||||||
|
sm.move_to(ORIGIN, aligned_edge)
|
||||||
|
sm.shift(x * x_unit * RIGHT + y * y_unit * DOWN)
|
||||||
|
self.center()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def get_grid(self, n_rows, n_cols, height=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Returns a new mobject containing multiple copies of this one
|
||||||
|
arranged in a grid
|
||||||
|
"""
|
||||||
|
grid = self.get_group_class()(
|
||||||
|
*(self.copy() for n in range(n_rows * n_cols))
|
||||||
|
)
|
||||||
|
grid.arrange_in_grid(n_rows, n_cols, **kwargs)
|
||||||
|
if height is not None:
|
||||||
|
grid.set_height(height)
|
||||||
|
return grid
|
||||||
|
|
||||||
|
def sort(self, point_to_num_func=lambda p: p[0], submob_func=None):
|
||||||
|
if submob_func is not None:
|
||||||
|
self.submobjects.sort(key=submob_func)
|
||||||
|
else:
|
||||||
|
self.submobjects.sort(key=lambda m: point_to_num_func(m.get_center()))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def shuffle(self, recurse=False):
|
||||||
|
if recurse:
|
||||||
|
for submob in self.submobjects:
|
||||||
|
submob.shuffle(recurse=True)
|
||||||
|
random.shuffle(self.submobjects)
|
||||||
|
return self
|
||||||
|
|
||||||
# Copying
|
# Copying
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
|
@ -373,16 +446,16 @@ class Mobject(object):
|
||||||
self.has_updaters = False
|
self.has_updaters = False
|
||||||
self.updating_suspended = False
|
self.updating_suspended = False
|
||||||
|
|
||||||
def update(self, dt=0, recursive=True):
|
def update(self, dt=0, recurse=True):
|
||||||
if not self.has_updaters or self.updating_suspended:
|
if not self.has_updaters or self.updating_suspended:
|
||||||
return self
|
return self
|
||||||
for updater in self.time_based_updaters:
|
for updater in self.time_based_updaters:
|
||||||
updater(self, dt)
|
updater(self, dt)
|
||||||
for updater in self.non_time_updaters:
|
for updater in self.non_time_updaters:
|
||||||
updater(self)
|
updater(self)
|
||||||
if recursive:
|
if recurse:
|
||||||
for submob in self.submobjects:
|
for submob in self.submobjects:
|
||||||
submob.update(dt, recursive)
|
submob.update(dt, recurse)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_time_based_updaters(self):
|
def get_time_based_updaters(self):
|
||||||
|
@ -419,13 +492,13 @@ class Mobject(object):
|
||||||
updater_list.remove(update_function)
|
updater_list.remove(update_function)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def clear_updaters(self, recursive=True):
|
def clear_updaters(self, recurse=True):
|
||||||
self.time_based_updaters = []
|
self.time_based_updaters = []
|
||||||
self.non_time_updaters = []
|
self.non_time_updaters = []
|
||||||
if recursive:
|
if recurse:
|
||||||
for submob in self.submobjects:
|
for submob in self.submobjects:
|
||||||
submob.clear_updaters()
|
submob.clear_updaters()
|
||||||
self.suspend_updating(recursive)
|
self.suspend_updating(recurse)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def match_updaters(self, mobject):
|
def match_updaters(self, mobject):
|
||||||
|
@ -434,22 +507,22 @@ class Mobject(object):
|
||||||
self.add_updater(updater)
|
self.add_updater(updater)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def suspend_updating(self, recursive=True):
|
def suspend_updating(self, recurse=True):
|
||||||
self.updating_suspended = True
|
self.updating_suspended = True
|
||||||
if recursive:
|
if recurse:
|
||||||
for submob in self.submobjects:
|
for submob in self.submobjects:
|
||||||
submob.suspend_updating(recursive)
|
submob.suspend_updating(recurse)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def resume_updating(self, recursive=True, call_updater=True):
|
def resume_updating(self, recurse=True, call_updater=True):
|
||||||
self.updating_suspended = False
|
self.updating_suspended = False
|
||||||
if recursive:
|
if recurse:
|
||||||
for submob in self.submobjects:
|
for submob in self.submobjects:
|
||||||
submob.resume_updating(recursive)
|
submob.resume_updating(recurse)
|
||||||
for parent in self.parents:
|
for parent in self.parents:
|
||||||
parent.resume_updating(recursive=False, call_updater=False)
|
parent.resume_updating(recurse=False, call_updater=False)
|
||||||
if call_updater:
|
if call_updater:
|
||||||
self.update(dt=0, recursive=recursive)
|
self.update(dt=0, recurse=recurse)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def refresh_has_updater_status(self):
|
def refresh_has_updater_status(self):
|
||||||
|
@ -744,30 +817,6 @@ class Mobject(object):
|
||||||
self.shift(start - curr_start)
|
self.shift(start - curr_start)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
# Background rectangle
|
|
||||||
|
|
||||||
def add_background_rectangle(self, color=BLACK, opacity=0.75, **kwargs):
|
|
||||||
# TODO, this does not behave well when the mobject has points,
|
|
||||||
# since it gets displayed on top
|
|
||||||
from manimlib.mobject.shape_matchers import BackgroundRectangle
|
|
||||||
self.background_rectangle = BackgroundRectangle(
|
|
||||||
self, color=color,
|
|
||||||
fill_opacity=opacity,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
self.add_to_back(self.background_rectangle)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def add_background_rectangle_to_submobjects(self, **kwargs):
|
|
||||||
for submobject in self.submobjects:
|
|
||||||
submobject.add_background_rectangle(**kwargs)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def add_background_rectangle_to_family_members_with_points(self, **kwargs):
|
|
||||||
for mob in self.family_members_with_points():
|
|
||||||
mob.add_background_rectangle(**kwargs)
|
|
||||||
return self
|
|
||||||
|
|
||||||
# Color functions
|
# Color functions
|
||||||
|
|
||||||
def set_rgba_array(self, color=None, opacity=None, name="rgbas", recurse=True):
|
def set_rgba_array(self, color=None, opacity=None, name="rgbas", recurse=True):
|
||||||
|
@ -857,6 +906,30 @@ class Mobject(object):
|
||||||
mob.uniforms["shadow"] = shadow
|
mob.uniforms["shadow"] = shadow
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
# Background rectangle
|
||||||
|
|
||||||
|
def add_background_rectangle(self, color=BLACK, opacity=0.75, **kwargs):
|
||||||
|
# TODO, this does not behave well when the mobject has points,
|
||||||
|
# since it gets displayed on top
|
||||||
|
from manimlib.mobject.shape_matchers import BackgroundRectangle
|
||||||
|
self.background_rectangle = BackgroundRectangle(
|
||||||
|
self, color=color,
|
||||||
|
fill_opacity=opacity,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
self.add_to_back(self.background_rectangle)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_background_rectangle_to_submobjects(self, **kwargs):
|
||||||
|
for submobject in self.submobjects:
|
||||||
|
submobject.add_background_rectangle(**kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_background_rectangle_to_family_members_with_points(self, **kwargs):
|
||||||
|
for mob in self.family_members_with_points():
|
||||||
|
mob.add_background_rectangle(**kwargs)
|
||||||
|
return self
|
||||||
|
|
||||||
# Getters
|
# Getters
|
||||||
|
|
||||||
def get_bounding_box_point(self, direction):
|
def get_bounding_box_point(self, direction):
|
||||||
|
@ -1037,84 +1110,6 @@ class Mobject(object):
|
||||||
def get_group_class(self):
|
def get_group_class(self):
|
||||||
return Group
|
return Group
|
||||||
|
|
||||||
# Submobject organization
|
|
||||||
|
|
||||||
def arrange(self, direction=RIGHT, center=True, **kwargs):
|
|
||||||
for m1, m2 in zip(self.submobjects, self.submobjects[1:]):
|
|
||||||
m2.next_to(m1, direction, **kwargs)
|
|
||||||
if center:
|
|
||||||
self.center()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def arrange_in_grid(self, n_rows=None, n_cols=None,
|
|
||||||
buff=None,
|
|
||||||
h_buff=None,
|
|
||||||
v_buff=None,
|
|
||||||
buff_ratio=None,
|
|
||||||
h_buff_ratio=0.5,
|
|
||||||
v_buff_ratio=0.5,
|
|
||||||
aligned_edge=ORIGIN,
|
|
||||||
fill_rows_first=True):
|
|
||||||
submobs = self.submobjects
|
|
||||||
if n_rows is None and n_cols is None:
|
|
||||||
n_rows = int(np.sqrt(len(submobs)))
|
|
||||||
if n_rows is None:
|
|
||||||
n_rows = len(submobs) // n_cols
|
|
||||||
if n_cols is None:
|
|
||||||
n_cols = len(submobs) // n_rows
|
|
||||||
|
|
||||||
if buff is not None:
|
|
||||||
h_buff = buff
|
|
||||||
v_buff = buff
|
|
||||||
else:
|
|
||||||
if buff_ratio is not None:
|
|
||||||
v_buff_ratio = buff_ratio
|
|
||||||
h_buff_ratio = buff_ratio
|
|
||||||
if h_buff is None:
|
|
||||||
h_buff = h_buff_ratio * self[0].get_width()
|
|
||||||
if v_buff is None:
|
|
||||||
v_buff = v_buff_ratio * self[0].get_height()
|
|
||||||
|
|
||||||
x_unit = h_buff + max([sm.get_width() for sm in submobs])
|
|
||||||
y_unit = v_buff + max([sm.get_height() for sm in submobs])
|
|
||||||
|
|
||||||
for index, sm in enumerate(submobs):
|
|
||||||
if fill_rows_first:
|
|
||||||
x, y = index % n_cols, index // n_cols
|
|
||||||
else:
|
|
||||||
x, y = index // n_rows, index % n_rows
|
|
||||||
sm.move_to(ORIGIN, aligned_edge)
|
|
||||||
sm.shift(x * x_unit * RIGHT + y * y_unit * DOWN)
|
|
||||||
self.center()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def get_grid(self, n_rows, n_cols, height=None, **kwargs):
|
|
||||||
"""
|
|
||||||
Returns a new mobject containing multiple copies of this one
|
|
||||||
arranged in a grid
|
|
||||||
"""
|
|
||||||
grid = self.get_group_class()(
|
|
||||||
*(self.copy() for n in range(n_rows * n_cols))
|
|
||||||
)
|
|
||||||
grid.arrange_in_grid(n_rows, n_cols, **kwargs)
|
|
||||||
if height is not None:
|
|
||||||
grid.set_height(height)
|
|
||||||
return grid
|
|
||||||
|
|
||||||
def sort(self, point_to_num_func=lambda p: p[0], submob_func=None):
|
|
||||||
if submob_func is not None:
|
|
||||||
self.submobjects.sort(key=submob_func)
|
|
||||||
else:
|
|
||||||
self.submobjects.sort(key=lambda m: point_to_num_func(m.get_center()))
|
|
||||||
return self
|
|
||||||
|
|
||||||
def shuffle(self, recurse=False):
|
|
||||||
if recurse:
|
|
||||||
for submob in self.submobjects:
|
|
||||||
submob.shuffle(recurse=True)
|
|
||||||
random.shuffle(self.submobjects)
|
|
||||||
return self
|
|
||||||
|
|
||||||
# Alignment
|
# Alignment
|
||||||
|
|
||||||
def align_data_and_family(self, mobject):
|
def align_data_and_family(self, mobject):
|
||||||
|
|
Loading…
Add table
Reference in a new issue