mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Add background stroke width to mobjects
This commit is contained in:
parent
7119f0cc6e
commit
3dc5b10e8b
3 changed files with 75 additions and 23 deletions
|
@ -316,8 +316,18 @@ class Camera(object):
|
||||||
pen, fill = self.get_pen_and_fill(vmobject)
|
pen, fill = self.get_pen_and_fill(vmobject)
|
||||||
pathstring = self.get_pathstring(vmobject)
|
pathstring = self.get_pathstring(vmobject)
|
||||||
symbol = aggdraw.Symbol(pathstring)
|
symbol = aggdraw.Symbol(pathstring)
|
||||||
|
self.draw_background_stroke(canvas, vmobject, symbol)
|
||||||
canvas.symbol((0, 0), symbol, pen, fill)
|
canvas.symbol((0, 0), symbol, pen, fill)
|
||||||
|
|
||||||
|
def draw_background_stroke(self, canvas, vmobject, symbol):
|
||||||
|
bs_width = vmobject.get_background_stroke_width()
|
||||||
|
if bs_width == 0:
|
||||||
|
return
|
||||||
|
bs_rgb = vmobject.get_background_stroke_rgb()
|
||||||
|
bs_hex = rgb_to_hex(bs_rgb)
|
||||||
|
pen = aggdraw.Pen(bs_hex, bs_width)
|
||||||
|
canvas.symbol((0, 0), symbol, pen, None)
|
||||||
|
|
||||||
def get_pen_and_fill(self, vmobject):
|
def get_pen_and_fill(self, vmobject):
|
||||||
stroke_width = max(vmobject.get_stroke_width(), 0)
|
stroke_width = max(vmobject.get_stroke_width(), 0)
|
||||||
if stroke_width == 0:
|
if stroke_width == 0:
|
||||||
|
|
|
@ -39,6 +39,8 @@ class SingleStringTexMobject(SVGMobject):
|
||||||
"template_tex_file": TEMPLATE_TEX_FILE,
|
"template_tex_file": TEMPLATE_TEX_FILE,
|
||||||
"stroke_width": 0,
|
"stroke_width": 0,
|
||||||
"fill_opacity": 1.0,
|
"fill_opacity": 1.0,
|
||||||
|
"background_stroke_width": 5,
|
||||||
|
"background_stroke_color": BLACK,
|
||||||
"should_center": True,
|
"should_center": True,
|
||||||
"height": None,
|
"height": None,
|
||||||
"organize_left_to_right": False,
|
"organize_left_to_right": False,
|
||||||
|
|
|
@ -19,6 +19,10 @@ class VMobject(Mobject):
|
||||||
"fill_opacity": 0.0,
|
"fill_opacity": 0.0,
|
||||||
"stroke_color": None,
|
"stroke_color": None,
|
||||||
"stroke_width": DEFAULT_POINT_THICKNESS,
|
"stroke_width": DEFAULT_POINT_THICKNESS,
|
||||||
|
# The purpose of background stroke is to have
|
||||||
|
# something that won't overlap the fill
|
||||||
|
"background_stroke_color": BLACK,
|
||||||
|
"background_stroke_width": 0,
|
||||||
# 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,
|
||||||
|
@ -36,10 +40,12 @@ class VMobject(Mobject):
|
||||||
# Colors
|
# Colors
|
||||||
def init_colors(self):
|
def init_colors(self):
|
||||||
self.set_style_data(
|
self.set_style_data(
|
||||||
stroke_color=self.stroke_color or self.color,
|
|
||||||
stroke_width=self.stroke_width,
|
|
||||||
fill_color=self.fill_color or self.color,
|
fill_color=self.fill_color or self.color,
|
||||||
fill_opacity=self.fill_opacity,
|
fill_opacity=self.fill_opacity,
|
||||||
|
stroke_color=self.stroke_color or self.color,
|
||||||
|
stroke_width=self.stroke_width,
|
||||||
|
background_stroke_color=self.background_stroke_color,
|
||||||
|
background_stroke_width=self.background_stroke_width,
|
||||||
family=self.propagate_style_to_family
|
family=self.propagate_style_to_family
|
||||||
)
|
)
|
||||||
return self
|
return self
|
||||||
|
@ -49,29 +55,37 @@ class VMobject(Mobject):
|
||||||
setattr(mob, attr, value)
|
setattr(mob, attr, value)
|
||||||
|
|
||||||
def set_style_data(self,
|
def set_style_data(self,
|
||||||
stroke_color=None,
|
|
||||||
stroke_width=None,
|
|
||||||
fill_color=None,
|
fill_color=None,
|
||||||
fill_opacity=None,
|
fill_opacity=None,
|
||||||
|
stroke_color=None,
|
||||||
|
stroke_width=None,
|
||||||
|
background_stroke_color=None,
|
||||||
|
background_stroke_width=None,
|
||||||
family=True
|
family=True
|
||||||
):
|
):
|
||||||
if stroke_color is not None:
|
kwargs = {
|
||||||
self.stroke_rgb = color_to_rgb(stroke_color)
|
"fill_color": fill_color,
|
||||||
if fill_color is not None:
|
"fill_opacity": fill_opacity,
|
||||||
self.fill_rgb = color_to_rgb(fill_color)
|
"stroke_color": stroke_color,
|
||||||
if stroke_width is not None:
|
"stroke_width": stroke_width,
|
||||||
self.stroke_width = stroke_width
|
"background_stroke_color": background_stroke_color,
|
||||||
if fill_opacity is not None:
|
"background_stroke_width": background_stroke_width,
|
||||||
self.fill_opacity = fill_opacity
|
"family": family,
|
||||||
|
}
|
||||||
|
for key in "fill_color", "stroke_color", "background_stroke_color":
|
||||||
|
# Instead of setting a self.fill_color attr,
|
||||||
|
# set a numerical self.fill_rgb to make
|
||||||
|
# interpolation easier
|
||||||
|
key_with_rgb = key.replace("color", "rgb")
|
||||||
|
color = kwargs[key]
|
||||||
|
if color is not None:
|
||||||
|
setattr(self, key_with_rgb, color_to_rgb(color))
|
||||||
|
for key in "fill_opacity", "stroke_width", "background_stroke_width":
|
||||||
|
if kwargs[key] is not None:
|
||||||
|
setattr(self, key, kwargs[key])
|
||||||
if family:
|
if family:
|
||||||
for mob in self.submobjects:
|
for mob in self.submobjects:
|
||||||
mob.set_style_data(
|
mob.set_style_data(**kwargs)
|
||||||
stroke_color=stroke_color,
|
|
||||||
stroke_width=stroke_width,
|
|
||||||
fill_color=fill_color,
|
|
||||||
fill_opacity=fill_opacity,
|
|
||||||
family=family
|
|
||||||
)
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def set_fill(self, color=None, opacity=None, family=True):
|
def set_fill(self, color=None, opacity=None, family=True):
|
||||||
|
@ -88,6 +102,13 @@ class VMobject(Mobject):
|
||||||
family=family
|
family=family
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def set_background_stroke(self, color=None, width=None, family=True):
|
||||||
|
return self.set_style_data(
|
||||||
|
background_stroke_color=color,
|
||||||
|
background_stroke_width=width,
|
||||||
|
family=family
|
||||||
|
)
|
||||||
|
|
||||||
def set_color(self, color, family=True):
|
def set_color(self, color, family=True):
|
||||||
self.set_style_data(
|
self.set_style_data(
|
||||||
stroke_color=color,
|
stroke_color=color,
|
||||||
|
@ -99,10 +120,12 @@ class VMobject(Mobject):
|
||||||
|
|
||||||
def match_style(self, vmobject):
|
def match_style(self, vmobject):
|
||||||
self.set_style_data(
|
self.set_style_data(
|
||||||
stroke_color=vmobject.get_stroke_color(),
|
|
||||||
stroke_width=vmobject.get_stroke_width(),
|
|
||||||
fill_color=vmobject.get_fill_color(),
|
fill_color=vmobject.get_fill_color(),
|
||||||
fill_opacity=vmobject.get_fill_opacity(),
|
fill_opacity=vmobject.get_fill_opacity(),
|
||||||
|
stroke_color=vmobject.get_stroke_color(),
|
||||||
|
stroke_width=vmobject.get_stroke_width(),
|
||||||
|
background_stroke_color=vmobject.get_background_stroke_color(),
|
||||||
|
background_stroke_width=vmobject.get_background_stroke_width(),
|
||||||
family=False
|
family=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -154,6 +177,21 @@ class VMobject(Mobject):
|
||||||
def get_stroke_width(self):
|
def get_stroke_width(self):
|
||||||
return max(0, self.stroke_width)
|
return max(0, self.stroke_width)
|
||||||
|
|
||||||
|
def get_background_stroke_rgb(self):
|
||||||
|
return np.clip(self.background_stroke_rgb, 0, 1)
|
||||||
|
|
||||||
|
def get_background_stroke_color(self):
|
||||||
|
try:
|
||||||
|
self.background_stroke_rgb = np.clip(
|
||||||
|
self.background_stroke_rgb, 0, 1
|
||||||
|
)
|
||||||
|
return Color(rgb=self.background_stroke_rgb)
|
||||||
|
except:
|
||||||
|
return Color(WHITE)
|
||||||
|
|
||||||
|
def get_background_stroke_width(self):
|
||||||
|
return max(0, self.background_stroke_width)
|
||||||
|
|
||||||
def get_color(self):
|
def get_color(self):
|
||||||
if self.fill_opacity == 0:
|
if self.fill_opacity == 0:
|
||||||
return self.get_stroke_color()
|
return self.get_stroke_color()
|
||||||
|
@ -404,10 +442,12 @@ class VMobject(Mobject):
|
||||||
|
|
||||||
def interpolate_color(self, mobject1, mobject2, alpha):
|
def interpolate_color(self, mobject1, mobject2, alpha):
|
||||||
attrs = [
|
attrs = [
|
||||||
"stroke_rgb",
|
|
||||||
"stroke_width",
|
|
||||||
"fill_rgb",
|
"fill_rgb",
|
||||||
"fill_opacity",
|
"fill_opacity",
|
||||||
|
"stroke_rgb",
|
||||||
|
"stroke_width",
|
||||||
|
"background_stroke_rgb",
|
||||||
|
"background_stroke_width",
|
||||||
]
|
]
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
setattr(self, attr, interpolate(
|
setattr(self, attr, interpolate(
|
||||||
|
|
Loading…
Add table
Reference in a new issue