Skip to content
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

Overloading operators for MVariable, MArray and MArrayPointer classes. #18

Open
drageelr opened this issue Feb 22, 2023 Discussed in #17 · 3 comments
Open

Overloading operators for MVariable, MArray and MArrayPointer classes. #18

drageelr opened this issue Feb 22, 2023 Discussed in #17 · 3 comments
Labels
enhancement New feature or request

Comments

@drageelr
Copy link
Owner

Discussed in #17

Originally posted by ttzytt February 22, 2023
Found some places to improve when using the package to implement the animation of a simple binary search algorithm:

class MyScene(Scene):
    def construct(self):
        arr = MArray(self, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        arr.shift(LEFT * 4 + UP * 2)
        tar_val = MVariable(self, 3, label="target value")
        tar_val.shift(DOWN * 2)
        l = MArrayPointer(self, arr, 0, label="left")
        r = MArrayPointer(self, arr, 9, label="right")

        self.play(Create(arr))
        self.play(Create(tar_val))
        self.play(Create(l))
        self.play(Create(r))

        mid = MArrayPointer(self, arr, (l.fetch_index() + r.fetch_index()) // 2, label="mid")
        self.play(Create(mid))

        # find first larger or equal to target value
        while (l.fetch_index() <= r.fetch_index()):
            anims = []
            if (mid.fetch_index() < tar_val.fetch_value()):
                anims.append(l.shift_to_elem(mid.fetch_index() + 1, play_anim=False))
            else:
                anims.append(r.shift_to_elem(mid.fetch_index() - 1, play_anim=False))
            anims.append(mid.shift_to_elem((l.fetch_index() + r.fetch_index()) // 2, play_anim=False))
            self.play(AnimationGroup(*anims))
            self.wait(1)

For every comparison between MArrayPointer, you have to call fetch_index() to get the position where the array is pointing. I think it will be better to overload comparators in MArrayPointer so that the implementation will be easier.

The same works for other operators like add and subtract: the addition or subtraction between MArrayPointer an integer or another MArrayPointer should give the addition and subtraction between the integer and the index that the pointer is pointing to in a MArray. That way, the operation of pointers will be much easier, and code like the following will be simplified:

r.shift_to_elem(mid.fetch_index() - 1, play_anim=False
mid.shift_to_elem((l.fetch_index() + r.fetch_index()) // 2

Another possible improvement from overloading operators is to overload __getitem__ and __setitem__ for MArray. Using these two methods, we could directly access the MArrayElement inside the MArray through the bracket operator, thus making animations on MArrayElement in an easier way.

I'm not sure about your ideas for these modifications, but if you think they are helpful, I can make a PR on that.

@ttzytt Please provide details for which classes and operators you think should be overloaded.

@drageelr drageelr added the enhancement New feature or request label Feb 22, 2023
@drageelr drageelr moved this to 🆕 New in Manim Data Structures Feb 22, 2023
@drageelr drageelr assigned drageelr and unassigned drageelr Feb 22, 2023
@ttzytt
Copy link

ttzytt commented Feb 23, 2023

Met some problems when trying to implement the __eq__ method for MArrayPointer. If there are no user-defined __eq__ functions for a class, python will use it directly for hashing. And if I implemented this function without implementing __hash__, and try to run the following code:

class MyScene(Scene):
    def construct(self):
        arr = MArray(self, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        arr.shift(LEFT * 4 + UP * 2)
        tar_val = MVariable(self, 3, label="target value")
        tar_val.shift(DOWN * 2)
        l = MArrayPointer(self, arr, 0, label="left")
        r = MArrayPointer(self, arr, 9, label="right")

        self.play(Create(arr))
        self.play(Create(tar_val))
        self.play(Create(l))
        self.play(Create(r))

        mid = MArrayPointer(self, arr, (l + r) // 2, label="mid")
        self.play(Create(mid))

        # find first larger or equal to target value
        while (l <= r):
            anims = []
            if (tar_val > mid):
                anims.append(l.shift_to_elem(mid + 1, play_anim=False))
            else:
                anims.append(r.shift_to_elem(mid - 1, play_anim=False))
            anims.append(mid.shift_to_elem((l + r) // 2, play_anim=False))
            self.play(AnimationGroup(*anims))
            self.wait(1)

The following error is shown:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ E:\pythons\3.11\Lib\site-packages\manim\cli\render\commands.py:115 in render                     │
│                                                                                                  │
│   112 │   │   │   try:                                                                           │
│   113 │   │   │   │   with tempconfig({}):                                                       │
│   114 │   │   │   │   │   scene = SceneClass()                                                   │
│ ❱ 115 │   │   │   │   │   scene.render()                                                         │
│   116 │   │   │   except Exception:                                                              │
│   117 │   │   │   │   error_console.print_exception()                                            │
│   118 │   │   │   │   sys.exit(1)                                                                │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:223 in render                             │
│                                                                                                  │
│    220 │   │   """                                                                               │
│    221 │   │   self.setup()                                                                      │
│    222 │   │   try:                                                                              │
│ ❱  223 │   │   │   self.construct()                                                              │
│    224 │   │   except EndSceneEarlyException:                                                    │
│    225 │   │   │   pass                                                                          │
│    226 │   │   except RerunSceneException as e:                                                  │
│                                                                                                  │
│ E:\prog\python\manim\manim-data-structures\tests\__init__.py:17 in construct                     │
│                                                                                                  │
│   14 │   │   r = MArrayPointer(self, arr, 9, label="right")                                      │
│   15 │   │                                                                                       │
│   16 │   │   self.play(Create(arr))                                                              │
│ ❱ 17 │   │   self.play(Create(tar_val))                                                          │
│   18 │   │   self.play(Create(l))                                                                │
│   19 │   │   self.play(Create(r))                                                                │
│   20                                                                                             │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:1033 in play                              │
│                                                                                                  │
│   1030 │   │   │   return                                                                        │
│   1031 │   │                                                                                     │
│   1032 │   │   start_time = self.renderer.time                                                   │
│ ❱ 1033 │   │   self.renderer.play(self, *args, **kwargs)                                         │
│   1034 │   │   run_time = self.renderer.time - start_time                                        │
│   1035 │   │   if subcaption:                                                                    │
│   1036 │   │   │   if subcaption_duration is None:                                               │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\renderer\cairo_renderer.py:93 in play                    │
│                                                                                                  │
│    90 │   │   )                                                                                  │
│    91 │   │                                                                                      │
│    92 │   │   self.file_writer.begin_animation(not self.skip_animations)                         │
│ ❱  93 │   │   scene.begin_animations()                                                           │
│    94 │   │                                                                                      │
│    95 │   │   # Save a static image, to avoid rendering non moving objects.                      │
│    96 │   │   self.save_static_frame_data(scene, scene.static_mobjects)                          │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:1162 in begin_animations                  │
│                                                                                                  │
│   1159 │   def begin_animations(self) -> None:                                                   │
│   1160 │   │   """Start the animations of the scene."""                                          │
│   1161 │   │   for animation in self.animations:                                                 │
│ ❱ 1162 │   │   │   animation._setup_scene(self)                                                  │
│   1163 │   │   │   animation.begin()                                                             │
│   1164 │   │                                                                                     │
│   1165 │   │   if config.renderer == RendererType.CAIRO:                                         │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:248 in _setup_scene               │
│                                                                                                  │
│   245 │   │   │   return                                                                         │
│   246 │   │   if (                                                                               │
│   247 │   │   │   self.is_introducer()                                                           │
│ ❱ 248 │   │   │   and self.mobject not in scene.get_mobject_family_members()                     │
PS E:\prog\python\manim\manim-data-structures> manim .\tests\__init__.py -pql
Manim Community v0.17.2

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "E:\pythons\3.11\Scripts\manim.exe\__main__.py", line 7, in <module>     
  File "E:\pythons\3.11\Lib\site-packages\click\core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\pythons\3.11\Lib\site-packages\click\core.py", line 1055, in main    
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "E:\pythons\3.11\Lib\site-packages\click\core.py", line 1657, in invoke  
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\pythons\3.11\Lib\site-packages\click\core.py", line 1404, in invoke  
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\pythons\3.11\Lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\pythons\3.11\Lib\site-packages\manim\cli\render\commands.py", line 111, in render
PS E:\prog\python\manim\manim-data-structures> manim .\tests\__init__.py -pql
Manim Community v0.17.2

[02/23/23 14:21:01] INFO     Animation 0 : Using cached data (hash : 4266129954_2149614056_223132457)                                                                     cairo_renderer.py:78
[02/23/23 14:21:02] INFO     Animation 1 : Using cached data (hash : 1442284246_4206486446_917344461)                                                                     cairo_renderer.py:78
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ E:\pythons\3.11\Lib\site-packages\manim\cli\render\commands.py:115 in render                     │
│                                                                                                  │
│   112 │   │   │   try:                                                                           │
│   113 │   │   │   │   with tempconfig({}):                                                       │
│   114 │   │   │   │   │   scene = SceneClass()                                                   │
│ ❱ 115 │   │   │   │   │   scene.render()                                                         │
│   116 │   │   │   except Exception:                                                              │
│   117 │   │   │   │   error_console.print_exception()                                            │
│   118 │   │   │   │   sys.exit(1)                                                                │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:223 in render                             │
│                                                                                                  │
│    220 │   │   """                                                                               │
│    221 │   │   self.setup()                                                                      │
│    222 │   │   try:                                                                              │
│ ❱  223 │   │   │   self.construct()                                                              │
│    224 │   │   except EndSceneEarlyException:                                                    │
│    225 │   │   │   pass                                                                          │
│    226 │   │   except RerunSceneException as e:                                                  │
│                                                                                                  │
│ E:\prog\python\manim\manim-data-structures\tests\__init__.py:18 in construct                     │
│                                                                                                  │
│   15 │   │                                                                                       │
│   16 │   │   self.play(Create(arr))                                                              │
│   17 │   │   self.play(Create(tar_val))                                                          │
│ ❱ 18 │   │   self.play(Create(l))                                                                │
│   19 │   │   self.play(Create(r))                                                                │
│   20 │   │                                                                                       │
│   21 │   │   mid = MArrayPointer(self, arr, (l + r) // 2, label="mid")                           │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:1033 in play                              │
│                                                                                                  │
│   1030 │   │   │   return                                                                        │
│   1031 │   │                                                                                     │
│   1032 │   │   start_time = self.renderer.time                                                   │
│ ❱ 1033 │   │   self.renderer.play(self, *args, **kwargs)                                         │
│   1034 │   │   run_time = self.renderer.time - start_time                                        │
│   1035 │   │   if subcaption:                                                                    │
│   1036 │   │   │   if subcaption_duration is None:                                               │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\renderer\cairo_renderer.py:93 in play                    │
│                                                                                                  │
│    90 │   │   )                                                                                  │
│    91 │   │                                                                                      │
│    92 │   │   self.file_writer.begin_animation(not self.skip_animations)                         │
│ ❱  93 │   │   scene.begin_animations()                                                           │
│    94 │   │                                                                                      │
│    95 │   │   # Save a static image, to avoid rendering non moving objects.                      │
│    96 │   │   self.save_static_frame_data(scene, scene.static_mobjects)                          │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:1162 in begin_animations                  │
│                                                                                                  │
│   1159 │   def begin_animations(self) -> None:                                                   │
│   1160 │   │   """Start the animations of the scene."""                                          │
│   1161 │   │   for animation in self.animations:                                                 │
│ ❱ 1162 │   │   │   animation._setup_scene(self)                                                  │
│   1163 │   │   │   animation.begin()                                                             │
│   1164 │   │                                                                                     │
│   1165 │   │   if config.renderer == RendererType.CAIRO:                                         │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:250 in _setup_scene               │
│                                                                                                  │
│   247 │   │   │   self.is_introducer()                                                           │
│   248 │   │   │   and self.mobject not in scene.get_mobject_family_members()                     │
│   249 │   │   ):                                                                                 │
│ ❱ 250 │   │   │   scene.add(self.mobject)                                                        │
│   251 │                                                                                          │
│   252 │   def create_starting_mobject(self) -> Mobject:                                          │
│   253 │   │   # Keep track of where the mobject starts                                           │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:468 in add                                │
│                                                                                                  │
│    465 │   │   │   self.meshes += new_meshes                                                     │
│    466 │   │   elif config.renderer == RendererType.CAIRO:                                       │
│    467 │   │   │   mobjects = [*mobjects, *self.foreground_mobjects]                             │
│ ❱  468 │   │   │   self.restructure_mobjects(to_remove=mobjects)                                 │
│    469 │   │   │   self.mobjects += mobjects                                                     │
│    470 │   │   │   if self.moving_mobjects:                                                      │
│    471 │   │   │   │   self.restructure_mobjects(                                                │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:602 in restructure_mobjects               │
│                                                                                                  │
│    599 │   │   │   The Scene mobject with restructured Mobjects.                                 │
│    600 │   │   """                                                                               │
│    601 │   │   if extract_families:                                                              │
│ ❱  602 │   │   │   to_remove = extract_mobject_family_members(                                   │
│    603 │   │   │   │   to_remove,                                                                │
│    604 │   │   │   │   use_z_index=self.renderer.camera.use_z_index,                             │
│    605 │   │   │   )                                                                             │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\utils\family.py:37 in extract_mobject_family_members     │
│                                                                                                  │
│   34 │   else:                                                                                   │
│   35 │   │   method = Mobject.get_family                                                         │
│   36 │   extracted_mobjects = remove_list_redundancies(                                          │
│ ❱ 37 │   │   list(it.chain(*(method(m) for m in mobjects))),                                     │
│   38 │   )                                                                                       │
│   39 │   if use_z_index:                                                                         │
│   40 │   │   return sorted(extracted_mobjects, key=lambda m: m.z_index)                          │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\utils\family.py:37 in <genexpr>                          │
│                                                                                                  │
│   34 │   else:                                                                                   │
│   35 │   │   method = Mobject.get_family                                                         │
│   36 │   extracted_mobjects = remove_list_redundancies(                                          │
│ ❱ 37 │   │   list(it.chain(*(method(m) for m in mobjects))),                                     │
│   38 │   )                                                                                       │
│   39 │   if use_z_index:                                                                         │
│   40 │   │   return sorted(extracted_mobjects, key=lambda m: m.z_index)                          │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\mobject\mobject.py:2147 in get_family                    │
│                                                                                                  │
│   2144 │   def get_family(self, recurse=True):                                                   │
│   2145 │   │   sub_families = list(map(Mobject.get_family, self.submobjects))                    │
│   2146 │   │   all_mobjects = [self] + list(it.chain(*sub_families))                             │
│ ❱ 2147 │   │   return remove_list_redundancies(all_mobjects)                                     │
│   2148 │                                                                                         │
│   2149 │   def family_members_with_points(self):                                                 │
│   2150 │   │   return [m for m in self.get_family() if m.get_num_points() > 0]                   │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\utils\iterables.py:230 in remove_list_redundancies       │
│                                                                                                  │
│   227 │   reversed_result = []                                                                   │
│   228 │   used = set()                                                                           │
│   229 │   for x in reversed(lst):                                                                │
│ ❱ 230 │   │   if x not in used:                                                                  │
│   231 │   │   │   reversed_result.append(x)                                                      │
│   232 │   │   │   used.add(x)                                                                    │
│   233 │   reversed_result.reverse()                                                              │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: unhashable type: 'MArrayPointer'

So it seems like somewhere in the Manim library, the hash function is used.

Then I tried to implement the hash function. In my idea, the hash function should return the same value if all the attributes are the same. So I use the following code as my implementation:

    def __key(self) -> tuple:
        # return the tuple of all attributues, used for hashing
        return (self.__scene, self.__arr, self.__index, self.__label, self.__arrow_len, self.__arrow_gap, self.__label_gap,
            self.__pointer_pos, self.__updater_pos 
                )
    def __hash__(self) -> int:
        return hash(self.__key())

And the following error is shown after run the initial code:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ E:\pythons\3.11\Lib\site-packages\manim\cli\render\commands.py:115 in render                     │
│                                                                                                  │
│   112 │   │   │   try:                                                                           │
│   113 │   │   │   │   with tempconfig({}):                                                       │
│   114 │   │   │   │   │   scene = SceneClass()                                                   │
│ ❱ 115 │   │   │   │   │   scene.render()                                                         │
│   116 │   │   │   except Exception:                                                              │
│   117 │   │   │   │   error_console.print_exception()                                            │
│   118 │   │   │   │   sys.exit(1)                                                                │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:223 in render                             │
│                                                                                                  │
│    220 │   │   """                                                                               │
│    221 │   │   self.setup()                                                                      │
│    222 │   │   try:                                                                              │
│ ❱  223 │   │   │   self.construct()                                                              │
│    224 │   │   except EndSceneEarlyException:                                                    │
│    225 │   │   │   pass                                                                          │
│    226 │   │   except RerunSceneException as e:                                                  │
│                                                                                                  │
│ E:\prog\python\manim\manim-data-structures\tests\__init__.py:18 in construct                     │
│                                                                                                  │
│   15 │   │                                                                                       │
│   16 │   │   self.play(Create(arr))                                                              │
│   17 │   │   self.play(Create(tar_val))                                                          │
│ ❱ 18 │   │   self.play(Create(l))                                                                │
│   19 │   │   self.play(Create(r))                                                                │
│   20 │   │                                                                                       │
│   21 │   │   mid = MArrayPointer(self, arr, (l + r) // 2, label="mid")                           │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:1033 in play                              │
│                                                                                                  │
│   1030 │   │   │   return                                                                        │
│   1031 │   │                                                                                     │
│   1032 │   │   start_time = self.renderer.time                                                   │
│ ❱ 1033 │   │   self.renderer.play(self, *args, **kwargs)                                         │
│   1034 │   │   run_time = self.renderer.time - start_time                                        │
│   1035 │   │   if subcaption:                                                                    │
│   1036 │   │   │   if subcaption_duration is None:                                               │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\renderer\cairo_renderer.py:93 in play                    │
│                                                                                                  │
│    90 │   │   )                                                                                  │
│    91 │   │                                                                                      │
│    92 │   │   self.file_writer.begin_animation(not self.skip_animations)                         │
│ ❱  93 │   │   scene.begin_animations()                                                           │
│    94 │   │                                                                                      │
│    95 │   │   # Save a static image, to avoid rendering non moving objects.                      │
│    96 │   │   self.save_static_frame_data(scene, scene.static_mobjects)                          │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\scene\scene.py:1163 in begin_animations                  │
│                                                                                                  │
│   1160 │   │   """Start the animations of the scene."""                                          │
│   1161 │   │   for animation in self.animations:                                                 │
│   1162 │   │   │   animation._setup_scene(self)                                                  │
│ ❱ 1163 │   │   │   animation.begin()                                                             │
│   1164 │   │                                                                                     │
│   1165 │   │   if config.renderer == RendererType.CAIRO:                                         │
│   1166 │   │   │   # Paint all non-moving objects onto the screen, so they don't                 │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:203 in begin                      │
│                                                                                                  │
│   200 │   │   │   # the internal updaters of self.starting_mobject,                              │
│   201 │   │   │   # or any others among self.get_all_mobjects()                                  │
│   202 │   │   │   self.mobject.suspend_updating()                                                │
│ ❱ 203 │   │   self.interpolate(0)                                                                │
│   204 │                                                                                          │
│   205 │   def finish(self) -> None:                                                              │
│   206 │   │   # TODO: begin and finish should require a scene as parameter.                      │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:323 in interpolate                │
│                                                                                                  │
│   320 │   │   │   The relative time to set the animation to, 0 meaning the start, 1 meaning      │
│   321 │   │   │   the end.                                                                       │
│   322 │   │   """                                                                                │
│ ❱ 323 │   │   self.interpolate_mobject(alpha)                                                    │
│   324 │                                                                                          │
│   325 │   def interpolate_mobject(self, alpha: float) -> None:                                   │
│   326 │   │   """Interpolates the mobject of the :class:`Animation` based on alpha value.        │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:335 in interpolate_mobject        │
│                                                                                                  │
│   332 │   │   │   is completed. For example, alpha-values of 0, 0.5, and 1 correspond            │
│   333 │   │   │   to the animation being completed 0%, 50%, and 100%, respectively.              │
│   334 │   │   """                                                                                │
│ ❱ 335 │   │   families = list(self.get_all_families_zipped())                                    │
│   336 │   │   for i, mobs in enumerate(families):                                                │
│   337 │   │   │   sub_alpha = self.get_sub_alpha(alpha, i, len(families))                        │
│   338 │   │   │   self.interpolate_submobject(*mobs, sub_alpha)                                  │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:271 in get_all_families_zipped    │
│                                                                                                  │
│   268 │   def get_all_families_zipped(self) -> Iterable[tuple]:                                  │
│   269 │   │   if config["renderer"] == RendererType.OPENGL:                                      │
│   270 │   │   │   return zip(*(mob.get_family() for mob in self.get_all_mobjects()))             │
│ ❱ 271 │   │   return zip(                                                                        │
│   272 │   │   │   *(mob.family_members_with_points() for mob in self.get_all_mobjects())         │
│   273 │   │   )                                                                                  │
│   274                                                                                            │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\animation\animation.py:272 in <genexpr>                  │
│                                                                                                  │
│   269 │   │   if config["renderer"] == RendererType.OPENGL:                                      │
│   270 │   │   │   return zip(*(mob.get_family() for mob in self.get_all_mobjects()))             │
│   271 │   │   return zip(                                                                        │
│ ❱ 272 │   │   │   *(mob.family_members_with_points() for mob in self.get_all_mobjects())         │
│   273 │   │   )                                                                                  │
│   274 │                                                                                          │
│   275 │   def update_mobjects(self, dt: float) -> None:                                          │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\mobject\mobject.py:2150 in family_members_with_points    │
│                                                                                                  │
│   2147 │   │   return remove_list_redundancies(all_mobjects)                                     │
│   2148 │                                                                                         │
│   2149 │   def family_members_with_points(self):                                                 │
│ ❱ 2150 │   │   return [m for m in self.get_family() if m.get_num_points() > 0]                   │
│   2151 │                                                                                         │
│   2152 │   def arrange(                                                                          │
│   2153 │   │   self,                                                                             │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\mobject\mobject.py:2147 in get_family                    │
│                                                                                                  │
│   2144 │   def get_family(self, recurse=True):                                                   │
│   2145 │   │   sub_families = list(map(Mobject.get_family, self.submobjects))                    │
│   2146 │   │   all_mobjects = [self] + list(it.chain(*sub_families))                             │
│ ❱ 2147 │   │   return remove_list_redundancies(all_mobjects)                                     │
│   2148 │                                                                                         │
│   2149 │   def family_members_with_points(self):                                                 │
│   2150 │   │   return [m for m in self.get_family() if m.get_num_points() > 0]                   │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\utils\iterables.py:230 in remove_list_redundancies       │
│                                                                                                  │
│   227 │   reversed_result = []                                                                   │
│   228 │   used = set()                                                                           │
│   229 │   for x in reversed(lst):                                                                │
│ ❱ 230 │   │   if x not in used:                                                                  │
│   231 │   │   │   reversed_result.append(x)                                                      │
│   232 │   │   │   used.add(x)                                                                    │
│   233 │   reversed_result.reverse()                                                              │
│                                                                                                  │
│ E:\prog\python\manim\manim-data-structures\./src\manim_data_structures\m_array_pointer.py:658 in │
│ __hash__                                                                                         │
│                                                                                                  │
│   655 │   │   │   self.__pointer_pos, self.__updater_pos                                         │
│   656 │   │   │   │   )                                                                          │
│   657 │   def __hash__(self) -> int:                                                             │
│ ❱ 658 │   │   return hash(self.__key())                                                          │
│   659                                                                                            │
│                                                                                                  │
│ E:\prog\python\manim\manim-data-structures\./src\manim_data_structures\m_array_pointer.py:654 in │
│ __key                                                                                            │
│                                                                                                  │
│   651 │                                                                                          │
│   652 │   def __key(self) -> tuple:                                                              │
│   653 │   │   # return the tuple of all attributues, used for hashing                            │
│ ❱ 654 │   │   return (self.__scene, self.__arr, self.__index, self.__label, self.__arrow_len,    │
│   655 │   │   │   self.__pointer_pos, self.__updater_pos                                         │
│   656 │   │   │   │   )                                                                          │
│   657 │   def __hash__(self) -> int:                                                             │
│                                                                                                  │
│ E:\pythons\3.11\Lib\site-packages\manim\mobject\mobject.py:660 in __getattr__                    │
│                                                                                                  │
│    657 │   │   │   return types.MethodType(setter, self)                                         │
│    658 │   │                                                                                     │
│    659 │   │   # Unhandled attribute, therefore error                                            │
│ ❱  660 │   │   raise AttributeError(f"{type(self).__name__} object has no attribute '{attr}'")   │
│    661 │                                                                                         │
│    662 │   @property                                                                             │
│    663 │   def width(self):                                                                      │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: MArrayPointer object has no attribute '_MArrayPointer__scene'

Basically it says there is no attributes named __scene.

@ttzytt
Copy link

ttzytt commented Feb 23, 2023

Now I used this implementation in my forked repo:

    def __hash__(self) -> int:
        return id(self)

But the problem is that it will not give the same value even if all the attributes are the same since the address of the object in memory is not the same.

@ttzytt
Copy link

ttzytt commented Feb 23, 2023

So I'm wondering what the correct way of implementing this. if I used id() way, It might be possible that the same thing (but a different object) is being rendered multiple times.

@drageelr drageelr moved this from 🆕 New to 🔖 Ready for review in Manim Data Structures Feb 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: 🔖 Ready for review
2 participants