mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00

* Comment tweak * Directly print traceback Since the shell.showtraceback is giving some issues * Make InteracrtiveSceneEmbed into a class This way it can keep track of it's internal shell; use of get_ipython has a finicky relationship with reloading. * Move remaining checkpoint_paste logic into scene_embed.py This involved making a few context managers for Scene: temp_record, temp_skip, temp_progress_bar, which seem useful in and of themselves. * Change null key to be the empty string * Ensure temporary svg paths for Text are deleted * Remove unused dict_ops.py functions * Remove break_into_partial_movies from file_writer configuration * Rewrite guarantee_existence using Path * Clean up SceneFileWriter It had a number of vestigial functions no longer used, and some setup that could be made more organized. * Remove --save_pngs CLI arg (which did nothing) * Add --subdivide CLI arg * Remove add_extension_if_not_present * Remove get_sorted_integer_files * Have find_file return Path * Minor clean up * Clean up num_tex_symbols * Fix find_file * Minor cleanup for extract_scene.py * Add preview_frame_while_skipping option to scene config * Use shell.showtraceback function * Move keybindings to config, instead of in-place constants * Replace DEGREES -> DEG
123 lines
3 KiB
Python
123 lines
3 KiB
Python
from __future__ import annotations
|
|
|
|
import inspect
|
|
|
|
from manimlib.constants import DEG
|
|
from manimlib.constants import RIGHT
|
|
from manimlib.mobject.mobject import Mobject
|
|
from manimlib.utils.simple_functions import clip
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from typing import Callable
|
|
|
|
import numpy as np
|
|
|
|
from manimlib.animation.animation import Animation
|
|
|
|
|
|
def assert_is_mobject_method(method):
|
|
assert inspect.ismethod(method)
|
|
mobject = method.__self__
|
|
assert isinstance(mobject, Mobject)
|
|
|
|
|
|
def always(method, *args, **kwargs):
|
|
assert_is_mobject_method(method)
|
|
mobject = method.__self__
|
|
func = method.__func__
|
|
mobject.add_updater(lambda m: func(m, *args, **kwargs))
|
|
return mobject
|
|
|
|
|
|
def f_always(method, *arg_generators, **kwargs):
|
|
"""
|
|
More functional version of always, where instead
|
|
of taking in args, it takes in functions which output
|
|
the relevant arguments.
|
|
"""
|
|
assert_is_mobject_method(method)
|
|
mobject = method.__self__
|
|
func = method.__func__
|
|
|
|
def updater(mob):
|
|
args = [
|
|
arg_generator()
|
|
for arg_generator in arg_generators
|
|
]
|
|
func(mob, *args, **kwargs)
|
|
|
|
mobject.add_updater(updater)
|
|
return mobject
|
|
|
|
|
|
def always_redraw(func: Callable[..., Mobject], *args, **kwargs) -> Mobject:
|
|
mob = func(*args, **kwargs)
|
|
mob.add_updater(lambda m: mob.become(func(*args, **kwargs)))
|
|
return mob
|
|
|
|
|
|
def always_shift(
|
|
mobject: Mobject,
|
|
direction: np.ndarray = RIGHT,
|
|
rate: float = 0.1
|
|
) -> Mobject:
|
|
mobject.add_updater(
|
|
lambda m, dt: m.shift(dt * rate * direction)
|
|
)
|
|
return mobject
|
|
|
|
|
|
def always_rotate(
|
|
mobject: Mobject,
|
|
rate: float = 20 * DEG,
|
|
**kwargs
|
|
) -> Mobject:
|
|
mobject.add_updater(
|
|
lambda m, dt: m.rotate(dt * rate, **kwargs)
|
|
)
|
|
return mobject
|
|
|
|
|
|
def turn_animation_into_updater(
|
|
animation: Animation,
|
|
cycle: bool = False,
|
|
**kwargs
|
|
) -> Mobject:
|
|
"""
|
|
Add an updater to the animation's mobject which applies
|
|
the interpolation and update functions of the animation
|
|
|
|
If cycle is True, this repeats over and over. Otherwise,
|
|
the updater will be popped uplon completion
|
|
"""
|
|
mobject = animation.mobject
|
|
animation.update_rate_info(**kwargs)
|
|
animation.suspend_mobject_updating = False
|
|
animation.begin()
|
|
animation.total_time = 0
|
|
|
|
def update(m, dt):
|
|
run_time = animation.get_run_time()
|
|
time_ratio = animation.total_time / run_time
|
|
if cycle:
|
|
alpha = time_ratio % 1
|
|
else:
|
|
alpha = clip(time_ratio, 0, 1)
|
|
if alpha >= 1:
|
|
animation.finish()
|
|
m.remove_updater(update)
|
|
return
|
|
animation.interpolate(alpha)
|
|
animation.update_mobjects(dt)
|
|
animation.total_time += dt
|
|
|
|
mobject.add_updater(update)
|
|
return mobject
|
|
|
|
|
|
def cycle_animation(animation: Animation, **kwargs) -> Mobject:
|
|
return turn_animation_into_updater(
|
|
animation, cycle=True, **kwargs
|
|
)
|