Skip to content

Commit

Permalink
Merge branch 'main' into tex-typing
Browse files Browse the repository at this point in the history
  • Loading branch information
chopan050 authored Nov 27, 2024
2 parents 1b59bc1 + f81d571 commit 6552eb5
Show file tree
Hide file tree
Showing 19 changed files with 1,181 additions and 155 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ repos:
- id: check-toml
name: Validate Poetry
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
rev: v0.8.0
hooks:
- id: ruff
name: ruff lint
Expand All @@ -22,7 +22,7 @@ repos:
- id: ruff-format
types: [python]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.12.1
rev: v1.13.0
hooks:
- id: mypy
additional_dependencies:
Expand Down
133 changes: 101 additions & 32 deletions manim/animation/animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
from .. import config, logger
from ..constants import RendererType
from ..mobject import mobject
from ..mobject.mobject import Mobject
from ..mobject.mobject import Group, Mobject
from ..mobject.opengl import opengl_mobject
from ..utils.rate_functions import linear, smooth

__all__ = ["Animation", "Wait", "override_animation"]
__all__ = ["Animation", "Wait", "Add", "override_animation"]


from collections.abc import Iterable, Sequence
from copy import deepcopy
from functools import partialmethod
from typing import TYPE_CHECKING, Callable
from typing import TYPE_CHECKING, Any, Callable

from typing_extensions import Self

Expand Down Expand Up @@ -172,6 +172,19 @@ def __init__(
),
)

@property
def run_time(self) -> float:
return self._run_time

@run_time.setter
def run_time(self, value: float) -> None:
if value < 0:
raise ValueError(
f"The run_time of {self.__class__.__name__} cannot be "
f"negative. The given value was {value}."
)
self._run_time = value

def _typecheck_input(self, mobject: Mobject | None) -> None:
if mobject is None:
logger.debug("Animation with empty mobject")
Expand All @@ -194,7 +207,6 @@ def begin(self) -> None:
method.
"""
self.run_time = validate_run_time(self.run_time, str(self))
self.starting_mobject = self.create_starting_mobject()
if self.suspend_mobject_updating:
# All calls to self.mobject's internal updaters
Expand Down Expand Up @@ -569,33 +581,6 @@ def prepare_animation(
raise TypeError(f"Object {anim} cannot be converted to an animation")


def validate_run_time(
run_time: float, caller_name: str, parameter_name: str = "run_time"
) -> float:
if run_time <= 0:
raise ValueError(
f"{caller_name} has a {parameter_name} of {run_time:g} <= 0 "
f"seconds which Manim cannot render. Please set the "
f"{parameter_name} to a positive number."
)

# config.frame_rate holds the number of frames per second
fps = config.frame_rate
seconds_per_frame = 1 / fps
if run_time < seconds_per_frame:
logger.warning(
f"The original {parameter_name} of {caller_name}, {run_time:g} "
f"seconds, is too short for the current frame rate of {fps:g} "
f"FPS. Rendering with the shortest possible {parameter_name} of "
f"{seconds_per_frame:g} seconds instead."
)
new_run_time = seconds_per_frame
else:
new_run_time = run_time

return new_run_time


class Wait(Animation):
"""A "no operation" animation.
Expand Down Expand Up @@ -638,7 +623,91 @@ def __init__(
self.mobject.shader_wrapper_list = []

def begin(self) -> None:
self.run_time = validate_run_time(self.run_time, str(self))
pass

def finish(self) -> None:
pass

def clean_up_from_scene(self, scene: Scene) -> None:
pass

def update_mobjects(self, dt: float) -> None:
pass

def interpolate(self, alpha: float) -> None:
pass


class Add(Animation):
"""Add Mobjects to a scene, without animating them in any other way. This
is similar to the :meth:`.Scene.add` method, but :class:`Add` is an
animation which can be grouped into other animations.
Parameters
----------
mobjects
One :class:`~.Mobject` or more to add to a scene.
run_time
The duration of the animation after adding the ``mobjects``. Defaults
to 0, which means this is an instant animation without extra wait time
after adding them.
**kwargs
Additional arguments to pass to the parent :class:`Animation` class.
Examples
--------
.. manim:: DefaultAddScene
class DefaultAddScene(Scene):
def construct(self):
text_1 = Text("I was added with Add!")
text_2 = Text("Me too!")
text_3 = Text("And me!")
texts = VGroup(text_1, text_2, text_3).arrange(DOWN)
rect = SurroundingRectangle(texts, buff=0.5)
self.play(
Create(rect, run_time=3.0),
Succession(
Wait(1.0),
# You can Add a Mobject in the middle of an animation...
Add(text_1),
Wait(1.0),
# ...or multiple Mobjects at once!
Add(text_2, text_3),
),
)
self.wait()
.. manim:: AddWithRunTimeScene
class AddWithRunTimeScene(Scene):
def construct(self):
# A 5x5 grid of circles
circles = VGroup(
*[Circle(radius=0.5) for _ in range(25)]
).arrange_in_grid(5, 5)
self.play(
Succession(
# Add a run_time of 0.2 to wait for 0.2 seconds after
# adding the circle, instead of using Wait(0.2) after Add!
*[Add(circle, run_time=0.2) for circle in circles],
rate_func=smooth,
)
)
self.wait()
"""

def __init__(
self, *mobjects: Mobject, run_time: float = 0.0, **kwargs: Any
) -> None:
mobject = mobjects[0] if len(mobjects) == 1 else Group(*mobjects)
super().__init__(mobject, run_time=run_time, introducer=True, **kwargs)

def begin(self) -> None:
pass

def finish(self) -> None:
pass
Expand Down
10 changes: 5 additions & 5 deletions manim/animation/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import numpy as np

from manim._config import config
from manim.animation.animation import Animation, prepare_animation, validate_run_time
from manim.animation.animation import Animation, prepare_animation
from manim.constants import RendererType
from manim.mobject.mobject import Group, Mobject
from manim.mobject.opengl.opengl_mobject import OpenGLGroup
Expand Down Expand Up @@ -87,7 +87,6 @@ def begin(self) -> None:
f"Trying to play {self} without animations, this is not supported. "
"Please add at least one subanimation."
)
self.run_time = validate_run_time(self.run_time, str(self))
self.anim_group_time = 0.0
if self.suspend_mobject_updating:
self.group.suspend_updating()
Expand Down Expand Up @@ -175,11 +174,13 @@ def interpolate(self, alpha: float) -> None:
]

run_times = to_update["end"] - to_update["start"]
with_zero_run_time = run_times == 0
run_times[with_zero_run_time] = 1
sub_alphas = (anim_group_time - to_update["start"]) / run_times
if time_goes_back:
sub_alphas[sub_alphas < 0] = 0
sub_alphas[(sub_alphas < 0) | with_zero_run_time] = 0
else:
sub_alphas[sub_alphas > 1] = 1
sub_alphas[(sub_alphas > 1) | with_zero_run_time] = 1

for anim_to_update, sub_alpha in zip(to_update["anim"], sub_alphas):
anim_to_update.interpolate(sub_alpha)
Expand Down Expand Up @@ -235,7 +236,6 @@ def begin(self) -> None:
f"Trying to play {self} without animations, this is not supported. "
"Please add at least one subanimation."
)
self.run_time = validate_run_time(self.run_time, str(self))
self.update_active_animation(0)

def finish(self) -> None:
Expand Down
Loading

0 comments on commit 6552eb5

Please sign in to comment.