Skip to content

Changed color, stroke_color and fill_color attributes to properties #2332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion manim/mobject/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2558,8 +2558,8 @@ def construct(self):
"""

def __init__(self, corner_radius=0.5, **kwargs):
self.corner_radius = corner_radius
super().__init__(**kwargs)
self.corner_radius = corner_radius
self.round_corners(self.corner_radius)


Expand Down
3 changes: 2 additions & 1 deletion manim/mobject/mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ def __init_subclass__(cls, **kwargs):
cls._original__init__ = cls.__init__

def __init__(self, color=WHITE, name=None, dim=3, target=None, z_index=0):
self.color = Color(color) if color else None
self.name = self.__class__.__name__ if name is None else name
self.dim = dim
self.target = target
Expand All @@ -100,6 +99,8 @@ def __init__(self, color=WHITE, name=None, dim=3, target=None, z_index=0):
self.submobjects = []
self.updaters = []
self.updating_suspended = False
self.color = Color(color) if color else None

self.reset_points()
self.generate_points()
self.init_colors()
Expand Down
15 changes: 10 additions & 5 deletions manim/mobject/opengl_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ def __init__(
self.data = getattr(self, "data", {})
self.uniforms = getattr(self, "uniforms", {})

self.color = Color(color) if color else None
self.opacity = opacity
self.dim = dim # TODO, get rid of this
# Lighting parameters
Expand Down Expand Up @@ -129,6 +128,7 @@ def __init__(
self.init_updaters()
# self.init_event_listners()
self.init_points()
self.color = Color(color) if color else None
self.init_colors()

self.shader_indices = None
Expand Down Expand Up @@ -646,7 +646,7 @@ def assemble_family(self):
return self

def get_family(self, recurse=True):
if recurse:
if recurse and hasattr(self, "family"):
return self.family
else:
return [self]
Expand Down Expand Up @@ -1874,13 +1874,18 @@ def set_rgba_array(self, color=None, opacity=None, name="rgbas", recurse=True):
# Color only
if color is not None and opacity is None:
for mob in self.get_family(recurse):
mob.data[name] = resize_array(mob.data[name], len(rgbs))
mob.data[name] = resize_array(
mob.data[name] if name in mob.data else np.empty((1, 3)), len(rgbs)
)
mob.data[name][:, :3] = rgbs

# Opacity only
if color is None and opacity is not None:
for mob in self.get_family(recurse):
mob.data[name] = resize_array(mob.data[name], len(opacities))
mob.data[name] = resize_array(
mob.data[name] if name in mob.data else np.empty((1, 3)),
len(opacities),
)
mob.data[name][:, 3] = opacities

# Color and opacity
Expand Down Expand Up @@ -2619,7 +2624,7 @@ def get_shader_vert_indices(self):

@property
def submobjects(self):
return self._submobjects
return self._submobjects if hasattr(self, "_submobjects") else []

@submobjects.setter
def submobjects(self, submobject_list):
Expand Down
7 changes: 3 additions & 4 deletions manim/mobject/shape_matchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@ def construct(self):
def __init__(
self, mobject, color=YELLOW, buff=SMALL_BUFF, corner_radius=0.0, **kwargs
):
self.color = color
self.buff = buff
super().__init__(
color=color,
width=mobject.width + 2 * self.buff,
height=mobject.height + 2 * self.buff,
width=mobject.width + 2 * buff,
height=mobject.height + 2 * buff,
corner_radius=corner_radius,
**kwargs
)
self.buff = buff
self.move_to(mobject)


Expand Down
49 changes: 37 additions & 12 deletions manim/mobject/svg/svg_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import re
import string
import warnings
from typing import Dict, List
from xml.dom.minidom import Element as MinidomElement
from xml.dom.minidom import parse as minidom_parse

import numpy as np
from colour import Color

from ... import config, logger
from ...constants import *
Expand Down Expand Up @@ -76,6 +76,10 @@ def __init__(
should_subdivide_sharp_curves=False,
should_remove_null_curves=False,
color=None,
*,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a typo or intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intentional, so as not to change the constructor signature. fill_color, stroke_color and stroke_opacity were keyword only before and they are keyword only now.

fill_color=None,
stroke_color=None,
stroke_opacity=1.0,
**kwargs,
):
self.def_map = {}
Expand All @@ -91,8 +95,21 @@ def __init__(
if config.renderer == "opengl"
else {}
)
self._initial_svg_style = self.generate_style(
Color(color) if color else None,
Color(fill_color) if fill_color else None,
Color(stroke_color) if stroke_color else None,
fill_opacity,
stroke_opacity,
)
super().__init__(
color=color, fill_opacity=fill_opacity, stroke_width=stroke_width, **kwargs
color=color,
fill_opacity=fill_opacity,
stroke_width=stroke_width,
fill_color=fill_color,
stroke_opacity=stroke_opacity,
stroke_color=stroke_color,
**kwargs,
)
self._move_into_position(width, height)

Expand Down Expand Up @@ -136,7 +153,7 @@ def generate_points(self):
for node in doc.childNodes:
if not isinstance(node, MinidomElement) or node.tagName != "svg":
continue
mobjects = self._get_mobjects_from(node, self.generate_style())
mobjects = self._get_mobjects_from(node, self._initial_svg_style)
if self.unpack_groups:
self.add(*mobjects)
else:
Expand Down Expand Up @@ -230,17 +247,25 @@ def _get_mobjects_from(

return result

def generate_style(self):
def generate_style(
self,
color: Color | None,
fill_color: Color | None,
stroke_color: Color | None,
fill_opacity: float,
stroke_opacity: float,
):
style = {
"fill-opacity": self.fill_opacity,
"stroke-opacity": self.stroke_opacity,
"fill-opacity": fill_opacity,
"stroke-opacity": stroke_opacity,
}
if self.color:
style["fill"] = style["stroke"] = self.color.get_hex_l()
if self.fill_color:
style["fill"] = self.fill_color
if self.stroke_color:
style["stroke"] = self.stroke_color
if color:
style["fill"] = style["stroke"] = color.get_hex_l()
if fill_color:
style["fill"] = fill_color.hex_l
if stroke_color:
style["stroke"] = stroke_color.hex_l

return style

def _path_string_to_mobject(self, path_string: str, style: dict):
Expand Down
37 changes: 21 additions & 16 deletions manim/mobject/svg/text_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ def __init__(
disable_ligatures: bool = False,
**kwargs,
):
self.color = color
self.line_spacing = line_spacing
self.font = font
self._font_size = float(font_size)
Expand Down Expand Up @@ -471,7 +470,7 @@ def __init__(
)
else:
self.line_spacing = self._font_size + self._font_size * self.line_spacing
file_name = self._text2svg()
file_name = self._text2svg(color)
PangoUtils.remove_last_M(file_name)
super().__init__(
file_name,
Expand Down Expand Up @@ -594,10 +593,10 @@ def _set_color_by_t2g(self, t2g=None):
for start, end in self._find_indexes(word, self.text):
self.chars[start:end].set_color_by_gradient(*gradient)

def _text2hash(self):
def _text2hash(self, color: Color):
"""Generates ``sha256`` hash for file name."""
settings = (
"PANGO" + self.font + self.slant + self.weight + self.color
"PANGO" + self.font + self.slant + self.weight + color
) # to differentiate Text and CairoText
settings += str(self.t2f) + str(self.t2s) + str(self.t2w) + str(self.t2c)
settings += str(self.line_spacing) + str(self._font_size)
Expand Down Expand Up @@ -671,15 +670,17 @@ def _get_settings_from_gradient(
settings.append(TextSetting(i, i + 1, **args))
return settings

def _text2settings(self):
def _text2settings(self, color: Color):
"""Converts the texts and styles to a setting for parsing."""
t2xs = [
(self.t2f, "font"),
(self.t2s, "slant"),
(self.t2w, "weight"),
(self.t2c, "color"),
]
setting_args = {arg: getattr(self, arg) for _, arg in t2xs}
setting_args = {
arg: getattr(self, arg) if arg != "color" else color for _, arg in t2xs
}

settings = self._get_settings_from_t2xs(t2xs)
settings.extend(self._get_settings_from_gradient(setting_args))
Expand Down Expand Up @@ -733,7 +734,7 @@ def _text2settings(self):
setting.line_num = 0
return settings

def _text2svg(self):
def _text2svg(self, color: Color):
"""Convert the text to SVG using Pango."""
size = self._font_size
line_spacing = self.line_spacing
Expand All @@ -743,13 +744,13 @@ def _text2svg(self):
dir_name = config.get_dir("text_dir")
if not os.path.exists(dir_name):
os.makedirs(dir_name)
hash_name = self._text2hash()
hash_name = self._text2hash(color)
file_name = os.path.join(dir_name, hash_name) + ".svg"

if os.path.exists(file_name):
svg_file = file_name
else:
settings = self._text2settings()
settings = self._text2settings(color)
width = config["pixel_width"]
height = config["pixel_height"]

Expand Down Expand Up @@ -1100,7 +1101,6 @@ def __init__(
**kwargs,
):
self.text = text
self.color = color
self.line_spacing = line_spacing
self.font = font
self._font_size = float(font_size)
Expand Down Expand Up @@ -1133,7 +1133,7 @@ def __init__(
else:
self.line_spacing = self._font_size + self._font_size * self.line_spacing

file_name = self._text2svg()
file_name = self._text2svg(Color(color) if color else None)
PangoUtils.remove_last_M(file_name)
super().__init__(
file_name,
Expand Down Expand Up @@ -1212,10 +1212,10 @@ def font_size(self, font_val):
else:
self.scale(font_val / self.font_size)

def _text2hash(self):
def _text2hash(self, color: Color):
"""Generates ``sha256`` hash for file name."""
settings = (
"MARKUPPANGO" + self.font + self.slant + self.weight + self.color
"MARKUPPANGO" + self.font + self.slant + self.weight + color.hex_l
) # to differentiate from classical Pango Text
settings += str(self.line_spacing) + str(self._font_size)
settings += str(self.disable_ligatures)
Expand All @@ -1225,7 +1225,7 @@ def _text2hash(self):
hasher.update(id_str.encode())
return hasher.hexdigest()[:16]

def _text2svg(self):
def _text2svg(self, color: Color | None):
"""Convert the text to SVG using Pango."""
size = self._font_size
line_spacing = self.line_spacing
Expand All @@ -1235,14 +1235,19 @@ def _text2svg(self):
dir_name = config.get_dir("text_dir")
if not os.path.exists(dir_name):
os.makedirs(dir_name)
hash_name = self._text2hash()
hash_name = self._text2hash(color)
file_name = os.path.join(dir_name, hash_name) + ".svg"
if os.path.exists(file_name):
svg_file = file_name
else:
final_text = (
f'<span foreground="{color}">{self.text}</span>'
if color is not None
else self.text
)
logger.debug(f"Setting Text {self.text}")
svg_file = MarkupUtils.text2svg(
f'<span foreground="{self.color}">{self.text}</span>',
final_text,
self.font,
self.slant,
self.weight,
Expand Down
Loading