3b1b-manim/animation/animation.py
Grant Sanderson e632be304d Removed sync_animation_run_times_and_rate_funcs, and changed
the implementaiton of Scene.play and AnimationGroup so as to
not change the run_time and rate_func of the animations passed
in.
2018-02-19 16:51:47 -08:00

142 lines
4 KiB
Python

from PIL import Image
from colour import Color
import numpy as np
import warnings
import time
import os
import progressbar
import inspect
from copy import deepcopy
from helpers import *
from mobject import Mobject
class Animation(object):
CONFIG = {
"run_time" : DEFAULT_ANIMATION_RUN_TIME,
"rate_func" : smooth,
"name" : None,
#Does this animation add or remove a mobject form the screen
"remover" : False,
#Options are lagged_start, smoothed_lagged_start,
#one_at_a_time, all_at_once
"submobject_mode" : "all_at_once",
"lag_factor" : 2,
# Used by EmptyAnimation to announce itself ignorable
# in Successions and AnimationGroups
"empty" : False
}
def __init__(self, mobject, **kwargs):
mobject = instantiate(mobject)
assert(isinstance(mobject, Mobject))
digest_config(self, kwargs, locals())
self.starting_mobject = self.mobject.copy()
if self.rate_func is None:
self.rate_func = (lambda x : x)
if self.name is None:
self.name = self.__class__.__name__ + str(self.mobject)
self.all_families_zipped = self.get_all_families_zipped()
self.update(0)
def update_config(self, **kwargs):
digest_config(self, kwargs)
if "rate_func" in kwargs and kwargs["rate_func"] is None:
self.rate_func = (lambda x : x)
return self
def __str__(self):
return self.name
def copy(self):
return deepcopy(self)
def update(self, alpha):
alpha = np.clip(alpha, 0, 1)
self.update_mobject(self.rate_func(alpha))
def update_mobject(self, alpha):
families = self.all_families_zipped
for i, mobs in enumerate(families):
sub_alpha = self.get_sub_alpha(alpha, i, len(families))
self.update_submobject(*list(mobs) + [sub_alpha])
return self
def update_submobject(self, submobject, starting_sumobject, alpha):
#Typically ipmlemented by subclass
pass
def get_all_mobjects(self):
"""
Ordering must match the ording of arguments to update_submobject
"""
return self.mobject, self.starting_mobject
def get_all_families_zipped(self):
return zip(*map(
Mobject.family_members_with_points,
self.get_all_mobjects()
))
def get_sub_alpha(self, alpha, index, num_submobjects):
if self.submobject_mode in ["lagged_start", "smoothed_lagged_start"]:
prop = float(index)/num_submobjects
if self.submobject_mode is "smoothed_lagged_start":
prop = smooth(prop)
lf = self.lag_factor
return np.clip(lf*alpha - (lf-1)*prop, 0, 1)
elif self.submobject_mode == "one_at_a_time":
lower = float(index)/num_submobjects
upper = float(index+1)/num_submobjects
return np.clip((alpha-lower)/(upper-lower), 0, 1)
elif self.submobject_mode == "all_at_once":
return alpha
raise Exception("Invalid submobject mode")
def filter_out(self, *filter_functions):
self.filter_functions += filter_functions
return self
def set_run_time(self, time):
self.run_time = time
return self
def get_run_time(self):
return self.run_time
def set_rate_func(self, rate_func):
if rate_func is None:
rate_func = lambda x : x
self.rate_func = rate_func
return self
def get_rate_func(self):
return self.rate_func
def set_name(self, name):
self.name = name
return self
def is_remover(self):
return self.remover
def clean_up(self, surrounding_scene = None):
self.update(1)
if surrounding_scene is not None:
if self.is_remover():
surrounding_scene.remove(self.mobject)
else:
surrounding_scene.add(self.mobject)
return self