Skip to content

Commit fb18ea9

Browse files
DigiDuncanpushfoo
andauthored
Swizzle support for colors (#1998)
* swizzle, swizzle, swizzle... 🎵🎶 * better output as per pushfoo's request * Add basic swizzle tests w/o itertools * More readable instantiation * Add doc for swizzle * Add edge case to swizzle tests --------- Co-authored-by: pushfoo <36696816+pushfoo@users.noreply.github.com>
1 parent b6f4add commit fb18ea9

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

arcade/types.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
"""
44
from __future__ import annotations
55

6-
from __future__ import annotations
7-
86
import sys
97
from array import array
108
import ctypes
@@ -429,6 +427,42 @@ def random(
429427

430428
return cls(r, g, b, a)
431429

430+
def swizzle(self, swizzle_string: str) -> Tuple[int, ...]:
431+
"""
432+
Get a tuple of channel values in the same order as the passed string.
433+
434+
This imitates swizzling `as implemented in GLSL <https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Swizzling>`_
435+
436+
.. code-block:: python
437+
438+
>>> from arcade.types import Color
439+
>>> color = Color(180, 90, 0, 255)
440+
>>> color.swizzle("abgr")
441+
(255, 0, 90, 180)
442+
443+
You can also use any length of swizzle string and use capital
444+
letters. Any capitals will be treated as lower case equivalents.
445+
446+
.. code-block: python
447+
448+
>>> from arcade.types import Color
449+
>>> color = Color(180, 90, 0, 255)
450+
>>> color.swizzle("ABGR")
451+
(255, 0, 90, 180)
452+
453+
454+
:param swizzle_string:
455+
A string of channel names as letters in ``"RGBArgba"``.
456+
:return:
457+
A tuple in the same order as the input string.
458+
"""
459+
ret = []
460+
for c in swizzle_string.lower():
461+
if c not in 'rgba':
462+
raise ValueError(f"Swizzle string must only contain characters in [RGBArgba], not {c}.")
463+
ret.append(getattr(self, c))
464+
return tuple(ret)
465+
432466

433467
ColorLike = Union[RGB, RGBA255]
434468

tests/unit/color/test_color_type.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,29 @@ def test_deepcopy_color_inheritance():
201201
assert isinstance(deep, ColorSubclass)
202202

203203

204+
@pytest.mark.parametrize("klass", [Color, ColorSubclass])
205+
def test_swizzle(klass):
206+
color_instance = klass(1, 2, 3, a=4)
207+
208+
# Edge case
209+
assert color_instance.swizzle("") == tuple()
210+
211+
assert color_instance.swizzle("r") == (1,)
212+
assert color_instance.swizzle("g") == (2,)
213+
assert color_instance.swizzle("b") == (3,)
214+
assert color_instance.swizzle("a") == (4,)
215+
assert color_instance.swizzle("R") == (1,)
216+
assert color_instance.swizzle("G") == (2,)
217+
assert color_instance.swizzle("B") == (3,)
218+
assert color_instance.swizzle("A") == (4,)
219+
220+
assert color_instance.swizzle("ra") == (1, 4)
221+
assert color_instance.swizzle("RA") == (1, 4)
222+
223+
assert color_instance.swizzle("aabbggrr") == (4, 4, 3, 3, 2, 2, 1, 1)
224+
assert color_instance.swizzle("AABBGGRR") == (4, 4, 3, 3, 2, 2, 1, 1)
225+
226+
204227
RANDINT_RETURN_RESULT = 128
205228

206229

0 commit comments

Comments
 (0)