Skip to content

Rewrite color_gradient to always return a list of ManimColors #4380

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 4 commits into from
Aug 11, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions manim/mobject/graphing/coordinate_systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
YELLOW,
ManimColor,
ParsableManimColor,
color_gradient,
color_gradient_as_list,
interpolate_color,
invert_color,
)
Expand Down Expand Up @@ -1293,7 +1293,7 @@ def construct(self):
else:
color = [ManimColor(color)]

colors = color_gradient(color, len(x_range_array))
colors = color_gradient_as_list(color, len(x_range_array))

for x, color in zip(x_range_array, colors):
if input_sample_type == "left":
Expand Down
6 changes: 2 additions & 4 deletions manim/mobject/graphing/probability.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
MAROON_B,
YELLOW,
ParsableManimColor,
color_gradient,
color_gradient_as_list,
)
from manim.utils.iterables import tuplify

Expand Down Expand Up @@ -103,9 +103,7 @@ def get_division_along_dimension(
vect: Vector3D,
) -> VGroup:
p_list_complete = self.complete_p_list(p_list)
colors_in_gradient = color_gradient(colors, len(p_list_complete))

assert isinstance(colors_in_gradient, list)
colors_in_gradient = color_gradient_as_list(colors, len(p_list_complete))

last_point = self.get_edge_center(-vect)
parts = VGroup()
Expand Down
4 changes: 2 additions & 2 deletions manim/mobject/mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
YELLOW_C,
ManimColor,
ParsableManimColor,
color_gradient,
color_gradient_as_list,
interpolate_color,
)
from ..utils.exceptions import MultiAnimationOverrideException
Expand Down Expand Up @@ -1970,7 +1970,7 @@ def set_submobject_colors_by_gradient(self, *colors: Iterable[ParsableManimColor
return self.set_color(*colors)

mobs = self.family_members_with_points()
new_colors = color_gradient(colors, len(mobs))
new_colors = color_gradient_as_list(colors, len(mobs))

for mob, color in zip(mobs, new_colors):
mob.set_color(color, family=False)
Expand Down
4 changes: 2 additions & 2 deletions manim/mobject/opengl/opengl_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
WHITE,
ManimColor,
ParsableManimColor,
color_gradient,
color_gradient_as_list,
color_to_rgb,
rgb_to_hex,
)
Expand Down Expand Up @@ -2176,7 +2176,7 @@ def set_submobject_colors_by_gradient(self, *colors: ParsableManimColor) -> Self

# mobs = self.family_members_with_points()
mobs = self.submobjects
new_colors = color_gradient(colors, len(mobs))
new_colors = color_gradient_as_list(colors, len(mobs))

for mob, color in zip(mobs, new_colors):
mob.set_color(color)
Expand Down
4 changes: 2 additions & 2 deletions manim/mobject/opengl/opengl_point_cloud_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
WHITE,
YELLOW,
ParsableManimColor,
color_gradient,
color_gradient_as_list,
color_to_rgba,
)
from manim.utils.config_ops import _Uniforms
Expand Down Expand Up @@ -92,7 +92,7 @@ def thin_func(num_points=num_points):

def set_color_by_gradient(self, *colors):
self.rgbas = np.array(
list(map(color_to_rgba, color_gradient(*colors, self.get_num_points()))),
map(color_to_rgba, color_gradient_as_list(*colors, self.get_num_points())),
)
return self

Expand Down
9 changes: 3 additions & 6 deletions manim/mobject/text/text_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def construct(self):
from manim.mobject.geometry.arc import Dot
from manim.mobject.svg.svg_mobject import SVGMobject
from manim.mobject.types.vectorized_mobject import VGroup, VMobject
from manim.utils.color import ManimColor, ParsableManimColor, color_gradient
from manim.utils.color import ManimColor, ParsableManimColor, color_gradient_as_list
from manim.utils.deprecation import deprecated

TEXT_MOB_SCALE_FACTOR = 0.05
Expand Down Expand Up @@ -735,17 +735,14 @@ def _get_settings_from_gradient(
settings = []
args = copy.copy(default_args)
if self.gradient:
colors = color_gradient(self.gradient, len(self.text))
colors = color_gradient_as_list(self.gradient, len(self.text))
for i in range(len(self.text)):
args["color"] = colors[i].to_hex()
settings.append(TextSetting(i, i + 1, **args))

for word, gradient in self.t2g.items():
if isinstance(gradient, str) or len(gradient) == 1:
color = gradient if isinstance(gradient, str) else gradient[0]
gradient = [ManimColor(color)]
colors = (
color_gradient(gradient, len(word))
color_gradient_as_list(gradient, len(word))
if len(gradient) != 1
else len(word) * gradient
)
Expand Down
4 changes: 2 additions & 2 deletions manim/mobject/types/point_cloud_mobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
YELLOW,
ManimColor,
ParsableManimColor,
color_gradient,
color_gradient_as_list,
color_to_rgba,
rgba_to_color,
)
Expand Down Expand Up @@ -124,7 +124,7 @@ def set_stroke_width(self, width: int, family: bool = True) -> Self:

def set_color_by_gradient(self, *colors: ParsableManimColor) -> Self:
self.rgbas = np.array(
list(map(color_to_rgba, color_gradient(*colors, len(self.points)))),
map(color_to_rgba, color_gradient_as_list(*colors, len(self.points))),
)
return self

Expand Down
37 changes: 37 additions & 0 deletions manim/utils/color/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,42 @@ def color_gradient(
]


def color_gradient_as_list(
reference_colors: Sequence[ParsableManimColor],
length_of_output: int,
) -> list[ManimColor]:
"""Create a list of colors interpolated between the input array of colors with a
specific number of colors.

Parameters
----------
reference_colors
The colors to be interpolated between or spread apart.
length_of_output
The number of colors that the output should have, ideally more than the input.

Returns
-------
list[ManimColor]
A list of interpolated :class:`ManimColor`'s.
"""
if length_of_output == 0:
return [ManimColor(reference_colors[0])]
if len(reference_colors) == 1:
return [ManimColor(reference_colors[0])] * length_of_output
rgbs = [color_to_rgb(color) for color in reference_colors]
alphas = np.linspace(0, (len(rgbs) - 1), length_of_output)
floors = alphas.astype("int")
alphas_mod1 = alphas % 1
# End edge case
alphas_mod1[-1] = 1
floors[-1] = len(rgbs) - 2
return [
rgb_to_color((rgbs[i] * (1 - alpha)) + (rgbs[i + 1] * alpha))
for i, alpha in zip(floors, alphas_mod1)
]


def interpolate_color(
color1: ManimColorT, color2: ManimColorT, alpha: float
) -> ManimColorT:
Expand Down Expand Up @@ -1670,6 +1706,7 @@ def get_shaded_rgb(
"hex_to_rgb",
"invert_color",
"color_gradient",
"color_gradient_as_list",
"interpolate_color",
"average_color",
"random_bright_color",
Expand Down
Loading