Repository: ManimCommunity/manim

Issue:
Using z-order to define layer for Mobjects
Matplotlib has a very nice method to define in which layer objects are shown on the screen with a parameter `zorder`.
![image](https://user-images.githubusercontent.com/44469195/71835887-05095b80-30b3-11ea-9a68-7da6253c6312.png) 
When working with manim, it's sometimes a little tricky to get the layers right, so what about an implementation, where you can write:
```py
d=Dot()
self.add(d, zorder= 1)
```
Furthermore, there could be defaults like:
* Dots at the first layer
* Text & Equations at the second layer
* Shapes on the third layer
* Functions and graphs on the fourth layer.

When I posted this text to the discord server, @eulertour wrote:
> I don't think it would require anything more than sorting scene.mobjects by z-index before rendering each frame
and since its already possible to assign arbitrary attributes to mobjects it may end up being a one-line change


Discussion:
Sounds good to me.

Relatedly, I was under the impression that `mobject.get_z_index_reference_point` had something to do with this, but now I'm not sure what it's supposed to be doing.

See:
https://github.com/manim-kindergarten/manim/commit/dde65b49a61144f4615040031d687038f07e7b64
https://github.com/manim-kindergarten/manim/commit/94675142995b8e9212ec9b784dee1c1da8fb3cc1

If you think this implementation is good, I can try to create a PR.
The name feels a little opaque to me. Maybe it's because I've worked with CSS some, but I find z_order or z_index to make more sense. Thoughts?
I'd preder `z_index` as well

Resolving patch:
diff --git a/manim/camera/camera.py b/manim/camera/camera.py
--- a/manim/camera/camera.py
+++ b/manim/camera/camera.py
@@ -61,6 +61,7 @@ class Camera(object):
         # round z coordinate to nearest hundredth when comparring
         "z_buff_func": lambda m: np.round(m.get_center()[2], 2),
         "cairo_line_width_multiple": 0.01,
+        "use_z_index": True,
     }
 
     def __init__(self, background=None, **kwargs):
@@ -413,6 +414,8 @@ def extract_mobject_family_members(
             method = Mobject.family_members_with_points
         else:
             method = Mobject.get_family
+        if self.use_z_index:
+            mobjects.sort(key=lambda m: m.z_index)
         return remove_list_redundancies(list(
             it.chain(*[method(m) for m in mobjects])
         ))
diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py
--- a/manim/mobject/mobject.py
+++ b/manim/mobject/mobject.py
@@ -34,6 +34,7 @@ class Mobject(Container):
         "name": None,
         "dim": 3,
         "target": None,
+        "z_index": 0,
     }
 
     def __init__(self, **kwargs):
@@ -1119,6 +1120,35 @@ def throw_error_if_no_points(self):
                       "for a Mobject with no points"
             caller_name = sys._getframe(1).f_code.co_name
             raise Exception(message.format(caller_name))
+    
+    # About z-index
+    def set_z_index(self, z_index_value):
+        """Sets the mobject's :attr:`z_index` to the value specified in `z_index_value`.
+
+        Parameters
+        ----------
+        z_index_value : Union[:class:`int`, :class:`float`]
+            The new value of :attr:`z_index` set.
+        
+        Returns
+        -------
+        :class:`Mobject`
+            The Mobject itself, after :attr:`z_index` is set. (Returns `self`.)
+        """
+        self.z_index = z_index_value
+        return self
+    
+    def set_z_index_by_z_coordinate(self):
+        """Sets the mobject's z coordinate to the value of :attr:`z_index`.
+        
+        Returns
+        -------
+        :class:`Mobject`
+            The Mobject itself, after :attr:`z_index` is set. (Returns `self`.)
+        """
+        z_coord = self.get_center()[-1]
+        self.set_z_index(z_coord)
+        return self
 
 
 class Group(Mobject):


Test patch: