Source code for manim.mobject.value_tracker

"""Simple mobjects that can be used for storing (and updating) a value."""

from __future__ import annotations

__all__ = ["ValueTracker", "ComplexValueTracker"]


import numpy as np

from manim.mobject.mobject import Mobject
from manim.mobject.opengl.opengl_compatibility import ConvertToOpenGL
from manim.utils.paths import straight_path


[docs]class ValueTracker(Mobject, metaclass=ConvertToOpenGL): """A mobject that can be used for tracking (real-valued) parameters. Useful for animating parameter changes. Not meant to be displayed. Instead the position encodes some number, often one which another animation or continual_animation uses for its update function, and by treating it as a mobject it can still be animated and manipulated just like anything else. This value changes continuously when animated using the :attr:`animate` syntax. Examples -------- .. manim:: ValueTrackerExample class ValueTrackerExample(Scene): def construct(self): number_line = NumberLine() pointer = Vector(DOWN) label = MathTex("x").add_updater(lambda m: m.next_to(pointer, UP)) tracker = ValueTracker(0) pointer.add_updater( lambda m: m.next_to( number_line.n2p(tracker.get_value()), UP ) ) self.add(number_line, pointer,label) tracker += 1.5 self.wait(1) tracker -= 4 self.wait(0.5) self.play(tracker.animate.set_value(5)), self.wait(0.5) self.play(tracker.animate.set_value(3)) self.play(tracker.animate.increment_value(-2)) self.wait(0.5) .. note:: You can also link ValueTrackers to updaters. In this case, you have to make sure that the ValueTracker is added to the scene by ``add`` .. manim:: ValueTrackerExample class ValueTrackerExample(Scene): def construct(self): tracker = ValueTracker(0) label = Dot(radius=3).add_updater(lambda x : x.set_x(tracker.get_value())) self.add(label) self.add(tracker) tracker.add_updater(lambda mobject, dt: mobject.increment_value(dt)) self.wait(2) """ def __init__(self, value=0, **kwargs): super().__init__(**kwargs) self.set_points(np.zeros((1, 3))) self.set_value(value)
[docs] def get_value(self) -> float: """Get the current value of this ValueTracker.""" return self.points[0, 0]
[docs] def set_value(self, value: float): """Sets a new scalar value to the ValueTracker""" self.points[0, 0] = value return self
[docs] def increment_value(self, d_value: float): """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.""" 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) 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``.""" 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``.""" 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``.""" 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``.""" 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) return self def __itruediv__(self, d_value: float): """Sets the value of this value tracker to the current value divided by ``d_value``.""" self.set_value(self.get_value() / d_value) return self
[docs] def interpolate(self, mobject1, mobject2, alpha, path_func=straight_path()): """ Turns self into an interpolation between mobject1 and mobject2. """ self.set_points(path_func(mobject1.points, mobject2.points, alpha)) return self
[docs]class ComplexValueTracker(ValueTracker): """Tracks a complex-valued parameter. When the value is set through :attr:`animate`, the value will take a straight path from the source point to the destination point. Examples -------- .. manim:: ComplexValueTrackerExample class ComplexValueTrackerExample(Scene): def construct(self): tracker = ComplexValueTracker(-2+1j) dot = Dot().add_updater( lambda x: x.move_to(tracker.points) ) self.add(NumberPlane(), dot) self.play(tracker.animate.set_value(3+2j)) self.play(tracker.animate.set_value(tracker.get_value() * 1j)) self.play(tracker.animate.set_value(tracker.get_value() - 2j)) self.play(tracker.animate.set_value(tracker.get_value() / (-2 + 3j))) """
[docs] 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.""" return complex(*self.points[0, :2])
[docs] def set_value(self, z): """Sets a new complex value to the ComplexValueTracker""" z = complex(z) self.points[0, :2] = (z.real, z.imag) return self