2021-01-04 23:09:29 -08:00
|
|
|
from manimlib.animation.composition import AnimationGroup
|
|
|
|
from manimlib.animation.fading import FadeTransformPieces
|
2021-01-05 18:03:06 -08:00
|
|
|
from manimlib.animation.fading import FadeInFromPoint
|
|
|
|
from manimlib.animation.fading import FadeOutToPoint
|
2021-01-04 23:09:29 -08:00
|
|
|
from manimlib.animation.transform import Transform
|
|
|
|
|
2021-01-05 18:03:06 -08:00
|
|
|
from manimlib.mobject.mobject import Mobject
|
|
|
|
from manimlib.mobject.mobject import Group
|
2021-01-04 23:09:29 -08:00
|
|
|
from manimlib.mobject.types.vectorized_mobject import VGroup
|
|
|
|
from manimlib.mobject.types.vectorized_mobject import VMobject
|
2021-01-05 18:03:06 -08:00
|
|
|
from manimlib.mobject.svg.tex_mobject import TexMobject
|
|
|
|
from manimlib.utils.config_ops import digest_config
|
2021-01-04 23:09:29 -08:00
|
|
|
|
|
|
|
|
|
|
|
class TransformMatchingParts(AnimationGroup):
|
2021-01-05 18:03:06 -08:00
|
|
|
CONFIG = {
|
|
|
|
"mobject_type": Mobject,
|
|
|
|
"group_type": Group,
|
2021-01-06 16:14:36 -08:00
|
|
|
"transform_mismatches": False,
|
2021-01-05 18:03:06 -08:00
|
|
|
"fade_transform_mismatches": False,
|
|
|
|
}
|
|
|
|
|
2021-01-04 23:09:29 -08:00
|
|
|
def __init__(self, mobject, target_mobject, **kwargs):
|
2021-01-05 18:03:06 -08:00
|
|
|
digest_config(self, kwargs)
|
2021-01-04 23:09:29 -08:00
|
|
|
assert(isinstance(mobject, VMobject) and isinstance(target_mobject, VMobject))
|
|
|
|
source_map = self.get_shape_map(mobject)
|
|
|
|
target_map = self.get_shape_map(target_mobject)
|
|
|
|
|
|
|
|
transform_source = VGroup()
|
|
|
|
transform_target = VGroup()
|
|
|
|
fade_source = VGroup()
|
|
|
|
fade_target = VGroup()
|
|
|
|
|
2021-01-05 18:03:06 -08:00
|
|
|
kwargs["final_alpha_value"] = 0
|
2021-01-04 23:09:29 -08:00
|
|
|
for key in set(source_map).intersection(target_map):
|
|
|
|
transform_source.add(source_map[key])
|
|
|
|
transform_target.add(target_map[key])
|
2021-01-05 18:03:06 -08:00
|
|
|
anims = [Transform(transform_source, transform_target, **kwargs)]
|
|
|
|
|
2021-01-04 23:09:29 -08:00
|
|
|
for key in set(source_map).difference(target_map):
|
|
|
|
fade_source.add(source_map[key])
|
|
|
|
for key in set(target_map).difference(source_map):
|
|
|
|
fade_target.add(target_map[key])
|
|
|
|
|
2021-01-06 16:14:36 -08:00
|
|
|
if self.transform_mismatches:
|
|
|
|
anims.append(Transform(fade_source, fade_target, **kwargs))
|
2021-01-05 18:03:06 -08:00
|
|
|
if self.fade_transform_mismatches:
|
|
|
|
anims.append(FadeTransformPieces(fade_source, fade_target, **kwargs))
|
|
|
|
else:
|
|
|
|
anims.append(FadeOutToPoint(
|
|
|
|
fade_source, fade_target.get_center(), **kwargs
|
|
|
|
))
|
|
|
|
anims.append(FadeInFromPoint(
|
|
|
|
fade_target.copy(), fade_source.get_center(), **kwargs
|
|
|
|
))
|
|
|
|
|
|
|
|
super().__init__(*anims)
|
2021-01-04 23:09:29 -08:00
|
|
|
|
|
|
|
self.to_remove = mobject
|
|
|
|
self.to_add = target_mobject
|
|
|
|
|
|
|
|
def get_shape_map(self, mobject):
|
|
|
|
shape_map = {}
|
2021-01-05 18:03:06 -08:00
|
|
|
for sm in self.get_mobject_parts(mobject):
|
|
|
|
key = self.get_mobject_key(sm)
|
2021-01-04 23:09:29 -08:00
|
|
|
if key not in shape_map:
|
|
|
|
shape_map[key] = VGroup()
|
|
|
|
shape_map[key].add(sm)
|
|
|
|
return shape_map
|
|
|
|
|
|
|
|
def clean_up_from_scene(self, scene):
|
|
|
|
for anim in self.animations:
|
|
|
|
anim.update(0)
|
|
|
|
scene.remove(self.mobject)
|
|
|
|
scene.remove(self.to_remove)
|
|
|
|
scene.add(self.to_add)
|
2021-01-05 18:03:06 -08:00
|
|
|
|
|
|
|
def get_mobject_parts(self, mobject):
|
|
|
|
# To be implemented in subclass
|
|
|
|
return mobject
|
|
|
|
|
|
|
|
def get_mobject_key(self, mobject):
|
|
|
|
# To be implemented in subclass
|
|
|
|
return hash(mobject)
|
|
|
|
|
|
|
|
|
|
|
|
class TransformMatchingShapes(TransformMatchingParts):
|
|
|
|
CONFIG = {
|
|
|
|
"mobject_type": VMobject,
|
|
|
|
"group_type": VGroup,
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_mobject_parts(self, mobject):
|
|
|
|
return mobject.family_members_with_points()
|
|
|
|
|
|
|
|
def get_mobject_key(self, mobject):
|
|
|
|
return hash(mobject.get_triangulation().tobytes())
|
|
|
|
|
|
|
|
|
|
|
|
class TransformMatchingTex(TransformMatchingParts):
|
|
|
|
CONFIG = {
|
|
|
|
"mobject_type": TexMobject,
|
|
|
|
"group_type": VGroup,
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_mobject_parts(self, mobject):
|
|
|
|
return mobject.submobjects
|
|
|
|
|
|
|
|
def get_mobject_key(self, mobject):
|
|
|
|
return mobject.get_tex_string()
|