diff --git a/manim/mobject/value_tracker.py b/manim/mobject/value_tracker.py index 9d81035e89..ff39de2df5 100644 --- a/manim/mobject/value_tracker.py +++ b/manim/mobject/value_tracker.py @@ -4,6 +4,7 @@ __all__ = ["ValueTracker", "ComplexValueTracker"] +from typing import TYPE_CHECKING, Any import numpy as np @@ -11,6 +12,11 @@ from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL from manim.utils.paths import straight_path +if TYPE_CHECKING: + from typing_extensions import Self + + from manim.typing import PathFuncType + class ValueTracker(Mobject, metaclass=ConvertToOpenGL): """A mobject that can be used for tracking (real-valued) parameters. @@ -69,69 +75,93 @@ def construct(self): """ - def __init__(self, value=0, **kwargs): + def __init__(self, value: float = 0, **kwargs: Any) -> None: super().__init__(**kwargs) self.set(points=np.zeros((1, 3))) self.set_value(value) def get_value(self) -> float: """Get the current value of this ValueTracker.""" - return self.points[0, 0] + value: float = self.points[0, 0] + return value - def set_value(self, value: float): - """Sets a new scalar value to the ValueTracker""" + def set_value(self, value: float) -> Self: + """Sets a new scalar value to the ValueTracker.""" self.points[0, 0] = value return self - def increment_value(self, d_value: float): - """Increments (adds) a scalar value to the ValueTracker""" + def increment_value(self, d_value: float) -> Self: + """Increments (adds) a scalar value to the ValueTracker.""" self.set_value(self.get_value() + d_value) return self - def __bool__(self): - """Return whether the value of this value tracker evaluates as true.""" + def __bool__(self) -> bool: + """Return whether the value of this ValueTracker evaluates as true.""" return bool(self.get_value()) - def __iadd__(self, d_value: float): - """adds ``+=`` syntax to increment the value of the ValueTracker""" - self.increment_value(d_value) + def __iadd__(self, d_value: float | Mobject) -> Self: + """adds ``+=`` syntax to increment the value of the ValueTracker.""" + if isinstance(d_value, Mobject): + raise ValueError( + "Cannot increment ValueTracker by a Mobject. Please provide a scalar value." + ) + else: + self.increment_value(d_value) return self - def __ifloordiv__(self, d_value: float): - """Set the value of this value tracker to the floor division of the current value by ``d_value``.""" + def __ifloordiv__(self, d_value: float) -> Self: + """Set the value of this ValueTracker to the floor division of the current value by ``d_value``.""" self.set_value(self.get_value() // d_value) return self - def __imod__(self, d_value: float): - """Set the value of this value tracker to the current value modulo ``d_value``.""" + def __imod__(self, d_value: float) -> Self: + """Set the value of this ValueTracker to the current value modulo ``d_value``.""" self.set_value(self.get_value() % d_value) return self - def __imul__(self, d_value: float): - """Set the value of this value tracker to the product of the current value and ``d_value``.""" + def __imul__(self, d_value: float) -> Self: + """Set the value of this ValueTracker to the product of the current value and ``d_value``.""" self.set_value(self.get_value() * d_value) return self - def __ipow__(self, d_value: float): - """Set the value of this value tracker to the current value raised to the power of ``d_value``.""" + def __ipow__(self, d_value: float) -> Self: + """Set the value of this ValueTracker to the current value raised to the power of ``d_value``.""" self.set_value(self.get_value() ** d_value) return self - def __isub__(self, d_value: float): - """adds ``-=`` syntax to decrement the value of the ValueTracker""" - self.increment_value(-d_value) + def __sub__(self, d_value: float | Mobject) -> Self: + """Decrements the ValueTracker by ``d_value``.""" + if isinstance(d_value, Mobject): + raise ValueError( + "Cannot decrement ValueTracker by a Mobject. Please provide a scalar value." + ) + else: + self.increment_value(-d_value) return self - def __itruediv__(self, d_value: float): - """Sets the value of this value tracker to the current value divided by ``d_value``.""" + def __isub__(self, d_value: float | Mobject) -> Self: + """Adds ``-=`` syntax to decrement the value of the ValueTracker.""" + if isinstance(d_value, Mobject): + raise ValueError( + "Cannot decrement ValueTracker by a Mobject. Please provide a scalar value." + ) + else: + self.increment_value(-d_value) + return self + + def __itruediv__(self, d_value: float) -> Self: + """Sets the value of this ValueTracker to the current value divided by ``d_value``.""" self.set_value(self.get_value() / d_value) return self - def interpolate(self, mobject1, mobject2, alpha, path_func=straight_path()): - """ - Turns self into an interpolation between mobject1 - and mobject2. - """ + def interpolate( + self, + mobject1: Mobject, + mobject2: Mobject, + alpha: float, + path_func: PathFuncType = straight_path(), + ) -> Self: + """Turns ``self`` into an interpolation between ``mobject1`` and ``mobject2``.""" self.set(points=path_func(mobject1.points, mobject2.points, alpha)) return self @@ -139,6 +169,8 @@ def interpolate(self, mobject1, mobject2, alpha, path_func=straight_path()): class ComplexValueTracker(ValueTracker): """Tracks a complex-valued parameter. + The value is internally stored as a points array [a, b, 0]. This can be accessed directly + to represent the value geometrically, see the usage example. When the value is set through :attr:`animate`, the value will take a straight path from the source point to the destination point. @@ -161,16 +193,12 @@ def construct(self): self.play(tracker.animate.set_value(tracker.get_value() / (-2 + 3j))) """ - def get_value(self): - """Get the current value of this value tracker as a complex number. - - The value is internally stored as a points array [a, b, 0]. This can be accessed directly - to represent the value geometrically, see the usage example. - """ + def get_value(self) -> complex: # type: ignore [override] + """Get the current value of this ComplexValueTracker as a complex number.""" return complex(*self.points[0, :2]) - def set_value(self, z): - """Sets a new complex value to the ComplexValueTracker""" - z = complex(z) + def set_value(self, value: complex | float) -> Self: + """Sets a new complex value to the ComplexValueTracker.""" + z = complex(value) self.points[0, :2] = (z.real, z.imag) return self diff --git a/mypy.ini b/mypy.ini index 80571869be..e44852342f 100644 --- a/mypy.ini +++ b/mypy.ini @@ -76,6 +76,9 @@ ignore_errors = False [mypy-manim.mobject.geometry.*] ignore_errors = True +[mypy-manim.mobject.value_tracker] +ignore_errors = False + [mypy-manim.renderer.*] ignore_errors = True