Repository: ManimCommunity/manim

Issue:
set_color(COLOR) (and some other methods mostly used for manipulating the size, position etc. of objects on canvas) dont change the attributes associated with the object.
I don't know if this is intentional but the setting methods especially those used for manipulating the position/color of objects on manim canvas don't actually change these attributes. For example, here I am trying to change the color of the TextMobject using set_color() but it is not changing the color property associated with the object although its appearance on the canvas has been changed to the desired color. 
```python
class Testing(Scene):
    def construct(self):
        some_text = TextMobject("This is some text")
        print("Color of the variable before applying set_color(): ",some_text.color)
        self.play(Write(some_text))
        self.wait()
        self.remove(some_text)
        some_text.set_color(GREEN_D)
        print("Color of the variable after applying set_color(): ",some_text.color)
        self.play(ShowCreation(some_text))
        self.wait()
```
Here is the output:
![Testing](https://user-images.githubusercontent.com/12208432/89587884-edb66a80-d85b-11ea-832a-cd2366078cde.gif)

![image](https://user-images.githubusercontent.com/12208432/89588659-86011f00-d85d-11ea-8907-c1b47a6b0731.png)




Discussion:
**UPDATE**
Upon further investigation, the changed color of the object can be retrieved using `object.get_color() ` (Other get methods work fine too). However, the color property of the object still remains unchanged. To fix this, the setters should modify the properties of the object too. I made a small change to the `set_color()` method by adding self.color = color and now it works just as intended.

```
class Testing(Scene):
    def construct(self):
        some_text = TextMobject("This is some text")
        # print("Color of the variable before applying set_color(): ",some_text.color)
        self.play(Write(some_text))
        self.wait()
        self.remove(some_text)
        some_text.set_color(GREEN_D)
        print("Color of the variable using variable.get_color() : ",\
            some_text.get_color())
        print("Color of the variable using variable.color : ",\
            some_text.color)
        self.play(ShowCreation(some_text))
        self.wait()
```
Print statement's output before making the change to `set_color(COLOR)`
![image](https://user-images.githubusercontent.com/12208432/89609260-c332d480-d890-11ea-8545-4c72f1ab7f95.png)
Print statement's output after making the change to `set_color(COLOR)`
![image](https://user-images.githubusercontent.com/12208432/89609403-2cb2e300-d891-11ea-8cab-2dfaf2c1d6aa.png)

`self.color = color` is already there though? What did you change exactly?

https://github.com/ManimCommunity/manim/blob/70c0d53a01ee6cd1da9a74c0338ed404f67b9123/manim/mobject/mobject.py#L579-L591

The vectorized M object class has its own `set_color(COLOR)` method defined where the COLOR passed is not set to the color attribute of the object. Looking at the method resolution order, TextMobject looks for the method `set_color(COLOR)` in VMobject.

https://github.com/ManimCommunity/manim/blob/70c0d53a01ee6cd1da9a74c0338ed404f67b9123/manim/mobject/types/vectorized_mobject.py#L227-L230

![image](https://user-images.githubusercontent.com/12208432/89627006-abb91300-d8b3-11ea-97a9-e179ae398569.png)

@Ammar34 would you be interested in opening a PR for this? :)
> @Ammar34 would you be interested in opening a PR for this? :)

Yes sir. I was a little busy for the past two weeks. I will PR tomorrow if that is okay!
For the record, I strongly suspect that this issue is one of the big causes of the SVG rendering bugs

Resolving patch:
diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py
--- a/manim/mobject/mobject.py
+++ b/manim/mobject/mobject.py
@@ -96,6 +96,9 @@ def add(self, *mobjects):
         ------
         :class:`ValueError`
             When a mobject tries to add itself.
+        :class:`TypeError`
+            When trying to add an object that is not an instance of :class:`Mobject`.
+
 
         Notes
         -----
@@ -130,8 +133,11 @@ def add(self, *mobjects):
             ValueError: Mobject cannot contain self
 
         """
-        if self in mobjects:
-            raise ValueError("Mobject cannot contain self")
+        for m in mobjects:
+            if not isinstance(m, Mobject):
+                raise TypeError("All submobjects must be of type Mobject")
+            if m is self:
+                raise ValueError("Mobject cannot contain self")
         self.submobjects = list_update(self.submobjects, mobjects)
         return self
 
@@ -698,7 +704,7 @@ def set_color(self, color=YELLOW_C, family=True):
         if family:
             for submob in self.submobjects:
                 submob.set_color(color, family=family)
-        self.color = color
+        self.color = Color(color)
         return self
 
     def set_color_by_gradient(self, *colors):
@@ -1242,7 +1248,5 @@ class Group(Mobject):
     """Groups together multiple Mobjects."""
 
     def __init__(self, *mobjects, **kwargs):
-        if not all([isinstance(m, Mobject) for m in mobjects]):
-            raise TypeError("All submobjects must be of type Mobject")
         Mobject.__init__(self, **kwargs)
         self.add(*mobjects)
diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py
--- a/manim/mobject/types/vectorized_mobject.py
+++ b/manim/mobject/types/vectorized_mobject.py
@@ -252,6 +252,7 @@ def match_style(self, vmobject, family=True):
     def set_color(self, color, family=True):
         self.set_fill(color, family=family)
         self.set_stroke(color, family=family)
+        self.color = colour.Color(color)
         return self
 
     def set_opacity(self, opacity, family=True):


Test patch:
diff --git a/tests/test_color.py b/tests/test_color.py
--- a/tests/test_color.py
+++ b/tests/test_color.py
@@ -1,7 +1,7 @@
 import pytest
 import numpy as np
 
-from manim import Camera, Scene, tempconfig, config
+from manim import Mobject, VMobject, Camera, Scene, tempconfig, config, WHITE, BLACK
 
 
 def test_import_color():
@@ -24,3 +24,15 @@ def test_background_color():
     S.camera.background_opacity = 0.5
     S.renderer.update_frame(S)
     assert np.all(S.renderer.get_frame()[0, 0] == np.array([187, 255, 187, 127]))
+
+
+def test_set_color():
+    m = Mobject()
+    assert m.color.hex == "#fff"
+    m.set_color(BLACK)
+    assert m.color.hex == "#000"
+
+    m = VMobject()
+    assert m.color.hex == "#fff"
+    m.set_color(BLACK)
+    assert m.color.hex == "#000"
diff --git a/tests/test_container.py b/tests/test_container.py
--- a/tests/test_container.py
+++ b/tests/test_container.py
@@ -58,6 +58,10 @@ def test_mobject_add():
     with pytest.raises(ValueError):
         obj.add(obj)
 
+    # can only add Mobjects
+    with pytest.raises(TypeError):
+        obj.add("foo")
+
 
 def test_mobject_remove():
     """Test Mobject.remove()."""
diff --git a/tests/test_scene_rendering/test_caching_related.py b/tests/test_scene_rendering/test_caching_related.py
--- a/tests/test_scene_rendering/test_caching_related.py
+++ b/tests/test_scene_rendering/test_caching_related.py
@@ -6,6 +6,7 @@
 from ..utils.video_tester import *
 
 
+@pytest.mark.slow
 @video_comparison(
     "SceneWithMultipleWaitCallsWithNFlag.json",
     "videos/simple_scenes/480p15/SceneWithMultipleWaitCalls.mp4",
@@ -29,6 +30,7 @@ def test_wait_skip(tmp_path, manim_cfg_file, simple_scenes_path):
     assert exit_code == 0, err
 
 
+@pytest.mark.slow
 @video_comparison(
     "SceneWithMultiplePlayCallsWithNFlag.json",
     "videos/simple_scenes/480p15/SceneWithMultipleCalls.mp4",