Skip to content

Added :class:~.Unwrite animation class to complement :class:~.Write #1107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 76 additions & 7 deletions manim/animation/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def construct(self):
"Uncreate",
"DrawBorderThenFill",
"Write",
"Unwrite",
"ShowIncreasingSubsets",
"AddTextLetterByLetter",
"ShowSubmobjectsOneByOne",
Expand Down Expand Up @@ -177,7 +178,7 @@ def __init__(
1 - t
),
remover: bool = True,
**kwargs
**kwargs,
) -> None:
super().__init__(mobject, rate_func=rate_func, remover=remover, **kwargs)

Expand All @@ -203,7 +204,7 @@ def __init__(
stroke_color: str = None,
draw_border_animation_config: typing.Dict = {}, # what does this dict accept?
fill_animation_config: typing.Dict = {},
**kwargs
**kwargs,
) -> None:
self._typecheck_input(vmobject)
super().__init__(vmobject, run_time=run_time, rate_func=rate_func, **kwargs)
Expand Down Expand Up @@ -267,7 +268,7 @@ def __init__(
run_time: float = None,
lag_ratio: float = None,
rate_func: typing.Callable[[float], np.ndarray] = linear,
**kwargs
**kwargs,
) -> None:
self.run_time = run_time
self.lag_ratio = lag_ratio
Expand All @@ -291,6 +292,74 @@ def _set_default_config_from_length(self, vmobject: VMobject) -> None:
self.lag_ratio = min(4.0 / length, 0.2)


class Unwrite(Write):
"""Simulate erasing by hand a :class:`~.Text` or a :class:`~.VMobject`.

Parameters
----------
reverse : :class:`bool`
Set True to have the animation start erasing from the last submobject first.

Examples
--------

.. manim:: UnwriteReverseFalse

class UnwriteReverseFalse(Scene):
def construct(self):
text = Tex("Alice and Bob").scale(3)
self.add(text)
self.play(Unwrite(text))

.. manim :: UnwriteReverseTrue

class UnwriteReverseTrue(Scene):
def construct(self):
text = Tex("Alice and Bob").scale(3)
self.add(text)
self.play(Unwrite(text,reverse=True))

"""

def __init__(
self,
vmobject: VMobject,
run_time: float = None,
lag_ratio: float = None,
rate_func: typing.Callable[[float], np.ndarray] = linear,
reverse: bool = False,
**kwargs,
) -> None:

backwards_rate_func = lambda t: -rate_func(t) + 1

self.vmobject = vmobject
self.run_time = run_time
self.lag_ratio = lag_ratio
self.reverse = reverse
self._set_default_config_from_length(vmobject)
super().__init__(
vmobject,
run_time=run_time,
lag_ratio=lag_ratio,
rate_func=backwards_rate_func,
**kwargs,
)

def begin(self) -> None:
if not self.reverse:
self.reverse_submobjects()
super().begin()

def finish(self) -> None:
if not self.reverse:
self.reverse_submobjects()
super().finish()

def reverse_submobjects(self) -> None:
self.vmobject.invert(recursive=True)


class ShowIncreasingSubsets(Animation):
"""Show one submobject at a time, leaving all previous ones displayed on screen.

Expand All @@ -312,7 +381,7 @@ def __init__(
group: Mobject,
suspend_mobject_updating: bool = False,
int_func: typing.Callable[[np.ndarray], np.ndarray] = np.floor,
**kwargs
**kwargs,
) -> None:
self.all_submobs = list(group.submobjects)
self.int_func = int_func
Expand Down Expand Up @@ -351,7 +420,7 @@ def __init__(
rate_func: typing.Callable[[float], float] = linear,
time_per_char: float = 0.1,
run_time: typing.Optional[float] = None,
**kwargs
**kwargs,
) -> None:
# time_per_char must be above 0.06, or the animation won't finish
self.time_per_char = time_per_char
Expand All @@ -376,7 +445,7 @@ def __init__(
self,
group: typing.Iterable[Mobject],
int_func: typing.Callable[[np.ndarray], np.ndarray] = np.ceil,
**kwargs
**kwargs,
) -> None:
new_group = Group(*group)
super().__init__(new_group, int_func=int_func, **kwargs)
Expand All @@ -397,7 +466,7 @@ def __init__(
text_mobject: "Text",
run_time: float = None,
time_per_char: float = 0.06,
**kwargs
**kwargs,
) -> None:
self.time_per_char = time_per_char
tpc = self.time_per_char
Expand Down
6 changes: 6 additions & 0 deletions manim/mobject/mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,12 @@ def shuffle(self, recursive=False):
submob.shuffle(recursive=True)
random.shuffle(self.submobjects)

def invert(self, recursive=False):
if recursive:
for submob in self.submobjects:
submob.invert(recursive=True)
list.reverse(self.submobjects)

# Just here to keep from breaking old scenes.
def arrange_submobjects(self, *args, **kwargs):
return self.arrange(*args, **kwargs)
Expand Down