Repository: ManimCommunity/manim
File: manim/utils/color/core.py (Python)

Code before:

    .. warning::
        This operation is very expensive. Please keep in mind the performance loss.

    Returns
    -------
    ManimColor
        A random bright :class:`ManimColor`.
    """
    curr_rgb = color_to_rgb(random_color())
    new_rgb = 0.5 * (curr_rgb + np.ones(3))
    return ManimColor(new_rgb)


def random_color() -> ManimColor:
    """Return a random :class:`ManimColor`.

    .. warning::
        This operation is very expensive. Please keep in mind the performance loss.

    Returns
    -------
    ManimColor
        A random :class:`ManimColor`.
    """
    return RandomColorGenerator().next()


class RandomColorGenerator:
    """A generator for producing random colors from a given list of Manim colors,
    optionally in a reproducible sequence using a seed value.

    When initialized with a specific seed, this class produces a deterministic
    sequence of :class:`.ManimColor` instances. If no seed is provided, the selection is
    non-deterministic using Python’s global random state.

    Parameters
    ----------
    seed
        A seed value to initialize the internal random number generator.
        If ``None`` (the default), colors are chosen using the global random state.

    sample_colors
        A custom list of Manim colors to sample from. Defaults to the full Manim
        color palette.

    Examples
    --------
    Without a seed (non-deterministic)::

        >>> from manim import RandomColorGenerator, ManimColor, RED, GREEN, BLUE

Review comment (performance):
@behackl
While thinking about the warning that you mentioned.
Do you think it would make sense to use a singleton object here instead of initializing a new one each time?

In a scenario where `random_color` is called frequently across a project, repeatedly creating and discarding instances could be inefficient (though I'm not entirely sure how Python handles cleanup in this case).

Would it be better to define a static version of the method, allowing us to directly call `next()` on the class rather than an instance?

Open to your thoughts or suggestions. Happy to include this as part of the current PR or address it as a follow-up improvement.


Code after:
    """Return a random bright color: a random color averaged with ``WHITE``.

    .. warning::
        This operation is very expensive. Please keep in mind the performance loss.

    Returns
    -------
    ManimColor
        A random bright :class:`ManimColor`.
    """
    curr_rgb = color_to_rgb(random_color())
    new_rgb = 0.5 * (curr_rgb + np.ones(3))
    return ManimColor(new_rgb)


def random_color() -> ManimColor:
    """Return a random :class:`ManimColor`.

    Returns
    -------
    ManimColor
        A random :class:`ManimColor`.
    """
    return RandomColorGenerator._random_color()


class RandomColorGenerator:
    _singleton: RandomColorGenerator | None = None
    """A generator for producing random colors from a given list of Manim colors,
    optionally in a reproducible sequence using a seed value.

    When initialized with a specific seed, this class produces a deterministic
    sequence of :class:`.ManimColor` instances. If no seed is provided, the selection is
    non-deterministic using Python’s global random state.

    Parameters
    ----------
    seed
        A seed value to initialize the internal random number generator.
        If ``None`` (the default), colors are chosen using the global random state.

    sample_colors
        A custom list of Manim colors to sample from. Defaults to the full Manim
        color palette.

    Examples
    --------
    Without a seed (non-deterministic)::

        >>> from manim import RandomColorGenerator, ManimColor, RED, GREEN, BLUE
        >>> rnd = RandomColorGenerator()