mirror of
https://github.com/3b1b/manim.git
synced 2025-07-28 04:23:16 +08:00

* Only use -no-pdf for xelatex rendering * Instead of tracking du and dv points on surface, track points off the surface in the normal direction This means that surface shading will not necessarily work well for arbitrary transformations of the surface. But the existing solution was flimsy anyway, and caused annoying issues with singularity points. * Have density of anchor points on arcs depend on arc length * Allow for specifying true normals and orientation of Sphere * Change miter threshold on stroke shader * Add get_start_and_end to DashedLine * Add min_total_width option to DecimalNumber * Have BackgroundRectangle.set_style absorb (and ignore) added configuration Note, this feels suboptimal * Add LineBrace * Update font_size adjustment in Tex * Add scale_factor parameter to BulletedList.fade_all_but * Minor import tweaks * Add play_sound * Small if -> elif update * Always use Group for FadeTransform * Use time_spanned_alpha in ChangingDecimal * Change priority of number_config vs. self.decimal_number_config in NumberLine init * Fix clock animation * Allow sample_coords to be passed into VectorField
215 lines
5.9 KiB
Python
215 lines
5.9 KiB
Python
from __future__ import annotations
|
|
|
|
import numpy as np
|
|
|
|
from manimlib.animation.animation import Animation
|
|
from manimlib.animation.transform import Transform
|
|
from manimlib.constants import ORIGIN
|
|
from manimlib.mobject.types.vectorized_mobject import VMobject
|
|
from manimlib.mobject.mobject import Group
|
|
from manimlib.utils.bezier import interpolate
|
|
from manimlib.utils.rate_functions import there_and_back
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from typing import Callable
|
|
from manimlib.mobject.mobject import Mobject
|
|
from manimlib.scene.scene import Scene
|
|
from manimlib.typing import Vect3
|
|
|
|
|
|
class Fade(Transform):
|
|
def __init__(
|
|
self,
|
|
mobject: Mobject,
|
|
shift: np.ndarray = ORIGIN,
|
|
scale: float = 1,
|
|
**kwargs
|
|
):
|
|
self.shift_vect = shift
|
|
self.scale_factor = scale
|
|
super().__init__(mobject, **kwargs)
|
|
|
|
|
|
class FadeIn(Fade):
|
|
def create_target(self) -> Mobject:
|
|
return self.mobject.copy()
|
|
|
|
def create_starting_mobject(self) -> Mobject:
|
|
start = super().create_starting_mobject()
|
|
start.set_opacity(0)
|
|
start.scale(1.0 / self.scale_factor)
|
|
start.shift(-self.shift_vect)
|
|
return start
|
|
|
|
|
|
class FadeOut(Fade):
|
|
def __init__(
|
|
self,
|
|
mobject: Mobject,
|
|
shift: Vect3 = ORIGIN,
|
|
remover: bool = True,
|
|
final_alpha_value: float = 0.0, # Put it back in original state when done,
|
|
**kwargs
|
|
):
|
|
super().__init__(
|
|
mobject, shift,
|
|
remover=remover,
|
|
final_alpha_value=final_alpha_value,
|
|
**kwargs
|
|
)
|
|
|
|
def create_target(self) -> Mobject:
|
|
result = self.mobject.copy()
|
|
result.set_opacity(0)
|
|
result.shift(self.shift_vect)
|
|
result.scale(self.scale_factor)
|
|
return result
|
|
|
|
|
|
class FadeInFromPoint(FadeIn):
|
|
def __init__(self, mobject: Mobject, point: Vect3, **kwargs):
|
|
super().__init__(
|
|
mobject,
|
|
shift=mobject.get_center() - point,
|
|
scale=np.inf,
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
class FadeOutToPoint(FadeOut):
|
|
def __init__(self, mobject: Mobject, point: Vect3, **kwargs):
|
|
super().__init__(
|
|
mobject,
|
|
shift=point - mobject.get_center(),
|
|
scale=0,
|
|
**kwargs,
|
|
)
|
|
|
|
|
|
class FadeTransform(Transform):
|
|
def __init__(
|
|
self,
|
|
mobject: Mobject,
|
|
target_mobject: Mobject,
|
|
stretch: bool = True,
|
|
dim_to_match: int = 1,
|
|
**kwargs
|
|
):
|
|
self.to_add_on_completion = target_mobject
|
|
self.stretch = stretch
|
|
self.dim_to_match = dim_to_match
|
|
|
|
mobject.save_state()
|
|
super().__init__(Group(mobject, target_mobject.copy()), **kwargs)
|
|
|
|
def begin(self) -> None:
|
|
self.ending_mobject = self.mobject.copy()
|
|
Animation.begin(self)
|
|
# Both 'start' and 'end' consists of the source and target mobjects.
|
|
# At the start, the traget should be faded replacing the source,
|
|
# and at the end it should be the other way around.
|
|
start, end = self.starting_mobject, self.ending_mobject
|
|
for m0, m1 in ((start[1], start[0]), (end[0], end[1])):
|
|
self.ghost_to(m0, m1)
|
|
|
|
def ghost_to(self, source: Mobject, target: Mobject) -> None:
|
|
source.replace(target, stretch=self.stretch, dim_to_match=self.dim_to_match)
|
|
source.set_uniform(**target.get_uniforms())
|
|
source.set_opacity(0)
|
|
|
|
def get_all_mobjects(self) -> list[Mobject]:
|
|
return [
|
|
self.mobject,
|
|
self.starting_mobject,
|
|
self.ending_mobject,
|
|
]
|
|
|
|
def get_all_families_zipped(self) -> zip[tuple[Mobject]]:
|
|
return Animation.get_all_families_zipped(self)
|
|
|
|
def clean_up_from_scene(self, scene: Scene) -> None:
|
|
Animation.clean_up_from_scene(self, scene)
|
|
scene.remove(self.mobject)
|
|
self.mobject[0].restore()
|
|
if not self.remover:
|
|
scene.add(self.to_add_on_completion)
|
|
|
|
|
|
class FadeTransformPieces(FadeTransform):
|
|
def begin(self) -> None:
|
|
self.mobject[0].align_family(self.mobject[1])
|
|
super().begin()
|
|
|
|
def ghost_to(self, source: Mobject, target: Mobject) -> None:
|
|
for sm0, sm1 in zip(source.get_family(), target.get_family()):
|
|
super().ghost_to(sm0, sm1)
|
|
|
|
|
|
class VFadeIn(Animation):
|
|
"""
|
|
VFadeIn and VFadeOut only work for VMobjects,
|
|
"""
|
|
def __init__(self, vmobject: VMobject, suspend_mobject_updating: bool = False, **kwargs):
|
|
super().__init__(
|
|
vmobject,
|
|
suspend_mobject_updating=suspend_mobject_updating,
|
|
**kwargs
|
|
)
|
|
|
|
def interpolate_submobject(
|
|
self,
|
|
submob: VMobject,
|
|
start: VMobject,
|
|
alpha: float
|
|
) -> None:
|
|
submob.set_stroke(
|
|
opacity=interpolate(0, start.get_stroke_opacity(), alpha)
|
|
)
|
|
submob.set_fill(
|
|
opacity=interpolate(0, start.get_fill_opacity(), alpha)
|
|
)
|
|
|
|
|
|
class VFadeOut(VFadeIn):
|
|
def __init__(
|
|
self,
|
|
vmobject: VMobject,
|
|
remover: bool = True,
|
|
final_alpha_value: float = 0.0,
|
|
**kwargs
|
|
):
|
|
super().__init__(
|
|
vmobject,
|
|
remover=remover,
|
|
final_alpha_value=final_alpha_value,
|
|
**kwargs
|
|
)
|
|
|
|
def interpolate_submobject(
|
|
self,
|
|
submob: VMobject,
|
|
start: VMobject,
|
|
alpha: float
|
|
) -> None:
|
|
super().interpolate_submobject(submob, start, 1 - alpha)
|
|
|
|
|
|
class VFadeInThenOut(VFadeIn):
|
|
def __init__(
|
|
self,
|
|
vmobject: VMobject,
|
|
rate_func: Callable[[float], float] = there_and_back,
|
|
remover: bool = True,
|
|
final_alpha_value: float = 0.5,
|
|
**kwargs
|
|
):
|
|
super().__init__(
|
|
vmobject,
|
|
rate_func=rate_func,
|
|
remover=remover,
|
|
final_alpha_value=final_alpha_value,
|
|
**kwargs
|
|
)
|