diff --git a/arcade/types.py b/arcade/types.py index 5263da3e3..f92063539 100644 --- a/arcade/types.py +++ b/arcade/types.py @@ -3,8 +3,6 @@ """ from __future__ import annotations -from __future__ import annotations - import sys from array import array import ctypes @@ -419,6 +417,42 @@ def random( return cls(r, g, b, a) + def swizzle(self, swizzle_string: str) -> Tuple[int, ...]: + """ + Get a tuple of channel values in the same order as the passed string. + + This imitates swizzling `as implemented in GLSL `_ + + .. code-block:: python + + >>> from arcade.types import Color + >>> color = Color(180, 90, 0, 255) + >>> color.swizzle("abgr") + (255, 0, 90, 180) + + You can also use any length of swizzle string and use capital + letters. Any capitals will be treated as lower case equivalents. + + .. code-block: python + + >>> from arcade.types import Color + >>> color = Color(180, 90, 0, 255) + >>> color.swizzle("ABGR") + (255, 0, 90, 180) + + + :param swizzle_string: + A string of channel names as letters in ``"RGBArgba"``. + :return: + A tuple in the same order as the input string. + """ + ret = [] + for c in swizzle_string.lower(): + if c not in 'rgba': + raise ValueError(f"Swizzle string must only contain characters in [RGBArgba], not {c}.") + ret.append(getattr(self, c)) + return tuple(ret) + ColorLike = Union[RGB, RGBA255] diff --git a/tests/unit/color/test_color_type.py b/tests/unit/color/test_color_type.py index 82cf2109b..43946288e 100644 --- a/tests/unit/color/test_color_type.py +++ b/tests/unit/color/test_color_type.py @@ -201,6 +201,29 @@ def test_deepcopy_color_inheritance(): assert isinstance(deep, ColorSubclass) +@pytest.mark.parametrize("klass", [Color, ColorSubclass]) +def test_swizzle(klass): + color_instance = klass(1, 2, 3, a=4) + + # Edge case + assert color_instance.swizzle("") == tuple() + + assert color_instance.swizzle("r") == (1,) + assert color_instance.swizzle("g") == (2,) + assert color_instance.swizzle("b") == (3,) + assert color_instance.swizzle("a") == (4,) + assert color_instance.swizzle("R") == (1,) + assert color_instance.swizzle("G") == (2,) + assert color_instance.swizzle("B") == (3,) + assert color_instance.swizzle("A") == (4,) + + assert color_instance.swizzle("ra") == (1, 4) + assert color_instance.swizzle("RA") == (1, 4) + + assert color_instance.swizzle("aabbggrr") == (4, 4, 3, 3, 2, 2, 1, 1) + assert color_instance.swizzle("AABBGGRR") == (4, 4, 3, 3, 2, 2, 1, 1) + + RANDINT_RETURN_RESULT = 128