@@ -1501,17 +1501,124 @@ def random_bright_color() -> ManimColor:
1501
1501
def random_color () -> ManimColor :
1502
1502
"""Return a random :class:`ManimColor`.
1503
1503
1504
- .. warning::
1505
- This operation is very expensive. Please keep in mind the performance loss.
1506
-
1507
1504
Returns
1508
1505
-------
1509
1506
ManimColor
1510
1507
A random :class:`ManimColor`.
1511
1508
"""
1512
- import manim .utils .color .manim_colors as manim_colors
1509
+ return RandomColorGenerator ._random_color ()
1510
+
1511
+
1512
+ class RandomColorGenerator :
1513
+ _singleton : RandomColorGenerator | None = None
1514
+ """A generator for producing random colors from a given list of Manim colors,
1515
+ optionally in a reproducible sequence using a seed value.
1516
+
1517
+ When initialized with a specific seed, this class produces a deterministic
1518
+ sequence of :class:`.ManimColor` instances. If no seed is provided, the selection is
1519
+ non-deterministic using Python’s global random state.
1520
+
1521
+ Parameters
1522
+ ----------
1523
+ seed
1524
+ A seed value to initialize the internal random number generator.
1525
+ If ``None`` (the default), colors are chosen using the global random state.
1526
+
1527
+ sample_colors
1528
+ A custom list of Manim colors to sample from. Defaults to the full Manim
1529
+ color palette.
1530
+
1531
+ Examples
1532
+ --------
1533
+ Without a seed (non-deterministic)::
1534
+
1535
+ >>> from manim import RandomColorGenerator, ManimColor, RED, GREEN, BLUE
1536
+ >>> rnd = RandomColorGenerator()
1537
+ >>> isinstance(rnd.next(), ManimColor)
1538
+ True
1539
+
1540
+ With a seed (deterministic sequence)::
1541
+
1542
+ >>> rnd = RandomColorGenerator(42)
1543
+ >>> rnd.next()
1544
+ ManimColor('#ECE7E2')
1545
+ >>> rnd.next()
1546
+ ManimColor('#BBBBBB')
1547
+ >>> rnd.next()
1548
+ ManimColor('#BBBBBB')
1549
+
1550
+ Re-initializing with the same seed gives the same sequence::
1551
+
1552
+ >>> rnd2 = RandomColorGenerator(42)
1553
+ >>> rnd2.next()
1554
+ ManimColor('#ECE7E2')
1555
+ >>> rnd2.next()
1556
+ ManimColor('#BBBBBB')
1557
+ >>> rnd2.next()
1558
+ ManimColor('#BBBBBB')
1559
+
1560
+ Using a custom color list::
1561
+
1562
+ >>> custom_palette = [RED, GREEN, BLUE]
1563
+ >>> rnd_custom = RandomColorGenerator(1, sample_colors=custom_palette)
1564
+ >>> rnd_custom.next() in custom_palette
1565
+ True
1566
+ >>> rnd_custom.next() in custom_palette
1567
+ True
1568
+
1569
+ Without a seed and custom palette (non-deterministic)::
1570
+
1571
+ >>> rnd_nodet = RandomColorGenerator(sample_colors=[RED])
1572
+ >>> rnd_nodet.next()
1573
+ ManimColor('#FC6255')
1574
+ """
1575
+
1576
+ def __init__ (
1577
+ self ,
1578
+ seed : int | None = None ,
1579
+ sample_colors : list [ManimColor ] | None = None ,
1580
+ ) -> None :
1581
+ self .choice = random .choice if seed is None else random .Random (seed ).choice
1582
+
1583
+ from manim .utils .color .manim_colors import _all_manim_colors
1513
1584
1514
- return random .choice (manim_colors ._all_manim_colors )
1585
+ self .colors = _all_manim_colors if sample_colors is None else sample_colors
1586
+
1587
+ def next (self ) -> ManimColor :
1588
+ """Returns the next color from the configured color list.
1589
+
1590
+ Returns
1591
+ -------
1592
+ ManimColor
1593
+ A randomly selected color from the specified color list.
1594
+
1595
+ Examples
1596
+ --------
1597
+ Usage::
1598
+
1599
+ >>> from manim import RandomColorGenerator, RED
1600
+ >>> rnd = RandomColorGenerator(sample_colors=[RED])
1601
+ >>> rnd.next()
1602
+ ManimColor('#FC6255')
1603
+ """
1604
+ return self .choice (self .colors )
1605
+
1606
+ @classmethod
1607
+ def _random_color (cls ) -> ManimColor :
1608
+ """Internal method to generate a random color using the singleton instance of
1609
+ `RandomColorGenerator`.
1610
+ It will be used by proxy method `random_color` publicly available
1611
+ and makes it backwards compatible.
1612
+
1613
+ Returns
1614
+ -------
1615
+ ManimColor:
1616
+ A randomly selected color from the configured color list of
1617
+ the singleton instance.
1618
+ """
1619
+ if cls ._singleton is None :
1620
+ cls ._singleton = cls ()
1621
+ return cls ._singleton .next ()
1515
1622
1516
1623
1517
1624
def get_shaded_rgb (
@@ -1567,6 +1674,7 @@ def get_shaded_rgb(
1567
1674
"average_color" ,
1568
1675
"random_bright_color" ,
1569
1676
"random_color" ,
1677
+ "RandomColorGenerator" ,
1570
1678
"get_shaded_rgb" ,
1571
1679
"HSV" ,
1572
1680
"RGBA" ,
0 commit comments