diff --git a/docs/source/example.rst b/docs/source/example.rst
new file mode 100644
index 0000000..e18653a
--- /dev/null
+++ b/docs/source/example.rst
@@ -0,0 +1,45 @@
+Example Gallery
+===============
+
+.. currentmodule:: manim_data_structures.m_array
+
+Find Pair Sum In Sorted MArray
+------------------------------
+
+The code snippet below uses the famous two pointer technique to find the pair sum ``17`` in the sorted array ``[2, 3, 5, 8, 9, 10, 11]``.
+
+.. manim:: MainScene
+ :quality: low
+
+ from manim_data_structures import *
+
+ class MainScene(Scene):
+ def isPairSumAnim(self, arr, n, val):
+ p_i = MArrayPointer(self, arr, 0, 'i', mob_arrow_args={'color': GREEN}, mob_label_args={'color': GREEN})
+ p_j = MArrayPointer(self, arr, n - 1, 'j', mob_arrow_args={'color': YELLOW}, mob_label_args={'color': YELLOW})
+ pair_sum = MVariable(self, 0, label='Sum')
+ pair_sum.shift(DOWN * 2)
+
+ self.play(Create(pair_sum))
+ self.play(Create(p_i), Create(p_j))
+
+ while (p_i.fetch_index() < p_j.fetch_index()):
+ pair_sum.update_value(arr.fetch_arr()[p_i.fetch_index()] + arr.fetch_arr()[p_j.fetch_index()])
+
+ if (pair_sum.fetch_value() == val):
+ pair_sum.fetch_mob_square().set(fill_color=GREEN)
+ return True
+ elif(pair_sum.fetch_value() < val):
+ p_i.shift_to_elem(p_i.fetch_index() + 1)
+ else:
+ p_j.shift_to_elem(p_j.fetch_index() - 1)
+
+ pair_sum.fetch_mob_square().set(fill_color=RED)
+ return False
+
+ def construct(self):
+ arr = MArray(self, [2, 3, 5, 8, 9, 10, 11], label='Array')
+ arr.shift(UP + LEFT * 2)
+ self.add(arr)
+ self.isPairSumAnim(arr, 7, 17)
+ self.wait(1)
diff --git a/docs/source/guides/arrays.rst b/docs/source/guides/arrays.rst
index 0576856..0b4077e 100644
--- a/docs/source/guides/arrays.rst
+++ b/docs/source/guides/arrays.rst
@@ -13,7 +13,7 @@ The most basic data structure this package provides is the :py:class:`MArray` (s
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.play(Create(arr))
self.wait(1)
@@ -29,7 +29,7 @@ The most basic data structure this package provides is the :py:class:`MArray` (s
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.play(Create(arr))
self.wait(1)
@@ -55,7 +55,7 @@ To animate the :py:class:`MArray`, simply invoke the ``animate`` property as sho
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.play(Create(arr))
self.play(arr.animate.shift(UP * 2 + LEFT * 5))
self.wait(1)
@@ -79,7 +79,7 @@ Moreover, you can also use the :py:func:`MArray.animate_elem` method to animate
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.play(Create(arr))
self.play(arr.animate_elem(1).shift(DOWN))
self.wait(1)
@@ -107,7 +107,7 @@ Lastly, you can also animate the body, value and the index of any element using
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.play(Create(arr))
self.play(
arr.animate_elem_square(1).set_fill(BLACK),
@@ -125,6 +125,7 @@ The :py:class:`MArray` also allows you to alter the way your array looks. While
:linenos:
arr = MArray(
+ self,
[1, 2, 3],
mob_square_args={'fill_color': RED_D},
mob_value_args={'color': BLACK},
@@ -144,6 +145,7 @@ The :py:class:`MArray` also allows you to alter the way your array looks. While
class MyScene(Scene):
def construct(self):
arr = MArray(
+ self,
[1, 2, 3],
mob_square_args={'fill_color': RED_D},
mob_value_args={'color': BLACK},
@@ -166,10 +168,10 @@ To do this, simply pass your preferred direction enum from :py:class:`MArrayDire
class MyScene(Scene):
def construct(self):
- arr_up = MArray([1, 2], arr_dir=MArrayDirection.UP)
- arr_right = MArray([3, 4], arr_dir=MArrayDirection.RIGHT)
- arr_down = MArray([5, 6], arr_dir=MArrayDirection.DOWN)
- arr_left = MArray([7, 8], arr_dir=MArrayDirection.LEFT)
+ arr_up = MArray(self, [1, 2], arr_dir=MArrayDirection.UP)
+ arr_right = MArray(self, [3, 4], arr_dir=MArrayDirection.RIGHT)
+ arr_down = MArray(self, [5, 6], arr_dir=MArrayDirection.DOWN)
+ arr_left = MArray(self, [7, 8], arr_dir=MArrayDirection.LEFT)
self.play(Create(arr_up))
self.play(arr_up.animate.shift(UP * 2))
@@ -194,10 +196,10 @@ To do this, simply pass your preferred direction enum from :py:class:`MArrayDire
class MyScene(Scene):
def construct(self):
- arr_up = MArray([1, 2], arr_dir=MArrayDirection.UP)
- arr_right = MArray([3, 4], arr_dir=MArrayDirection.RIGHT)
- arr_down = MArray([5, 6], arr_dir=MArrayDirection.DOWN)
- arr_left = MArray([7, 8], arr_dir=MArrayDirection.LEFT)
+ arr_up = MArray(self, [1, 2], arr_dir=MArrayDirection.UP)
+ arr_right = MArray(self, [3, 4], arr_dir=MArrayDirection.RIGHT)
+ arr_down = MArray(self, [5, 6], arr_dir=MArrayDirection.DOWN)
+ arr_left = MArray(self, [7, 8], arr_dir=MArrayDirection.LEFT)
self.play(Create(arr_up))
self.play(arr_up.animate.shift(UP * 2))
@@ -226,10 +228,10 @@ Similar to how we specify the growth direction using :py:class:`MArrayDirection`
class MyScene(Scene):
def construct(self):
- arr_label_left = MArray([1, 2, 3], label='Arr')
- arr_label_right = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.RIGHT)
- arr_label_down = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.DOWN)
- arr_label_up = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.UP, arr_label_gap=0.75)
+ arr_label_left = MArray(self, [1, 2, 3], label='Arr')
+ arr_label_right = MArray(self, [1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.RIGHT)
+ arr_label_down = MArray(self, [1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.DOWN)
+ arr_label_up = MArray(self, [1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.UP, arr_label_gap=0.75)
self.play(Create(arr_label_left))
self.play(arr_label_left.animate.shift(UP * 2 + LEFT * 4))
@@ -254,10 +256,10 @@ Similar to how we specify the growth direction using :py:class:`MArrayDirection`
class MyScene(Scene):
def construct(self):
- arr_label_left = MArray([1, 2, 3], label='Arr')
- arr_label_right = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.RIGHT)
- arr_label_down = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.DOWN)
- arr_label_up = MArray([1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.UP, arr_label_gap=0.75)
+ arr_label_left = MArray(self, [1, 2, 3], label='Arr')
+ arr_label_right = MArray(self, [1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.RIGHT)
+ arr_label_down = MArray(self, [1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.DOWN)
+ arr_label_up = MArray(self, [1, 2, 3], label='Arr', arr_label_pos=MArrayDirection.UP, arr_label_gap=0.75)
self.play(Create(arr_label_left))
self.play(arr_label_left.animate.shift(UP * 2 + LEFT * 4))
@@ -287,6 +289,7 @@ Lets say you want to show a 4-byte integer array with its addresses. You can sim
class MyScene(Scene):
def construct(self):
arr = MArray(
+ self,
[1, 2, 3, 4],
index_hex_display=True,
index_offset=4
@@ -307,6 +310,7 @@ Lets say you want to show a 4-byte integer array with its addresses. You can sim
class MyScene(Scene):
def construct(self):
arr = MArray(
+ self,
[1, 2, 3, 4],
index_hex_display=True,
index_offset=4
@@ -325,6 +329,7 @@ Or if you don't want to show the indices at all, simply pass ``True`` as the ``h
class MyScene(Scene):
def construct(self):
arr = MArray(
+ self,
[1, 2, 3, 4],
hide_index=True
)
@@ -344,6 +349,7 @@ Or if you don't want to show the indices at all, simply pass ``True`` as the ``h
class MyScene(Scene):
def construct(self):
arr = MArray(
+ self,
[1, 2, 3, 4],
hide_index=True
)
@@ -365,10 +371,10 @@ For an existing array, you can also append an element simply by invoking the :py
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
+ arr = MArray(self, [1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
self.add(arr)
self.wait(1)
- self.play(*arr.append_elem(4))
+ arr.append_elem(4)
self.wait(1)
.. raw:: html
@@ -383,24 +389,22 @@ For an existing array, you can also append an element simply by invoking the :py
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
+ arr = MArray(self, [1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
self.add(arr)
self.wait(1)
- self.play(*arr.append_elem(4))
+ arr.append_elem(4)
self.wait(1)
.. note::
You can also pass ``mob_*_args`` to this method to customize the inserted element.
-Did you notice the the ``*`` before we invoked the :py:func:`MArray.append_elem` method? Since the method returns a list of :py:class:`manim.Animation` therefore, we unpack it while feeding it to the ``self.play`` method of the ``Scene``.
-
-Moreover, you can also specify the animation that is played for the inserted element via the ``append_anim`` argument. The code snippet below passes the :py:class:`manim.GrowFromCenter` animation to the :py:class:`MArray.append_elem` method:
+Moreover, you can also specify the animation that is played for the inserted element via the ``append_anim`` argument. The code snippet below passes the :py:class:`manim.GrowFromCenter` animation to the :py:func:`MArray.append_elem` method:
.. code-block:: python
:linenos:
- self.play(*arr.append_elem(4, append_anim=GrowFromCenter))
+ arr.append_elem(4, append_anim=GrowFromCenter)
.. raw:: html
@@ -414,10 +418,10 @@ Moreover, you can also specify the animation that is played for the inserted ele
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
+ arr = MArray(self, [1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
self.add(arr)
self.wait(1)
- self.play(*arr.append_elem(4, append_anim=GrowFromCenter))
+ arr.append_elem(4, append_anim=GrowFromCenter)
self.wait(1)
.. currentmodule:: manim_data_structures.m_enum
@@ -426,19 +430,26 @@ Moreover, you can also specify the animation that is played for the inserted ele
You can also specify arguments to the passed animation via the ``append_anim_args`` parameter and also set the target of the animation using the ``append_anim_target`` parameter that takes in :py:class:`MArrayElementComp` enum.
+Did you notice that in both snippets, we didn't pass any animation to our :py:class:`manim.Scene` but the append animation still played? This is thanks to the ``self`` that we pass as the first argument to our :py:class:`MArray` constructor, which is basically a reference to the current :py:class:`manim.Scene`.
+
+However, if you'd like to play the animation yourself, we have got you covered! The :py:func:`MArrayElement` method returns a list of :py:class:`manim.Animation` that you can pass to the :py:func:`manim.Scene.play` method as follows:
+
+.. code-block:: python
+ :linenos:
+
+ self.play(*arr.append_elem(4, play_anim=False))
+
Remove Element
^^^^^^^^^^^^^^
.. currentmodule:: manim_data_structures.m_array
-To remove an element simply invoke the :py:class:`MArray.remove_elem` method with the index of element you wish to remove. The method returns two the removal animation and a function that udpates the indices of the remaining elements.
+To remove an element simply invoke the :py:class:`MArray.remove_elem` method with the index of element you wish to remove.
.. code-block:: python
:linenos:
- (remove_anim, update_indices) = arr.remove_elem(1)
- self.play(remove_anim)
- self.play(*update_indices())
+ arr.remove_elem(1)
.. raw:: html
@@ -452,15 +463,14 @@ To remove an element simply invoke the :py:class:`MArray.remove_elem` method wit
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
+ arr = MArray(self, [1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
self.add(arr)
self.wait(1)
- (remove_anim, update_indices) = arr.remove_elem(1)
- self.play(remove_anim)
- self.play(*update_indices())
+ arr.remove_elem(1)
self.wait(1)
Similar to how you were able to pass the append animation to the :py:class:`MArray.append_elem` function, you can specify two animations for the :py:class:`MArray.remove_elem` method:
+
1. Element removal animation via the ``removal_anim`` parameter.
2. Indices update animation via the ``update_anim`` parameter.
@@ -469,7 +479,7 @@ The code snippet below provides an example:
.. code-block:: python
:linenos:
- (remove_anim, update_indices) = arr.remove_elem(1, removal_anim=ShowPassingFlash , update_anim=Indicate)
+ arr.remove_elem(1, removal_anim=ShowPassingFlash , update_anim=Write)
.. raw:: html
@@ -483,18 +493,25 @@ The code snippet below provides an example:
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
+ arr = MArray(self, [1, 2, 3], label='Array', arr_label_pos=MArrayDirection.DOWN)
self.add(arr)
self.wait(1)
- (remove_anim, update_indices) = arr.remove_elem(1, removal_anim=ShowPassingFlash , update_anim=Indicate)
- self.play(remove_anim)
- self.play(*update_indices())
+ arr.remove_elem(1, removal_anim=ShowPassingFlash , update_anim=Write)
self.wait(1)
.. note::
You can also specify arguments to the passed animation via the ``*_anim_args`` parameter and also set the target of the animation using the ``*_anim_target`` parameter.
+Lastly, as the :py:func:`MArray.append_elem` returns a list of :py:class:`manim.Animation`, the :py:func:`MArray.remove_elem` returns two objects; a removal animation and a function that udpates the indices of the remaining elements and returns their animations. Hence, you can animate this as follows:
+
+.. code-block:: python
+ :linenos:
+
+ (remove_anim, update_indices) = arr.remove_elem(1, removal_anim=ShowPassingFlash , update_anim=Write, play_anim=False)
+ self.play(remove_anim) # Play removal animation first
+ self.play(*update_indices(play_anim=False)) # Then play the update_indices animation
+
Update Element
^^^^^^^^^^^^^^
@@ -505,13 +522,11 @@ You can also update the value and the index of an existing array using the :py:c
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.add(arr)
self.wait(1)
- self.play(
- Write(arr.update_elem_value(1, 20)),
- Write(arr.update_elem_index(1, -2))
- )
+ arr.update_elem_value(1, 20)
+ arr.update_elem_index(1, -2)
self.wait(1)
.. raw:: html
@@ -526,17 +541,67 @@ You can also update the value and the index of an existing array using the :py:c
class MyScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3])
+ arr = MArray(self, [1, 2, 3])
self.add(arr)
self.wait(1)
- self.play(
- Write(arr.update_elem_value(1, 20)),
- Write(arr.update_elem_index(1, -2))
- )
+ arr.update_elem_value(1, 20)
+ arr.update_elem_index(1, -2)
self.wait(1)
.. note::
You can also pass ``mob_value_args`` and ``mob_index_args`` to respective methods to customize the updated element mobject.
+Using MArrayPointer
+~~~~~~~~~~~~~~~~~~~
+
+Thus far, if you had been hoping for a pointer to associate with your array, then your prayers have been answered. The :class:`MArrayPointer` allows you to attach a pointer with your array. The following snippet demonstrates its capabilities:
+
+.. code-block:: python
+ :linenos:
+
+ class MyScene(Scene):
+ def construct(self):
+ arr = MArray(self, [1, 2, 3, 4, 5], label='Array')
+ arr.shift(UP + LEFT * 2)
+ self.add(arr)
+
+ pointer = MArrayPointer(self, arr, 2, 'P')
+ self.play(Create(pointer))
+ self.wait(1)
+ pointer.shift_to_elem(4)
+ self.wait(1)
+ pointer.shift_to_elem(0)
+ self.wait(1)
+ pointer.attach_to_elem(2)
+
+ self.wait(1)
+
+.. raw:: html
+
+
+
+.. manim:: MyScene
+ :hide_source:
+ :quality: low
+
+ from manim_data_structures import *
+
+ class MyScene(Scene):
+ def construct(self):
+ arr = MArray(self, [1, 2, 3, 4, 5], label='Array')
+ arr.shift(UP + LEFT * 2)
+ self.add(arr)
+
+ pointer = MArrayPointer(self, arr, 2, 'P')
+ self.play(Create(pointer))
+ self.wait(1)
+ pointer.shift_to_elem(4)
+ self.wait(1)
+ pointer.shift_to_elem(0)
+ self.wait(1)
+ pointer.attach_to_elem(2)
+
+ self.wait(1)
+
With this we conclude this guide. We hope you found it useful! ✌️
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 9a27f02..55b1f32 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -36,7 +36,7 @@ Variables
class VarScene(Scene):
def construct(self):
- var = MVariable(10, 0, 'Var')
+ var = MVariable(self, 10, 0, 'Var')
self.add(var)
Arrays
@@ -49,7 +49,7 @@ Arrays
class ArrayScene(Scene):
def construct(self):
- arr = MArray([1, 2, 3], label='Arr')
+ arr = MArray(self, [1, 2, 3], label='Arr')
self.add(arr)
Next Steps
@@ -65,5 +65,6 @@ Index
.. toctree::
:maxdepth: 2
+ example
guides/index
reference/index
diff --git a/docs/source/reference/arrays.rst b/docs/source/reference/arrays.rst
index 8b054cf..b73b308 100644
--- a/docs/source/reference/arrays.rst
+++ b/docs/source/reference/arrays.rst
@@ -8,3 +8,4 @@ Arrays
~m_array.MArrayElement
~m_array.MArray
+ ~m_array.MArrayPointer
diff --git a/src/manim_data_structures/__init__.py b/src/manim_data_structures/__init__.py
index e8d6b71..647d53e 100644
--- a/src/manim_data_structures/__init__.py
+++ b/src/manim_data_structures/__init__.py
@@ -7,6 +7,7 @@
__all__ = [
"MArrayElement",
"MArray",
+ "MArrayPointer",
"MArrayDirection",
"MArrayElementComp",
"MVariable",
diff --git a/src/manim_data_structures/m_array.py b/src/manim_data_structures/m_array.py
index ef555bd..0c4bbbb 100644
--- a/src/manim_data_structures/m_array.py
+++ b/src/manim_data_structures/m_array.py
@@ -1,5 +1,7 @@
"""Contains classes to construct an array."""
+from copy import deepcopy
+
import numpy as np
from manim import *
@@ -11,6 +13,8 @@ class MArrayElement(VGroup):
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
mob_square_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Square` that represents the element body.
mob_value_args : :class:`dict`, default: `{}`
@@ -32,6 +36,8 @@ class MArrayElement(VGroup):
Attributes
----------
+ __scene : :class:`manim.Scene`
+ The scene where the object should exist.
__mob_square_props : :class:`dict`
Default arguments passed to :class:`manim.Square` that represents the element body.
__mob_value_props : :class:`dict`
@@ -48,14 +54,15 @@ class MArrayElement(VGroup):
Specifies the position of :attr:`__mob_index`
__index_gap : :class:`float`
Specifies the distance between :attr:`__mob_square` and :attr:`__mob_index`
- __label_pos : :class:`np.ndarray`, default: `LEFT`
+ __label_pos : :class:`np.ndarray`
Specifies the position of :attr:`__mob_label`
- __label_gap : :class:`float`, default: `0.5`
+ __label_gap : :class:`float`
Specifies the distance between :attr:`__mob_square` and :attr:`__mob_label`
"""
def __init_props(
self,
+ scene: Scene,
index_pos: np.ndarray,
index_gap: float,
label_pos: np.ndarray,
@@ -65,6 +72,8 @@ def __init_props(
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
index_pos : :class:`np.ndarray`
Specifies the position of :attr:`__mob_index`
index_gap : :class:`float`
@@ -84,6 +93,7 @@ def __init_props(
self.__mob_value_props = {"text": "", "color": WHITE, "weight": BOLD}
self.__mob_index_props = {"text": "", "color": BLUE_D, "font_size": 32}
self.__mob_label_props = {"text": "", "color": BLUE_A, "font_size": 38}
+ self.__scene = scene
self.__index_pos = index_pos
self.__index_gap = index_gap
self.__label_pos = label_pos
@@ -178,8 +188,22 @@ def __init_mobs(
)
self.add(self.__mob_label)
+ def __deepcopy__(self, memo):
+ """Deepcopy that excludes attributes specified in `exclude_list`."""
+
+ exclude_list = ["_MArrayElement__scene"]
+
+ cls = self.__class__
+ result = cls.__new__(cls)
+ memo[id(self)] = result
+ for k, v in self.__dict__.items():
+ if k not in exclude_list:
+ setattr(result, k, deepcopy(v, memo))
+ return result
+
def __init__(
self,
+ scene: Scene,
mob_square_args: dict = {},
mob_value_args: dict = {},
mob_index_args: dict = {},
@@ -196,6 +220,8 @@ def __init__(
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
mob_square_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Square` that represents the element body.
mob_value_args : :class:`dict`, default: `{}`
@@ -221,7 +247,7 @@ def __init__(
super().__init__(**kwargs)
# Initialize props
- self.__init_props(index_pos, index_gap, label_pos, label_gap)
+ self.__init_props(scene, index_pos, index_gap, label_pos, label_gap)
# Update props
self.__update_props(
@@ -300,13 +326,28 @@ def fetch_mob(self, mob_target: MArrayElementComp) -> Mobject:
else:
return self
- def update_mob_value(self, mob_value_args: dict = {}) -> Text:
+ def update_mob_value(
+ self,
+ mob_value_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
"""Re-intializes the :class:`manim.Text` that represents the element value.
Parameters
----------
mob_value_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element value.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
Returns
-------
@@ -314,19 +355,48 @@ def update_mob_value(self, mob_value_args: dict = {}) -> Text:
Represents the updated element value.
"""
+ # Update props of mob_value
self.__update_props(mob_value_args=mob_value_args)
+
+ # Remove current mob_value
self.remove(self.__mob_value)
+
+ # Initialize new mob_value
self.__init_mobs(init_value=True)
+
+ # Add new mob_value to group
self.add(self.__mob_value)
+
+ # Animate change
+ if play_anim:
+ self.__scene.play(
+ update_anim(self.__mob_value, **update_anim_args), **play_anim_args
+ )
+
return self.__mob_value
- def update_mob_index(self, mob_index_args: dict = {}) -> Text:
+ def update_mob_index(
+ self,
+ mob_index_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
"""Re-intializes the :class:`manim.Text` that represents the element index.
Parameters
----------
mob_index_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element index.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
Returns
-------
@@ -334,19 +404,48 @@ def update_mob_index(self, mob_index_args: dict = {}) -> Text:
Represents the updated element index.
"""
+ # Update props of mob_index
self.__update_props(mob_index_args=mob_index_args)
+
+ # Remove current mob_index
self.remove(self.__mob_index)
+
+ # Initialize new mob_index
self.__init_mobs(init_index=True)
+
+ # Add new mob_index to group
self.add(self.__mob_index)
+
+ # Animate change
+ if play_anim:
+ self.__scene.play(
+ update_anim(self.__mob_index, **update_anim_args), **play_anim_args
+ )
+
return self.__mob_index
- def update_mob_label(self, mob_label_args: dict = {}) -> Text:
+ def update_mob_label(
+ self,
+ mob_label_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
"""Re-intializes the :class:`manim.Text` that represents the element label.
Parameters
----------
mob_label_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element label.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
Returns
-------
@@ -354,10 +453,24 @@ def update_mob_label(self, mob_label_args: dict = {}) -> Text:
Represents the updated element label.
"""
+ # Update props of mob_label
self.__update_props(mob_label_args=mob_label_args)
+
+ # Remove current mob_label
self.remove(self.__mob_label)
+
+ # Initialize new mob_label
self.__init_mobs(init_label=True)
+
+ # Add new mob_label to group
self.add(self.__mob_label)
+
+ # Animate change
+ if play_anim:
+ self.__scene.play(
+ update_anim(self.__mob_label, **update_anim_args), **play_anim_args
+ )
+
return self.__mob_label
def animate_mob_square(self) -> "_AnimationBuilder": # type: ignore
@@ -410,8 +523,12 @@ class MArray(VGroup):
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
arr : :class:`list`, default: `[]`
Array to represent. Elements must be convertible to :class:`str`.
+ label : :class:`str`, default: `''`
+ Specifies the label of the array.
index_offset : :class:`int`, default: `1`
Difference between successive indices.
index_start : :class:`int`, default: `0`
@@ -422,6 +539,12 @@ class MArray(VGroup):
Specifies whether to display indices or not.
arr_dir : :class:`.m_enum.MArrayDirection`, default: :attr:`.m_enum.MArrayDirection.RIGHT`
Specifies the growing direction of array.
+ arr_label_pos : :class:`.enum.MArrayDirection`, default: :attr:`.m_enum.MArrayDirection.LEFT`
+ Specifies the position of :attr:`__mob_arr_label`.
+ arr_label_gap : :class:`float`, default: `0.5`
+ Specifies the distance between :attr:`__mob_arr` and :attr:`__mob_arr_label`.
+ mob_arr_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the label for :class:`MArray`.
mob_square_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Square` that represents the element body of :class:`MArrayElement`.
mob_value_args : :class:`dict`, default: `{}`
@@ -433,21 +556,30 @@ class MArray(VGroup):
Attributes
----------
+ __scene : :class:`manim.Scene`
+ The scene where the object should exist.
__arr : :class:`list`
Array to represent. Elements must be convertible to :class:`str`.
__mob_arr : List[:class:`MArrayElement`]
Array containing the manim objects.
+ __label : :class:`str`
+ Specifies the label of the array.
__index_offset : :class:`int`
Difference between successive indices.
__index_start : :class:`int`
Starting value of index.
__index_hex_display : :class:`bool`
Displays indices in hex if `True` otherwise in decimal.
- __hide_index : :class:`bool`, default: `False`
+ __hide_index : :class:`bool`
Specifies whether to display indices or not.
- __arr_dir : :class:`.m_enum.MArrayDirection`, default: :attr:`.m_enum.MArrayDirection.RIGHT`
+ __arr_dir : :class:`.m_enum.MArrayDirection`
Specifies the growing direction of array.
- __mob_arr_label_props
+ __arr_label_pos : :class:`.enum.MArrayDirection`
+ Specifies the position of :attr:`__mob_arr_label`.
+ __arr_label_gap : :class:`float`, default: `0.5`
+ Specifies the distance between :attr:`__mob_arr` and :attr:`__mob_arr_label`.
+ __mob_arr_label_props : :class:`dict`
+ Arguments for :class:`manim.Text` that represents the label for :class:`MArray`.
"""
__dir_map = [
@@ -458,32 +590,6 @@ class MArray(VGroup):
]
"""Maps :class:`.m_enum.MArrayDirection` to correct :class:`MArrayElement` placement."""
- def __init_props(self) -> None:
- """Initializes the attributes for the class."""
-
- self.__mob_arr_label_props = {"text": "", "color": BLUE_A, "font_size": 38}
-
- def __update_props(
- self,
- label: str = "",
- mob_arr_label_args: dict = {},
- ) -> None:
- """Updates the attributes of the class.
-
- Parameters
- ----------
- label : :class:`str`, default `''`
- Specifies the textual value for :attr:`__mob_arr_label`
- mob_arr_label_args : :class:`dict`, default: `{}`
- Arguments for :class:`manim.Text` that represents the array label.
- """
-
- self.__mob_arr_label_props["text"] = label
- self.__mob_arr_label_props.update(mob_arr_label_args)
-
- if type(self.__mob_arr_label_props["text"]) != str:
- self.__mob_arr_label_props["text"] = str(self.__mob_arr_label_props["text"])
-
def __sum_elem_len(self, index_start: int, index_end: int) -> int:
"""Sums the length of :class:`manim.Square` elements between the specified bound.
@@ -546,10 +652,12 @@ def __calc_label_pos_and_mob(self) -> typing.Tuple[Square, np.ndarray]:
else:
middle_index = len_before = len_after = 0
if len(self.__mob_arr) > 1:
+ odd_indices = len(self.__mob_arr) % 2 == 1
middle_index = int(len(self.__mob_arr) / 2)
len_before = self.__sum_elem_len(0, middle_index - 1)
len_after = self.__sum_elem_len(
- middle_index + 1, len(self.__mob_arr) - 1
+ middle_index + 1 if odd_indices else middle_index,
+ len(self.__mob_arr) - 1,
)
return (
self.__mob_arr[middle_index].fetch_mob_square(),
@@ -558,27 +666,6 @@ def __calc_label_pos_and_mob(self) -> typing.Tuple[Square, np.ndarray]:
* ((len_after - len_before) / 2),
)
- def __init_mobs(
- self,
- init_arr_label: bool = False,
- ) -> None:
- """Initializes the :class:`Mobject`s for the class.
-
- Parameters
- ----------
- init_arr_label : :class:`bool`, default: `False`
- Instantiates a :class:`manim.Text` and adds it to :attr:`__mob_arr_label`.
- """
-
- if init_arr_label:
- self.__mob_arr_label = Text(**self.__mob_arr_label_props)
- if len(self.__mob_arr):
- (next_to_mob, label_pos) = self.__calc_label_pos_and_mob()
- self.__mob_arr_label.next_to(
- next_to_mob, label_pos, self.__arr_label_gap
- )
- self.add(self.__mob_arr_label)
-
def __calc_index(self, index: int) -> typing.Union[int, str]:
"""Calculates and returns the index based on attributes set at initialization.
@@ -686,6 +773,7 @@ def __append_elem(
mob_index_args["text"] = self.__calc_index(len(self.__mob_arr))
self.__mob_arr.append(
MArrayElement(
+ scene=self.__scene,
mob_square_args=mob_square_args,
mob_value_args=mob_value_args,
mob_index_args=mob_index_args,
@@ -717,12 +805,12 @@ def __remove_elem(
self,
index: int,
removal_anim: Animation = FadeOut,
- update_anim: Animation = Write,
+ update_anim: Animation = Indicate,
removal_anim_args: dict = {},
update_anim_args: dict = {},
removal_anim_target: MArrayElementComp = None,
update_anim_target: MArrayElementComp = MArrayElementComp.INDEX,
- ) -> typing.Tuple[Succession, typing.Callable[[], typing.List[Animation]]]:
+ ) -> typing.Tuple[Succession, typing.Callable[[bool], typing.List[Animation]]]:
"""Removes the :class:`MArrayElement` from :attr:`__mob_arr` at the specified index.
Parameters
@@ -746,7 +834,7 @@ def __remove_elem(
-------
:class:`manim.Succession`
Contains :class:`manim.Animations` played for removal and shifting of :class:`MArrayElement`.
- Callable[[], List[:class:`manim.Animation`]]
+ Callable[[bool], List[:class:`manim.Animation`]]
Method that updates the indices of :class:`MArrayElement`(s) that occur after the removal and returns a list of update :class:`manim.Animation`(s).
"""
@@ -779,9 +867,18 @@ def __remove_elem(
)
)
- def update_indices() -> typing.List[Animation]:
+ def update_indices(
+ play_anim: bool = True, play_anim_args: dict = {}
+ ) -> typing.List[Animation]:
"""Updates the indices of :class:`MArrayElement`(s) that occur after the removal.
+ Parameters
+ ----------
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
+
Returns
-------
List[:class:`manim.Animation`]
@@ -791,7 +888,7 @@ def update_indices() -> typing.List[Animation]:
anims_index = []
for i in range(index, len(self.__mob_arr)):
self.__mob_arr[i].update_mob_index(
- mob_index_args={"text": self.__calc_index(i)}
+ mob_index_args={"text": self.__calc_index(i)}, play_anim=False
)
anims_index.append(
update_anim(
@@ -800,6 +897,9 @@ def update_indices() -> typing.List[Animation]:
)
)
+ if play_anim:
+ self.__scene.play(*anims_index, **play_anim_args)
+
return anims_index
return (
@@ -812,10 +912,126 @@ def update_indices() -> typing.List[Animation]:
update_indices,
)
+ def __init_props(
+ self,
+ scene: Scene,
+ arr: list,
+ label: str,
+ index_offset: int,
+ index_start: int,
+ index_hex_display: bool,
+ hide_index: bool,
+ arr_dir: MArrayDirection,
+ switch_index_pos: bool,
+ arr_label_pos: MArrayDirection,
+ arr_label_gap: float,
+ ) -> None:
+ """Initializes the attributes for the class.
+
+ Parameters
+ ----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
+ arr : :class:`list`
+ Array to represent. Elements must be convertible to :class:`str`.
+ label : :class:`str`
+ Specifies the label of the array.
+ index_offset : :class:`int`
+ Difference between successive indices.
+ index_start : :class:`int`
+ Starting value of index.
+ index_hex_display : :class:`bool`
+ Displays indices in hex if `True` otherwise in decimal.
+ hide_index : :class:`bool`
+ Specifies whether to display indices or not.
+ arr_dir : :class:`.m_enum.MArrayDirection`
+ Specifies the growing direction of array.
+ arr_label_pos : :class:`.enum.MArrayDirection`
+ Specifies the position of :attr:`__mob_arr_label`.
+ arr_label_gap : :class:`float`
+ Specifies the distance between :attr:`__mob_arr` and :attr:`__mob_arr_label`.
+ """
+
+ self.__mob_arr_label_props: dict = {
+ "text": "",
+ "color": BLUE_A,
+ "font_size": 38,
+ }
+ self.__scene: Scene = scene
+ self.__arr: typing.List[Any] = arr
+ self.__label: str = label
+ self.__mob_arr: typing.List[MArrayElement] = []
+ self.__index_offset: int = index_offset
+ self.__index_start: int = index_start
+ self.__index_hex_display: bool = index_hex_display
+ self.__hide_index: int = hide_index
+ self.__arr_dir: MArrayDirection = arr_dir
+ self.__switch_index_pos: bool = switch_index_pos
+ self.__arr_label_pos: MArrayDirection = arr_label_pos
+ self.__arr_label_gap: float = arr_label_gap
+
+ def __update_props(
+ self,
+ mob_arr_label_args: dict = {},
+ ) -> None:
+ """Updates the attributes of the class.
+
+ Parameters
+ ----------
+ mob_arr_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the array label.
+ """
+
+ self.__mob_arr_label_props["text"] = self.__label
+ self.__mob_arr_label_props.update(mob_arr_label_args)
+
+ if type(self.__mob_arr_label_props["text"]) != str:
+ self.__mob_arr_label_props["text"] = str(self.__mob_arr_label_props["text"])
+
+ def __init_mobs(
+ self,
+ init_arr_label: bool = False,
+ ) -> None:
+ """Initializes the :class:`Mobject`s for the class.
+
+ Parameters
+ ----------
+ init_arr_label : :class:`bool`, default: `False`
+ Instantiates a :class:`manim.Text` and adds it to :attr:`__mob_arr_label`.
+ """
+
+ if init_arr_label:
+ self.__mob_arr_label = Text(**self.__mob_arr_label_props)
+ if len(self.__mob_arr):
+ (next_to_mob, label_pos) = self.__calc_label_pos_and_mob()
+ self.__mob_arr_label.next_to(
+ next_to_mob, label_pos, self.__arr_label_gap
+ )
+ if len(self.__mob_arr) % 2 == 0:
+ self.__mob_arr_label.shift(
+ -self.__dir_map[self.__arr_dir.value]["arr"]
+ * (next_to_mob.side_length / 2)
+ )
+ self.add(self.__mob_arr_label)
+
+ def __deepcopy__(self, memo):
+ """Deepcopy that excludes attributes specified in `exclude_list`."""
+
+ exclude_list = ["_MArray__scene"]
+
+ cls = self.__class__
+ result = cls.__new__(cls)
+ memo[id(self)] = result
+ for k, v in self.__dict__.items():
+ if k not in exclude_list:
+ setattr(result, k, deepcopy(v, memo))
+ return result
+
def __init__(
self,
+ scene: Scene,
arr: list = [],
- label="",
+ label: str = "",
index_offset: int = 1,
index_start: int = 0,
index_hex_display: bool = False,
@@ -834,8 +1050,12 @@ def __init__(
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
arr : :class:`list`, default: `[]`
Array to represent. Elements must be convertible to :class:`str`.
+ label : :class:`str`, default: `''`
+ Specifies the label of the array.
index_offset : :class:`int`, default: `1`
Difference between successive indices.
index_start : :class:`int`, default: `0`
@@ -863,20 +1083,26 @@ def __init__(
"""
super().__init__(**kwargs)
- self.__arr = arr
- self.__mob_arr = []
- self.__index_offset = index_offset
- self.__index_start = index_start
- self.__index_hex_display = index_hex_display
- self.__hide_index = hide_index
- self.__arr_dir = arr_dir
- self.__switch_index_pos = switch_index_pos
- self.__arr_label_pos = arr_label_pos
- self.__arr_label_gap = arr_label_gap
-
- self.__init_props()
- self.__update_props(label=label, mob_arr_label_args=mob_arr_label_args)
+ # Initialize props
+ self.__init_props(
+ scene,
+ arr,
+ label,
+ index_offset,
+ index_start,
+ index_hex_display,
+ hide_index,
+ arr_dir,
+ switch_index_pos,
+ arr_label_pos,
+ arr_label_gap,
+ )
+
+ # Update props
+ self.__update_props(mob_arr_label_args)
+
+ # Append elements to __mob_arr
for v in arr:
self.__append_elem(
v,
@@ -886,9 +1112,19 @@ def __init__(
mob_index_args=mob_index_args,
)
+ # Initialize other mobjects (e.g. __arr_label)
self.__init_mobs(True)
- def update_elem_value(self, index: int, value, mob_value_args: dict = {}) -> Text:
+ def update_elem_value(
+ self,
+ index: int,
+ value,
+ mob_value_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
"""Updates the elements value.
Parameters
@@ -899,6 +1135,14 @@ def update_elem_value(self, index: int, value, mob_value_args: dict = {}) -> Tex
New value to be assigned.
mob_value_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element value of :class:`MArrayElement`.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
Returns
-------
@@ -911,9 +1155,20 @@ def update_elem_value(self, index: int, value, mob_value_args: dict = {}) -> Tex
self.__arr[index] = value
mob_value_args["text"] = value
- return self.__mob_arr[index].update_mob_value(mob_value_args)
+ return self.__mob_arr[index].update_mob_value(
+ mob_value_args, update_anim, update_anim_args, play_anim, play_anim_args
+ )
- def update_elem_index(self, index: int, value, mob_index_args: dict = {}) -> Text:
+ def update_elem_index(
+ self,
+ index: int,
+ value,
+ mob_index_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
"""Updates the elements index.
Parameters
@@ -924,6 +1179,14 @@ def update_elem_index(self, index: int, value, mob_index_args: dict = {}) -> Tex
New value to be assigned.
mob_index_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element index of :class:`MArrayElement`.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
Returns
-------
@@ -935,7 +1198,61 @@ def update_elem_index(self, index: int, value, mob_index_args: dict = {}) -> Tex
raise Exception("Index out of bounds!")
mob_index_args["text"] = value
- return self.__mob_arr[index].update_mob_index(mob_index_args)
+ return self.__mob_arr[index].update_mob_index(
+ mob_index_args, update_anim, update_anim_args, play_anim, play_anim_args
+ )
+
+ def update_mob_arr_label(
+ self,
+ label: str,
+ mob_arr_label_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
+ """Re-intializes the :class:`manim.Text` that represents the array label.
+
+ Parameters
+ ----------
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the array label.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
+
+ Returns
+ -------
+ :class:`manim.Text`
+ Represents the updated array label.
+ """
+
+ self.__label = label
+
+ # Update props of mob_label
+ self.__update_props(mob_arr_label_args=mob_arr_label_args)
+
+ # Remove current mob_label
+ self.remove(self.__mob_arr_label)
+
+ # Initialize new mob_label
+ self.__init_mobs(init_arr_label=True)
+
+ # Add new mob_label to group
+ self.add(self.__mob_arr_label)
+
+ # Animate change
+ if play_anim:
+ self.__scene.play(
+ update_anim(self.__mob_arr_label, **update_anim_args), **play_anim_args
+ )
+
+ return self.__mob_arr_label
def animate_elem(self, index: int) -> "_AnimationBuilder": # type: ignore
"""Invokes the :meth:`MArrayElement.animate` property of :class:`MArrayElement` on specified index of :attr:`__mob_arr`.
@@ -1019,6 +1336,8 @@ def append_elem(
append_anim: Animation = Write,
append_anim_args: dict = {},
append_anim_target: MArrayElementComp = None,
+ play_anim: bool = True,
+ play_anim_args: dict = {},
mob_square_args: dict = {},
mob_value_args: dict = {},
mob_index_args: dict = {},
@@ -1035,14 +1354,16 @@ def append_elem(
Arguments for append :class:`manim.Animation`.
append_anim_target : :class:`.m_enum.MArrayElementComp`, default: `None`
Specifies the :class:`manim.Mobject` of the :class:`MArrayElement` on which the append :class:`manim.Animation` is to be played.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
mob_square_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Square` that represents the element body of :class:`MArrayElement`.
mob_value_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element value of :class:`MArrayElement`.
mob_index_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element index of :class:`MArrayElement`.
- shift_label: :class:`bool`, default: `True`
- Specifies whether to shift the :class:`__mob_arr_label` or not.
Returns
-------
@@ -1051,7 +1372,8 @@ def append_elem(
"""
self.__arr.append(value)
- return self.__append_elem(
+
+ anim_list = self.__append_elem(
value,
mob_square_args=mob_square_args,
mob_value_args=mob_value_args,
@@ -1061,16 +1383,23 @@ def append_elem(
append_anim_target=append_anim_target,
)
+ if play_anim:
+ self.__scene.play(*anim_list, **play_anim_args)
+
+ return anim_list
+
def remove_elem(
self,
index,
removal_anim: Animation = FadeOut,
- update_anim: Animation = Write,
+ update_anim: Animation = Indicate,
removal_anim_args: dict = {},
update_anim_args: dict = {},
removal_anim_target: MArrayElementComp = None,
update_anim_target: MArrayElementComp = MArrayElementComp.INDEX,
- ) -> typing.Tuple[Succession, typing.Callable[[], typing.List[Animation]]]:
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> typing.Tuple[Succession, typing.Callable[[bool], typing.List[Animation]]]:
"""Removes the element from :attr:`__arr` and removes :class:`MArrayElement` from :attr:`__mob_arr` at the specified index.
Parameters
@@ -1079,7 +1408,7 @@ def remove_elem(
Index of :class:`MArrayElement` to remove.
removal_anim : :class:`manim.Animation`, default: :class:`manim.FadeOut`
Specifies the :class:`manim.Animation` to be played on the :class:`MArrayElement` being removed.
- update_anim : :class:`manim.Animation`, default: :class:`manim.Write`
+ update_anim : :class:`manim.Animation`, default: :class:`manim.Indicate`
Specifies the :class:`manim.Animation` to be played on the :class:`MArrayElement`(s) after the removed element.
removal_anim_args : :class:`dict`, default: `{}`
Arguments for removal :class:`manim.Animation`.
@@ -1089,12 +1418,16 @@ def remove_elem(
Specifies the :class:`manim.Mobject` of the :class:`MArrayElement` on which the removal :class:`manim.Animation` is to be played.
update_anim_target : :class:`.m_enum.MArrayElementComp`, default: :attr:`.m_enum.MArrayElementComp.INDEX`
Specifies the :class:`manim.Mobject` of the :class:`MArrayElement` on which the update :class:`manim.Animation` is to be played.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
Returns
-------
:class:`manim.Succession`
Contains :class:`manim.Animations` played for removal and shifting of :class:`MArrayElement`.
- Callable[[], List[:class:`manim.Animation`]]
+ Callable[[bool], List[:class:`manim.Animation`]]
Method that updates the indices of :class:`MArrayElement`(s) that occur after the removal and returns a list of update :class:`manim.Animation`(s).
"""
@@ -1103,7 +1436,7 @@ def remove_elem(
self.__arr = self.__arr[0:index] + self.__arr[index + 1 :]
- return self.__remove_elem(
+ (remove_anim, update_indices) = self.__remove_elem(
index,
removal_anim,
update_anim,
@@ -1113,6 +1446,12 @@ def remove_elem(
update_anim_target,
)
+ if play_anim:
+ self.__scene.play(remove_anim, **play_anim_args)
+ update_indices(play_anim_args=play_anim_args)
+
+ return (remove_anim, update_indices)
+
def fetch_arr(self) -> list:
"""Fetches :attr:`__arr`.
@@ -1145,3 +1484,482 @@ def fetch_arr_label(self) -> Text:
"""
return self.__mob_arr_label
+
+ def fetch_arr_dir(self) -> MArrayDirection:
+ """Fetches the :class:`MArrayDirection` that represents the array's growth direction.
+
+ Returns
+ -------
+ :class:`MArrayDirection`
+ Represents the array's growth direction.
+ """
+
+ return self.__arr_dir
+
+
+class MArrayPointer(VGroup):
+ """A class that represents a pointer.
+
+ Parameters
+ ----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
+ arr : typing.List[:class:`MArray`]
+ Array to attach the pointer to.
+ index : :class:`int`, default = `0`
+ Index of the array to attach the pointer to.
+ label : :class:`str`, default: `''`
+ Specifies the label of the pointer.
+ arrow_len : :class:`float`, default: `1`
+ Specifies the length of the arrow.
+ arrow_gap : :class:`float`, default: `0.25`
+ Specifies the distance between the array and the arrow head.
+ label_gap : :class:`float`, default: `0.25`
+ Specifies the distance betweem the label and the arrow tail.
+ pointer_pos : :class:`.m_enum.MArrayDirection`, default: :attr:`.m_enum.MArrayDirection.DOWN`
+ Specifies the poistion of the pointer w.r.t the array.
+ mob_arrow_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Arrow` that represents the arrow for :class:`MArrayPointer`.
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the label for :class:`MArrayPointer`.
+ **kwargs
+ Forwarded to constructor of the parent.
+
+ Attributes
+ ----------
+ __scene : :class:`manim.Scene`
+ The scene where the object should exist.
+ __arr : :class:`list`
+ Array to attach the pointer to.
+ __index : :class:`int`, default = `0`
+ Index of the array to attach the pointer to.
+ __label : :class:`str`, default: `''`
+ Specifies the label of the pointer.
+ __arrow_len : :class:`float`, default: `1`
+ Specifies the length of the arrow.
+ __arrow_gap : :class:`float`, default: `0.25`
+ Specifies the distance between the array and the arrow head.
+ __label_gap : :class:`float`, default: `0.25`
+ Specifies the distance betweem the label and the arrow tail.
+ __pointer_pos : :class:`.m_enum.MArrayDirection`, default: :attr:`.m_enum.MArrayDirection.DOWN`
+ Specifies the poistion of the pointer w.r.t the array.
+ __mob_arrow_props : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Arrow` that represents the arrow for :class:`MArrayPointer`.
+ __mob_label_props : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the label for :class:`MArrayPointer`.
+ __updater_pos : typing.Callable[[], None]
+ Updater function to keep the pointer intact with the array.
+ """
+
+ __dir_map = [
+ {"np": UP, "dir": MArrayDirection.UP},
+ {"np": DOWN, "dir": MArrayDirection.DOWN},
+ {"np": RIGHT, "dir": MArrayDirection.RIGHT},
+ {"np": LEFT, "dir": MArrayDirection.LEFT},
+ ]
+
+ def __calc_arrow_pos(self) -> np.ndarray:
+ """Calculates direction vector for :class:`manim.Arrow`.
+
+ Returns
+ -------
+ :class:`np.ndarray`
+ Position vector for the arrow.
+ """
+
+ arr_dir_np = self.__dir_map[self.__arr.fetch_arr_dir().value]["np"]
+ arrow_pos_np = np.copy(self.__dir_map[self.__pointer_pos.value]["np"])
+
+ # If array's direction and pointer's direction are not perpendicular to each other
+ if np.dot(arr_dir_np, arrow_pos_np):
+ # swap the x and y values of arrow_pos_np
+ arrow_pos_np[0], arrow_pos_np[1] = arrow_pos_np[1], arrow_pos_np[0]
+ # update the __pointer_pos accordingly
+ self.__pointer_pos = self.__dir_map[
+ (self.__pointer_pos.value + 2) % len(self.__dir_map)
+ ]["dir"]
+
+ return arrow_pos_np
+
+ def __add_updater(self) -> None:
+ """Attaches the position updater with the object."""
+
+ def updater_pos(mob: Mobject) -> None:
+ self.__init_pos()
+
+ self.__updater_pos = updater_pos
+
+ self.add_updater(self.__updater_pos)
+
+ def __remove_updater(self) -> None:
+ """Removes the attached updater from the object."""
+
+ self.remove_updater(self.__updater_pos)
+
+ def __calc_shift_np(self, new_index: int) -> np.ndarray:
+ """Calculates how much the pointer should shift by to point to the new index.
+
+ Parameters
+ ----------
+ :class:`int`
+ New index towards which the pointer should point to.
+
+ Returns
+ -------
+ :class:`np.ndarray`
+ A vector that represents how much the pointer should shift.
+ """
+
+ to_lesser_index = False
+ index_start = self.__index
+ index_end = new_index
+ if index_start > index_end:
+ index_start, index_end = index_end, index_start
+ to_lesser_index = True
+
+ return (
+ (
+ self.__arr._MArray__sum_elem_len(index_start, index_end)
+ - (
+ self.__arr.fetch_mob_arr()[self.__index]
+ .fetch_mob_square()
+ .side_length
+ )
+ )
+ * self.__dir_map[self.__arr.fetch_arr_dir().value]["np"]
+ * (-1 if to_lesser_index else 1)
+ )
+
+ def __init_props(
+ self,
+ scene: Scene,
+ arr: MArray,
+ index: int,
+ label: str,
+ arrow_len: float,
+ arrow_gap: float,
+ label_gap: float,
+ pointer_pos: MArrayDirection,
+ ) -> None:
+ """Initializes the attributes for the class.
+
+ Parameters
+ ----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
+ arr : :class:`MArray`
+ Array to attach the pointer to.
+ index : :class:`int`
+ Index of the array to which the pointer is attached.
+ label : :class:`str`
+ Specifies the label of the pointer.
+ arrow_len : :class:`.enum.MArrayDirection`
+ Specifies the length of :class:`manim.Arrow`.
+ arrow_pos_gap : :class:`float`
+ Specifies the distance between :attr:`__mob_arr` and :attr:`__mob_arrow`.
+ label_gap : :class:`float`
+ Specifies the distance between :attr:`__mob_arrow` and :attr:`__mob_label`.
+ pointer_pos : :class:`MArrayDirection`
+ Specifies the position of the pointer.
+ """
+
+ self.__mob_arrow_props: dict = {"color": GOLD_D}
+ self.__mob_label_props: dict = {"text": label, "color": GOLD_A, "font_size": 38}
+ self.__scene: Scene = scene
+ self.__arr: MArray = arr
+ if index >= len(self.__arr.fetch_mob_arr()) or index < 0:
+ raise Exception("Index out of bounds!")
+ self.__index: int = index
+ self.__label: str = label
+ self.__arrow_len: float = arrow_len
+ self.__arrow_gap: float = arrow_gap
+ self.__label_gap: float = label_gap
+ self.__pointer_pos: MArrayDirection = pointer_pos
+
+ def __update_props(self, mob_arrow_args: dict = {}, mob_label_args: dict = {}):
+ """Updates the attributes of the class.
+
+ Parameters
+ ----------
+ mob_arrow_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Arrow` that represents the pointer arrow.
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the pointer label.
+ """
+
+ self.__mob_arrow_props.update(mob_arrow_args)
+ self.__mob_label_props["text"] = self.__label
+ self.__mob_label_props.update(mob_label_args)
+
+ if type(self.__mob_label_props["text"]) != str:
+ self.__mob_label_props["text"] = str(self.__mob_label_props["text"])
+
+ def __init_mobs(self, init_arrow: bool = False, init_label: bool = False):
+ """Initializes the :class:`Mobject`s for the class.
+
+ Parameters
+ ----------
+ init_arrow : :class:`bool`, default: `False`
+ Instantiates a :class:`manim.Arrow` and adds it to :attr:`__mob_arrpw`.
+ init_label : :class:`bool`, default: `False`
+ Instantiates a :class:`manim.Text` and adds it to :attr:`__mob_label`.
+ """
+
+ if init_arrow:
+ arrow_pos_np = self.__calc_arrow_pos()
+ self.__mob_arrow = Arrow(
+ start=(-arrow_pos_np + (arrow_pos_np * self.__arrow_len)),
+ end=-arrow_pos_np,
+ **self.__mob_arrow_props
+ )
+ self.__mob_arrow.next_to(
+ self.__arr.fetch_mob_arr()[self.__index].fetch_mob_square(),
+ arrow_pos_np,
+ self.__arrow_gap,
+ )
+ self.add(self.__mob_arrow)
+
+ if init_label:
+ self.__mob_label = Text(**self.__mob_label_props)
+ self.__mob_label.next_to(
+ self.__mob_arrow,
+ self.__dir_map[self.__pointer_pos.value]["np"],
+ self.__label_gap,
+ )
+ self.add(self.__mob_label)
+
+ def __init_pos(self) -> None:
+ """Initializes the position of the object"""
+
+ arrow_pos_np = self.__calc_arrow_pos()
+ self.next_to(
+ self.__arr.fetch_mob_arr()[self.__index].fetch_mob_square(),
+ arrow_pos_np,
+ self.__arrow_gap,
+ )
+
+ def __deepcopy__(self, memo):
+ """Deepcopy that excludes attributes specified in `exclude_list`."""
+
+ exclude_list = ["_MArrayPointer__scene", "_MArrayPointer__arr"]
+
+ cls = self.__class__
+ result = cls.__new__(cls)
+ memo[id(self)] = result
+ for k, v in self.__dict__.items():
+ if k not in exclude_list:
+ setattr(result, k, deepcopy(v, memo))
+ return result
+
+ def __init__(
+ self,
+ scene: Scene,
+ arr: MArray,
+ index: int = 0,
+ label: str = "",
+ arrow_len: float = 1,
+ arrow_gap: float = 0.25,
+ label_gap: float = 0.25,
+ pointer_pos: MArrayDirection = MArrayDirection.DOWN,
+ mob_arrow_args: dict = {},
+ mob_label_args: dict = {},
+ **kwargs
+ ) -> None:
+ """Initializes the class.
+
+ Parameters
+ ----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
+ arr : typing.List[:class:`MArray`]
+ Array to attach the pointer to.
+ index : :class:`int`, default = `0`
+ Index of the array to attach the pointer to.
+ label : :class:`str`, default: `''`
+ Specifies the label of the pointer.
+ arrow_len : :class:`float`, default: `1`
+ Specifies the length of the arrow.
+ arrow_gap : :class:`float`, default: `0.25`
+ Specifies the distance between the array and the arrow head.
+ label_gap : :class:`float`, default: `0.25`
+ Specifies the distance betweem the label and the arrow tail.
+ pointer_pos : :class:`.m_enum.MArrayDirection`, default: :attr:`.m_enum.MArrayDirection.DOWN`
+ Specifies the poistion of the pointer w.r.t the array.
+ mob_arrow_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Arrow` that represents the arrow for :class:`MArrayPointer`.
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the label for :class:`MArrayPointer`.
+ **kwargs
+ Forwarded to constructor of the parent.
+ """
+
+ super().__init__(**kwargs)
+
+ # Initialize props
+ self.__init_props(
+ scene, arr, index, label, arrow_len, arrow_gap, label_gap, pointer_pos
+ )
+
+ # Update props
+ self.__update_props(mob_arrow_args, mob_label_args)
+
+ # Initialize mobjects
+ self.__init_mobs(True, True)
+
+ # Add updater
+ self.__add_updater()
+
+ def shift_to_elem(
+ self, index: int, play_anim: bool = True, play_anim_args: dict = {}
+ ) -> ApplyMethod:
+ """Shifts pointer to the specified element.
+
+ Parameters
+ ----------
+ index : :class:`int`
+ Index of the array to shift the pointer to.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
+
+ Returns
+ -------
+ :class:`manim.ApplyMethod`
+ Represents the shifting animation.
+ """
+
+ if index < 0 or index > len(self.__arr.fetch_mob_arr()):
+ raise Exception("Index out of bounds!")
+
+ shift_anim = ApplyMethod(
+ self.shift, self.__calc_shift_np(index), suspend_mobject_updating=True
+ )
+ self.__index = index
+
+ if play_anim:
+ self.__scene.play(shift_anim, **play_anim_args)
+
+ return shift_anim
+
+ def attach_to_elem(self, index: int) -> None:
+ """Attaches pointer to the specified element.
+
+ Parameters
+ ----------
+ index : :class:`int`
+ Index of the array to shift the pointer to.
+ """
+
+ if index < 0 or index > len(self.__arr.fetch_mob_arr()):
+ raise Exception("Index out of bounds!")
+
+ self.__index = index
+ self.__init_pos()
+
+ def fetch_mob_arrow(self) -> Arrow:
+ """Fetches :attr:`__mob_arrow`.
+
+ Returns
+ -------
+ :class:`manim.Arrow`
+ Represents the arrow stored in :attr:`__mob_arrow`.
+ """
+
+ return self.__mob_arrow
+
+ def fetch_mob_label(self) -> Text:
+ """Fetches the :class:`manim.Text` that represents the pointer label.
+
+ Returns
+ -------
+ :class:`manim.Text`
+ Represents the pointer label.
+ """
+
+ return self.__mob_label
+
+ def fetch_index(self) -> int:
+ """Fetches the index that the pointer is attached to.
+
+ Returns
+ -------
+ :class:`int`
+ Represents the index that the pointer is attached to.
+ """
+
+ return self.__index
+
+ def update_mob_label(
+ self,
+ label: str,
+ mob_label_args: dict = {},
+ update_anim: Animation = Write,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ play_anim_args: dict = {},
+ ) -> Text:
+ """Re-intializes the :class:`manim.Text` that represents the pointer label.
+
+ Parameters
+ ----------
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the pointer label.
+ update_anim : :class:`manim.Animation`, default `manim.Write`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
+ play_anim_args : :class:`dict, default: `{}`
+ Arguments for :meth:`manim.Scene.play`.
+
+ Returns
+ -------
+ :class:`manim.Text`
+ Represents the updated pointer label.
+ """
+
+ self.__label = label
+
+ # Update props of mob_label
+ self.__update_props(mob_label_args=mob_label_args)
+
+ # Remove current mob_label
+ self.remove(self.__mob_label)
+
+ # Initialize new mob_label
+ self.__init_mobs(init_label=True)
+
+ # Add new mob_label to group
+ self.add(self.__mob_label)
+
+ # Animate change
+ if play_anim:
+ self.__scene.play(
+ update_anim(self.__mob_label, **update_anim_args), **play_anim_args
+ )
+
+ return self.__mob_label
+
+ def animate_mob_arrow(self) -> "_AnimationBuilder": # type: ignore
+ """Invokes the :meth:`manim.Arrow.animate` property of :class:`manim.Arrow` for the pointer arrow.
+
+ Returns
+ -------
+ :class:`_AnimationBuilder`
+ Value returned by :meth:`manim.Arrow.animate` property of :class:`manim.Arrow`.
+ """
+
+ return self.__mob_arrow.animate
+
+ def animate_mob_label(self) -> "_AnimationBuilder": # type: ignore
+ """Invokes the :meth:`manim.Text.animate` property of :class:`manim.Text` for the pointer label.
+
+ Returns
+ -------
+ :class:`_AnimationBuilder`
+ Value returned by :meth:`manim.Text.animate` property of :class:`manim.Text`.
+ """
+
+ return self.__mob_label.animate
diff --git a/src/manim_data_structures/m_variable.py b/src/manim_data_structures/m_variable.py
index a5eeca9..c151ffb 100644
--- a/src/manim_data_structures/m_variable.py
+++ b/src/manim_data_structures/m_variable.py
@@ -10,6 +10,8 @@ class MVariable(MArrayElement):
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
value
Specifies the value of the variable.
index
@@ -22,6 +24,8 @@ class MVariable(MArrayElement):
Arguments for :class:`manim.Text` that represents the element value.
mob_index_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element index.
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the element label.
Attributes
----------
@@ -35,9 +39,11 @@ class MVariable(MArrayElement):
def __init__(
self,
+ scene: Scene,
value="",
index="",
label="",
+ mob_square_args: dict = {},
mob_value_args: dict = {},
mob_index_args: dict = {},
mob_label_args: dict = {},
@@ -47,6 +53,8 @@ def __init__(
Parameters
----------
+ scene : :class:`manim.Scene`
+ The scene where the object should exist.
value
Specifies the value of the variable.
index
@@ -59,15 +67,8 @@ def __init__(
Arguments for :class:`manim.Text` that represents the element value.
mob_index_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element index.
-
- Attributes
- ----------
- __value
- Specifies the value of the variable.
- __index
- Specifies the index of the variable.
- __label
- Specifies the label of the variable.
+ mob_label_args : :class:`dict`, default: `{}`
+ Arguments for :class:`manim.Text` that represents the element label.
"""
self.__value = value
@@ -79,6 +80,8 @@ def __init__(
mob_label_args["text"] = label
super().__init__(
+ scene=scene,
+ mob_square_args=mob_square_args,
mob_value_args=mob_value_args,
mob_index_args=mob_index_args,
mob_label_args=mob_label_args,
@@ -118,13 +121,26 @@ def fetch_label(self):
return self.__label
- def update_value(self, value, mob_value_args: dict = {}) -> Text:
+ def update_value(
+ self,
+ value,
+ mob_value_args: dict = {},
+ update_anim: Animation = Indicate,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ ) -> Text:
"""Updates :attr:`__value` and the :class:`manim.Text` that represents the element value.
Parameters
----------
mob_value_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element value.
+ update_anim : :class:`manim.Animation`, default `{manim.Indicate}`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
Returns
-------
@@ -134,15 +150,30 @@ def update_value(self, value, mob_value_args: dict = {}) -> Text:
self.__value = value
mob_value_args["text"] = value
- return self.update_mob_value(mob_value_args)
+ return self.update_mob_value(
+ mob_value_args, update_anim, update_anim_args, play_anim
+ )
- def update_index(self, index, mob_index_args: dict = {}) -> Text:
+ def update_index(
+ self,
+ index,
+ mob_index_args: dict = {},
+ update_anim: Animation = Indicate,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ ) -> Text:
"""Updates :attr:`__index` and the :class:`manim.Text` that represents the element index.
Parameters
----------
mob_index_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element index.
+ update_anim : :class:`manim.Animation`, default `{manim.Indicate}`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
Returns
-------
@@ -152,15 +183,30 @@ def update_index(self, index, mob_index_args: dict = {}) -> Text:
self.__index = index
mob_index_args["text"] = index
- return self.update_mob_index(mob_index_args)
+ return self.update_mob_index(
+ mob_index_args, update_anim, update_anim_args, play_anim
+ )
- def update_label(self, label, mob_label_args: dict = {}) -> Text:
+ def update_label(
+ self,
+ label,
+ mob_label_args: dict = {},
+ update_anim: Animation = Indicate,
+ update_anim_args: dict = {},
+ play_anim: bool = True,
+ ) -> Text:
"""Updates :attr:`__label` and the :class:`manim.Text` that represents the element label.
Parameters
----------
mob_label_args : :class:`dict`, default: `{}`
Arguments for :class:`manim.Text` that represents the element label.
+ update_anim : :class:`manim.Animation`, default `{manim.Indicate}`
+ Animation to be applied to the updated :class:`manim.Text`.
+ update_anim_args : :class:`dict`, default: `{}`
+ Arguments for update :class:`manim.Animation`.
+ play_anim : :class:`bool`, default: `True`
+ Specifies whether to play the update :class:`manim.Animation`.
Returns
-------
@@ -170,4 +216,6 @@ def update_label(self, label, mob_label_args: dict = {}) -> Text:
self.__value = label
mob_label_args["text"] = label
- return self.update_mob_label(mob_label_args)
+ return self.update_mob_label(
+ mob_label_args, update_anim, update_anim_args, play_anim
+ )