mirror of
https://github.com/3b1b/manim.git
synced 2025-08-01 17:29:06 +08:00
Bug fixes to new VMobject color model
This commit is contained in:
@ -127,6 +127,8 @@ class Mobject(Container):
|
|||||||
for attr, value in list(self.__dict__.items()):
|
for attr, value in list(self.__dict__.items()):
|
||||||
if isinstance(value, Mobject) and value in family and value is not self:
|
if isinstance(value, Mobject) and value in family and value is not self:
|
||||||
setattr(copy_mobject, attr, value.copy())
|
setattr(copy_mobject, attr, value.copy())
|
||||||
|
if isinstance(value, np.ndarray):
|
||||||
|
setattr(copy_mobject, attr, np.array(value))
|
||||||
return copy_mobject
|
return copy_mobject
|
||||||
|
|
||||||
def deepcopy(self):
|
def deepcopy(self):
|
||||||
|
@ -726,7 +726,7 @@ class Logo(VMobject):
|
|||||||
0, TAU, n_spikes, endpoint=False
|
0, TAU, n_spikes, endpoint=False
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
index = 3 * n_spikes / 4
|
index = (3 * n_spikes) // 4
|
||||||
if radius == radii[0]:
|
if radius == radii[0]:
|
||||||
layer = VGroup(*full_spikes)
|
layer = VGroup(*full_spikes)
|
||||||
layer.rotate(
|
layer.rotate(
|
||||||
@ -773,6 +773,7 @@ class Logo(VMobject):
|
|||||||
fill_color=BLACK,
|
fill_color=BLACK,
|
||||||
fill_opacity=1,
|
fill_opacity=1,
|
||||||
stroke_width=0,
|
stroke_width=0,
|
||||||
|
sheen=0.0
|
||||||
)
|
)
|
||||||
self.add(self.pupil)
|
self.add(self.pupil)
|
||||||
|
|
||||||
|
@ -31,11 +31,10 @@ class VMobject(Mobject):
|
|||||||
"background_stroke_width": 0,
|
"background_stroke_width": 0,
|
||||||
# When a color c is set, there will be a second color
|
# When a color c is set, there will be a second color
|
||||||
# computed based on interpolating c to WHITE by with
|
# computed based on interpolating c to WHITE by with
|
||||||
# gradient_to_white_factor, and the display will
|
# sheen, and the display will gradient to this
|
||||||
# gradient to this secondary color in the direction
|
# secondary color in the direction of sheen_direction.
|
||||||
# of color_gradient_direction.
|
"sheen": 0.0,
|
||||||
"color_gradient_direction": UL,
|
"sheen_direction": UL,
|
||||||
"gradient_to_white_factor": 0.2,
|
|
||||||
# Indicates that it will not be displayed, but
|
# Indicates that it will not be displayed, but
|
||||||
# that it should count in parent mobject's path
|
# that it should count in parent mobject's path
|
||||||
"is_subpath": False,
|
"is_subpath": False,
|
||||||
@ -69,13 +68,21 @@ class VMobject(Mobject):
|
|||||||
opacity=self.background_stroke_opacity,
|
opacity=self.background_stroke_opacity,
|
||||||
family=self.propagate_style_to_family,
|
family=self.propagate_style_to_family,
|
||||||
)
|
)
|
||||||
|
self.set_sheen_direction(
|
||||||
|
self.sheen_direction,
|
||||||
|
family=self.propagate_style_to_family
|
||||||
|
)
|
||||||
|
self.set_sheen(
|
||||||
|
self.sheen,
|
||||||
|
family=self.propagate_style_to_family
|
||||||
|
)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_rgbas_array(self, color=None, opacity=None):
|
def get_rgbas_array(self, color=None, opacity=None):
|
||||||
"""
|
"""
|
||||||
First arg can be either a color, or a tuple/list of colors.
|
First arg can be either a color, or a tuple/list of colors.
|
||||||
Likewise, opacity can either be a float, or a tuple of floats.
|
Likewise, opacity can either be a float, or a tuple of floats.
|
||||||
If self.gradient_to_white_factor is not zero, and only
|
If self.sheen is not zero, and only
|
||||||
one color was passed in, a second slightly light color
|
one color was passed in, a second slightly light color
|
||||||
will automatically be added for the gradient
|
will automatically be added for the gradient
|
||||||
"""
|
"""
|
||||||
@ -83,29 +90,36 @@ class VMobject(Mobject):
|
|||||||
color = self.color
|
color = self.color
|
||||||
colors = list(tuplify(color))
|
colors = list(tuplify(color))
|
||||||
opacities = list(tuplify(opacity))
|
opacities = list(tuplify(opacity))
|
||||||
g2w_factor = self.get_gradient_to_white_factor()
|
rgbas = np.array([
|
||||||
if g2w_factor != 0 and len(colors) == 1:
|
|
||||||
lighter_color = interpolate_color(
|
|
||||||
colors[0], WHITE, g2w_factor
|
|
||||||
)
|
|
||||||
colors.append(lighter_color)
|
|
||||||
|
|
||||||
return np.array([
|
|
||||||
color_to_rgba(c, o)
|
color_to_rgba(c, o)
|
||||||
for c, o in zip(*make_even(colors, opacities))
|
for c, o in zip(*make_even(colors, opacities))
|
||||||
])
|
])
|
||||||
|
|
||||||
|
sheen = self.get_sheen()
|
||||||
|
if sheen != 0 and len(rgbas) == 1:
|
||||||
|
light_rgbas = np.array(rgbas)
|
||||||
|
light_rgbas[:, :3] += sheen
|
||||||
|
light_rgbas = np.clip(light_rgbas, 0, 1)
|
||||||
|
rgbas = np.append(rgbas, light_rgbas, axis=0)
|
||||||
|
return rgbas
|
||||||
|
|
||||||
def set_fill(self, color=None, opacity=None, family=True):
|
def set_fill(self, color=None, opacity=None, family=True):
|
||||||
if opacity is None:
|
|
||||||
opacity = self.get_fill_opacity()
|
|
||||||
self.fill_rgbas = self.get_rgbas_array(color, opacity)
|
|
||||||
if family:
|
if family:
|
||||||
for submobject in self.submobjects:
|
for submobject in self.submobjects:
|
||||||
submobject.set_fill(color, opacity, family)
|
submobject.set_fill(color, opacity, family)
|
||||||
|
if opacity is None:
|
||||||
|
opacity = self.get_fill_opacity()
|
||||||
|
self.fill_rgbas = self.get_rgbas_array(color, opacity)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_stroke(self, color=None, width=None, opacity=None,
|
def set_stroke(self, color=None, width=None, opacity=None,
|
||||||
background=False, family=True):
|
background=False, family=True):
|
||||||
|
if family:
|
||||||
|
for submobject in self.submobjects:
|
||||||
|
submobject.set_stroke(
|
||||||
|
color, width, opacity, background, family
|
||||||
|
)
|
||||||
|
|
||||||
if opacity is None:
|
if opacity is None:
|
||||||
opacity = self.get_stroke_opacity(background)
|
opacity = self.get_stroke_opacity(background)
|
||||||
|
|
||||||
@ -119,11 +133,6 @@ class VMobject(Mobject):
|
|||||||
setattr(self, array_name, rgbas)
|
setattr(self, array_name, rgbas)
|
||||||
if width is not None:
|
if width is not None:
|
||||||
setattr(self, width_name, width)
|
setattr(self, width_name, width)
|
||||||
if family:
|
|
||||||
for submobject in self.submobjects:
|
|
||||||
submobject.set_stroke(
|
|
||||||
color, width, opacity, background, family
|
|
||||||
)
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_background_stroke(self, **kwargs):
|
def set_background_stroke(self, **kwargs):
|
||||||
@ -154,18 +163,16 @@ class VMobject(Mobject):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def fade_no_recurse(self, darkness):
|
def fade_no_recurse(self, darkness):
|
||||||
self.set_stroke(
|
attrs = ["fill_rgbas", "stroke_rgbas", "background_stroke_rgbas"]
|
||||||
width=(1 - darkness) * self.get_stroke_width(),
|
for attr in attrs:
|
||||||
family=False
|
getattr(self, attr)[:, 3] *= (1.0 - darkness)
|
||||||
)
|
|
||||||
self.set_fill(
|
|
||||||
opacity=(1 - darkness) * self.get_fill_opacity(),
|
|
||||||
family=False
|
|
||||||
)
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_fill_rgbas(self):
|
def get_fill_rgbas(self):
|
||||||
|
try:
|
||||||
return np.clip(self.fill_rgbas, 0, 1)
|
return np.clip(self.fill_rgbas, 0, 1)
|
||||||
|
except AttributeError:
|
||||||
|
return np.zeros((1, 4))
|
||||||
|
|
||||||
def get_fill_color(self):
|
def get_fill_color(self):
|
||||||
"""
|
"""
|
||||||
@ -191,11 +198,14 @@ class VMobject(Mobject):
|
|||||||
return self.get_fill_rgbas()[:, 3]
|
return self.get_fill_rgbas()[:, 3]
|
||||||
|
|
||||||
def get_stroke_rgbas(self, background=False):
|
def get_stroke_rgbas(self, background=False):
|
||||||
|
try:
|
||||||
if background:
|
if background:
|
||||||
rgbas = self.background_stroke_rgbas
|
rgbas = self.background_stroke_rgbas
|
||||||
else:
|
else:
|
||||||
rgbas = self.stroke_rgbas
|
rgbas = self.stroke_rgbas
|
||||||
return np.clip(rgbas, 0, 1)
|
return np.clip(rgbas, 0, 1)
|
||||||
|
except AttributeError:
|
||||||
|
return np.zeros((1, 4))
|
||||||
|
|
||||||
def get_stroke_color(self, background=False):
|
def get_stroke_color(self, background=False):
|
||||||
return self.get_stroke_colors(background)[0]
|
return self.get_stroke_colors(background)[0]
|
||||||
@ -224,31 +234,33 @@ class VMobject(Mobject):
|
|||||||
return self.get_stroke_color()
|
return self.get_stroke_color()
|
||||||
return self.get_fill_color()
|
return self.get_fill_color()
|
||||||
|
|
||||||
def set_color_gradient_direction(self, direction, family=True):
|
def set_sheen_direction(self, direction, family=True):
|
||||||
direction = np.array(direction)
|
direction = np.array(direction)
|
||||||
if family:
|
if family:
|
||||||
for submob in self.submobject_family():
|
for submob in self.submobject_family():
|
||||||
submob.color_gradient_direction = direction
|
submob.sheen_direction = direction
|
||||||
else:
|
else:
|
||||||
self.color_gradient_direction = direction
|
self.sheen_direction = direction
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_gradient_to_white_factor(self, factor, family=True):
|
def set_sheen(self, factor, family=True):
|
||||||
if family:
|
if family:
|
||||||
for submob in self.submobject_family():
|
for submob in self.submobject_family():
|
||||||
submob.gradient_to_white_factor = factor
|
submob.sheen = factor
|
||||||
else:
|
else:
|
||||||
self.gradient_to_white_factor = factor
|
self.sheen = factor
|
||||||
|
self.set_stroke(self.get_stroke_color(), family=family)
|
||||||
|
self.set_fill(self.get_fill_color(), family=family)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_color_gradient_direction(self):
|
def get_sheen_direction(self):
|
||||||
return np.array(self.color_gradient_direction)
|
return np.array(self.sheen_direction)
|
||||||
|
|
||||||
def get_gradient_to_white_factor(self):
|
def get_sheen(self):
|
||||||
return self.gradient_to_white_factor
|
return self.sheen
|
||||||
|
|
||||||
def get_gradient_start_and_end_points(self):
|
def get_gradient_start_and_end_points(self):
|
||||||
direction = self.get_color_gradient_direction()
|
direction = self.get_sheen_direction()
|
||||||
c = self.get_center()
|
c = self.get_center()
|
||||||
bases = np.array([
|
bases = np.array([
|
||||||
self.get_edge_center(vect) - c
|
self.get_edge_center(vect) - c
|
||||||
@ -518,8 +530,8 @@ class VMobject(Mobject):
|
|||||||
"background_stroke_rgbas",
|
"background_stroke_rgbas",
|
||||||
"stroke_width",
|
"stroke_width",
|
||||||
"background_stroke_width",
|
"background_stroke_width",
|
||||||
"color_gradient_direction",
|
"sheen_direction",
|
||||||
"gradient_to_white_factor",
|
"sheen",
|
||||||
]
|
]
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
setattr(self, attr, interpolate(
|
setattr(self, attr, interpolate(
|
||||||
@ -528,7 +540,6 @@ class VMobject(Mobject):
|
|||||||
alpha
|
alpha
|
||||||
))
|
))
|
||||||
if alpha == 1.0:
|
if alpha == 1.0:
|
||||||
# print getattr(mobject2, attr)
|
|
||||||
setattr(self, attr, getattr(mobject2, attr))
|
setattr(self, attr, getattr(mobject2, attr))
|
||||||
|
|
||||||
def pointwise_become_partial(self, mobject, a, b):
|
def pointwise_become_partial(self, mobject, a, b):
|
||||||
|
Reference in New Issue
Block a user