Skip to content

Commit a93d112

Browse files
authored
Improved setting of OpenGL colors (ManimCommunity#2111)
* Improve setting of opengl colors * Use keyword arguments and move tests to opengl folder
1 parent dd16347 commit a93d112

File tree

4 files changed

+140
-7
lines changed

4 files changed

+140
-7
lines changed

manim/mobject/opengl_mobject.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,10 @@ def set_color(self, color, opacity=None, recurse=True):
13261326
self.set_rgba_array(color, opacity, recurse=False)
13271327
# Recurse to submobjects differently from how set_rgba_array
13281328
# in case they implement set_color differently
1329+
if color is not None:
1330+
self.color = Color(color)
1331+
if opacity is not None:
1332+
self.opacity = opacity
13291333
if recurse:
13301334
for submob in self.submobjects:
13311335
submob.set_color(color, recurse=True)

manim/mobject/types/opengl_vectorized_mobject.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import moderngl
77
import numpy as np
8+
from colour import Color
89

910
from ... import config
1011
from ...constants import *
@@ -152,6 +153,14 @@ def init_colors(self):
152153
return self
153154

154155
def set_fill(self, color=None, opacity=None, recurse=True):
156+
if color is not None:
157+
self.fill_color = Color(color)
158+
if opacity is not None:
159+
self.fill_opacity = opacity
160+
if recurse:
161+
for submobject in self.submobjects:
162+
submobject.set_fill(color, opacity, recurse)
163+
155164
self.set_rgba_array(color, opacity, "fill_rgba", recurse)
156165
return self
157166

@@ -163,6 +172,20 @@ def set_stroke(
163172
background=None,
164173
recurse=True,
165174
):
175+
if color is not None:
176+
self.stroke_color = Color(color)
177+
if opacity is not None:
178+
self.stroke_opacity = opacity
179+
if recurse:
180+
for submobject in self.submobjects:
181+
submobject.set_stroke(
182+
color=color,
183+
width=width,
184+
opacity=opacity,
185+
background=background,
186+
recurse=recurse,
187+
)
188+
166189
self.set_rgba_array(color, opacity, "stroke_rgba", recurse)
167190

168191
if width is not None:
@@ -235,9 +258,12 @@ def match_style(self, vmobject, recurse=True):
235258
sm1.match_style(sm2)
236259
return self
237260

238-
def set_color(self, color, recurse=True):
239-
self.set_fill(color, recurse=recurse)
240-
self.set_stroke(color, recurse=recurse)
261+
def set_color(self, color, opacity=None, recurse=True):
262+
self.color = Color(color)
263+
if opacity is not None:
264+
self.opacity = opacity
265+
self.set_fill(color, opacity=opacity, recurse=recurse)
266+
self.set_stroke(color, opacity=opacity, recurse=recurse)
241267
return self
242268

243269
def set_opacity(self, opacity, recurse=True):

manim/renderer/opengl_renderer.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ def __init__(self, file_writer_class=SceneFileWriter, skip_animations=False):
234234
# Initialize texture map.
235235
self.path_to_texture_id = {}
236236

237+
self._background_color = color_to_rgba(config["background_color"], 1.0)
238+
237239
def init_scene(self, scene):
238240
self.partial_movie_files = []
239241
self.file_writer = self._file_writer_class(
@@ -405,8 +407,7 @@ def play(self, scene, *args, **kwargs):
405407
scene.play_internal()
406408

407409
def clear_screen(self):
408-
window_background_color = color_to_rgba(config["background_color"])
409-
self.frame_buffer_object.clear(*window_background_color)
410+
self.frame_buffer_object.clear(*self.background_color)
410411
self.window.swap_buffers()
411412

412413
def render(self, scene, frame_offset, moving_mobjects):
@@ -424,8 +425,7 @@ def render(self, scene, frame_offset, moving_mobjects):
424425
self.window.swap_buffers()
425426

426427
def update_frame(self, scene):
427-
window_background_color = color_to_rgba(config["background_color"])
428-
self.frame_buffer_object.clear(*window_background_color)
428+
self.frame_buffer_object.clear(*self.background_color)
429429
self.refresh_perspective_uniforms(scene.camera)
430430

431431
for mobject in scene.mobjects:
@@ -531,3 +531,11 @@ def pixel_coords_to_space_coords(self, px, py, relative=False):
531531
# Only scale wrt one axis
532532
scale = fh / ph
533533
return fc + scale * np.array([(px - pw / 2), (py - ph / 2), 0])
534+
535+
@property
536+
def background_color(self):
537+
return self._background_color
538+
539+
@background_color.setter
540+
def background_color(self, value):
541+
self._background_color = color_to_rgba(value, 1.0)

tests/opengl/test_color_opengl.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import numpy as np
2+
3+
from manim import BLACK, PURE_GREEN, Scene
4+
from manim.mobject.opengl_mobject import OpenGLMobject
5+
from manim.mobject.types.opengl_vectorized_mobject import OpenGLVMobject
6+
7+
8+
def test_import_color(using_opengl_renderer):
9+
import manim.utils.color as C
10+
11+
C.WHITE
12+
13+
14+
def test_background_color(using_opengl_renderer):
15+
S = Scene()
16+
S.renderer.background_color = "#ff0000"
17+
S.renderer.update_frame(S)
18+
assert np.all(S.renderer.get_frame()[0, 0] == np.array([255, 0, 0, 255]))
19+
20+
S.renderer.background_color = "#436f80"
21+
S.renderer.update_frame(S)
22+
assert np.all(S.renderer.get_frame()[0, 0] == np.array([67, 111, 128, 255]))
23+
24+
S.renderer.background_color = "#fff"
25+
S.renderer.update_frame(S)
26+
assert np.all(S.renderer.get_frame()[0, 0] == np.array([255, 255, 255, 255]))
27+
28+
29+
def test_set_color(using_opengl_renderer):
30+
m = OpenGLMobject()
31+
assert m.color.hex == "#fff"
32+
np.alltrue(m.rgbas == np.array((0.0, 0.0, 0.0, 1.0)))
33+
34+
m.set_color(BLACK)
35+
assert m.color.hex == "#000"
36+
np.alltrue(m.rgbas == np.array((1.0, 1.0, 1.0, 1.0)))
37+
38+
m.set_color(PURE_GREEN, opacity=0.5)
39+
assert m.color.hex == "#0f0"
40+
np.alltrue(m.rgbas == np.array((0.0, 1.0, 0.0, 0.5)))
41+
42+
m = OpenGLVMobject()
43+
assert m.color.hex == "#fff"
44+
np.alltrue(m.fill_rgba == np.array((0.0, 0.0, 0.0, 1.0)))
45+
np.alltrue(m.stroke_rgba == np.array((0.0, 0.0, 0.0, 1.0)))
46+
47+
m.set_color(BLACK)
48+
assert m.color.hex == "#000"
49+
np.alltrue(m.fill_rgba == np.array((1.0, 1.0, 1.0, 1.0)))
50+
np.alltrue(m.stroke_rgba == np.array((1.0, 1.0, 1.0, 1.0)))
51+
52+
m.set_color(PURE_GREEN, opacity=0.5)
53+
assert m.color.hex == "#0f0"
54+
np.alltrue(m.fill_rgba == np.array((0.0, 1.0, 0.0, 0.5)))
55+
np.alltrue(m.stroke_rgba == np.array((0.0, 1.0, 0.0, 0.5)))
56+
57+
58+
def test_set_fill_color(using_opengl_renderer):
59+
m = OpenGLVMobject()
60+
assert m.fill_color.hex == "#fff"
61+
np.alltrue(m.fill_rgba == np.array((0.0, 1.0, 0.0, 0.5)))
62+
63+
m.set_fill(BLACK)
64+
assert m.fill_color.hex == "#000"
65+
np.alltrue(m.fill_rgba == np.array((1.0, 1.0, 1.0, 1.0)))
66+
67+
m.set_fill(PURE_GREEN, opacity=0.5)
68+
assert m.fill_color.hex == "#0f0"
69+
np.alltrue(m.fill_rgba == np.array((0.0, 1.0, 0.0, 0.5)))
70+
71+
72+
def test_set_stroke_color(using_opengl_renderer):
73+
m = OpenGLVMobject()
74+
assert m.stroke_color.hex == "#fff"
75+
np.alltrue(m.stroke_rgba == np.array((0.0, 1.0, 0.0, 0.5)))
76+
77+
m.set_stroke(BLACK)
78+
assert m.stroke_color.hex == "#000"
79+
np.alltrue(m.stroke_rgba == np.array((1.0, 1.0, 1.0, 1.0)))
80+
81+
m.set_stroke(PURE_GREEN, opacity=0.5)
82+
assert m.stroke_color.hex == "#0f0"
83+
np.alltrue(m.stroke_rgba == np.array((0.0, 1.0, 0.0, 0.5)))
84+
85+
86+
def test_set_fill(using_opengl_renderer):
87+
m = OpenGLMobject()
88+
assert m.color.hex == "#fff"
89+
m.set_color(BLACK)
90+
assert m.color.hex == "#000"
91+
92+
m = OpenGLVMobject()
93+
assert m.color.hex == "#fff"
94+
m.set_color(BLACK)
95+
assert m.color.hex == "#000"

0 commit comments

Comments
 (0)