From cefb5b3d32a467a9195dac1ad3912923d8fddfc2 Mon Sep 17 00:00:00 2001 From: DragonMoffon Date: Tue, 19 Mar 2024 09:04:37 +1300 Subject: [PATCH 1/5] add visible flag and strip out changing alpha when setting visible This is so the alpha state is stored when setting visibility. originally it overrode the alpha which was stinky. --- arcade/sprite/base.py | 41 +++++++++++-------------------- arcade/sprite_list/sprite_list.py | 2 +- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/arcade/sprite/base.py b/arcade/sprite/base.py index 68e0d57b30..8707e181b9 100644 --- a/arcade/sprite/base.py +++ b/arcade/sprite/base.py @@ -38,6 +38,7 @@ class BasicSprite: "_color", "_texture", "_hit_box", + "_visible", "sprite_lists", "_angle", "__weakref__", @@ -49,6 +50,7 @@ def __init__( scale: float = 1.0, center_x: float = 0, center_y: float = 0, + visible: bool = True, **kwargs: Any, ) -> None: self._position = (center_x, center_y) @@ -57,6 +59,7 @@ def __init__( self._width = texture.width * scale self._height = texture.height * scale self._scale = scale, scale + self._visible = visible self._color: Color = Color(255, 255, 255, 255) self.sprite_lists: List["SpriteList"] = [] @@ -306,16 +309,15 @@ def visible(self) -> bool: sprite.visible = not sprite.visible """ - return self._color[3] > 0 + return self._visible @visible.setter def visible(self, value: bool): - self._color = Color( - self._color[0], - self._color[1], - self._color[2], - 255 if value else 0, - ) + if self._visible == value: + return + + self._visible = value + for sprite_list in self.sprite_lists: sprite_list._update_color(self) @@ -346,27 +348,14 @@ def color(self) -> Color: @color.setter def color(self, color: RGBA255): - if len(color) == 4: - if ( - self._color[0] == color[0] - and self._color[1] == color[1] - and self._color[2] == color[2] - and self._color[3] == color[3] - ): - return - self._color = Color.from_iterable(color) - - elif len(color) == 3: - if ( - self._color[0] == color[0] - and self._color[1] == color[1] - and self._color[2] == color[2] - ): - return - self._color = Color(color[0], color[1], color[2], self._color[3]) - else: + if color == self._color: + return + + if len(color) != 3 and len(color) != 4: raise ValueError("Color must be three or four ints from 0-255") + self._color = Color(color[0], color[1], color[2], self._color[3] if len(color) != 4 else color[3]) + for sprite_list in self.sprite_lists: sprite_list._update_color(self) diff --git a/arcade/sprite_list/sprite_list.py b/arcade/sprite_list/sprite_list.py index 5cc832ada7..a608466b36 100644 --- a/arcade/sprite_list/sprite_list.py +++ b/arcade/sprite_list/sprite_list.py @@ -1262,7 +1262,7 @@ def _update_color(self, sprite: SpriteType) -> None: self._sprite_color_data[slot * 4] = int(sprite._color[0]) self._sprite_color_data[slot * 4 + 1] = int(sprite._color[1]) self._sprite_color_data[slot * 4 + 2] = int(sprite._color[2]) - self._sprite_color_data[slot * 4 + 3] = int(sprite._color[3]) + self._sprite_color_data[slot * 4 + 3] = int(sprite._color[3] * sprite._visible) self._sprite_color_changed = True def _update_size(self, sprite: SpriteType) -> None: From c6ebe1ca24f3d8fb0f77cddcffd1ba02ea42f8ee Mon Sep 17 00:00:00 2001 From: DragonMoffon Date: Tue, 19 Mar 2024 10:07:04 +1300 Subject: [PATCH 2/5] removed alpha assumption from sprite unit tests --- tests/unit/sprite/test_sprite.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/unit/sprite/test_sprite.py b/tests/unit/sprite/test_sprite.py index 0ebcb20017..b12d677490 100644 --- a/tests/unit/sprite/test_sprite.py +++ b/tests/unit/sprite/test_sprite.py @@ -324,12 +324,10 @@ def test_visible(): # Make invisible sprite.visible = False assert sprite.visible is False - assert sprite.alpha == 0 # Make visible again sprite.visible = True assert sprite.visible is True - assert sprite.alpha == 255 def test_sprite_scale_xy(window): From 4f5234be7c667b4a14ce88ea5b059d448faaa4ec Mon Sep 17 00:00:00 2001 From: DragonMoffon Date: Thu, 21 Mar 2024 12:48:37 +1300 Subject: [PATCH 3/5] updating based on @pushfoo's suggestions --- arcade/sprite/base.py | 15 +++++++++++---- tests/unit/sprite/test_sprite.py | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arcade/sprite/base.py b/arcade/sprite/base.py index 8707e181b9..80a711a604 100644 --- a/arcade/sprite/base.py +++ b/arcade/sprite/base.py @@ -59,7 +59,7 @@ def __init__( self._width = texture.width * scale self._height = texture.height * scale self._scale = scale, scale - self._visible = visible + self._visible = bool(visible) self._color: Color = Color(255, 255, 255, 255) self.sprite_lists: List["SpriteList"] = [] @@ -313,6 +313,7 @@ def visible(self) -> bool: @visible.setter def visible(self, value: bool): + value = bool(value) if self._visible == value: return @@ -351,10 +352,16 @@ def color(self, color: RGBA255): if color == self._color: return - if len(color) != 3 and len(color) != 4: - raise ValueError("Color must be three or four ints from 0-255") + r, g, b, *_a = color - self._color = Color(color[0], color[1], color[2], self._color[3] if len(color) != 4 else color[3]) + if _a: + if len(_a) > 1: + raise ValueError(f"iterable must unpack to 3 or 4 values not {len(color)}") + a = _a[0] + else: + a = self._color.a + + self._color = Color(r, g, b, a) for sprite_list in self.sprite_lists: sprite_list._update_color(self) diff --git a/tests/unit/sprite/test_sprite.py b/tests/unit/sprite/test_sprite.py index b12d677490..1e88f6221a 100644 --- a/tests/unit/sprite/test_sprite.py +++ b/tests/unit/sprite/test_sprite.py @@ -321,13 +321,19 @@ def test_visible(): assert sprite.alpha == 255 assert sprite.visible is True + # initialise alpha value + sprite.alpha = 100 + assert sprite.alpha == 100 + # Make invisible sprite.visible = False assert sprite.visible is False + assert sprite.alpha == 100 # Make visible again sprite.visible = True assert sprite.visible is True + assert sprite.alpha == 100 def test_sprite_scale_xy(window): From f2677a8f36767d472b9724b4d39800577f094f0a Mon Sep 17 00:00:00 2001 From: DragonMoffon Date: Thu, 21 Mar 2024 16:30:36 +1300 Subject: [PATCH 4/5] improved typing --- arcade/sprite/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcade/sprite/base.py b/arcade/sprite/base.py index 80a711a604..e8226c9077 100644 --- a/arcade/sprite/base.py +++ b/arcade/sprite/base.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Iterable, List, TypeVar, Any import arcade -from arcade.types import Point, Color, RGBA255, PointList +from arcade.types import Point, Color, RGBA255, RGBOrA255, PointList from arcade.color import BLACK from arcade.hitbox import HitBox from arcade.texture import Texture @@ -348,7 +348,7 @@ def color(self) -> Color: return self._color @color.setter - def color(self, color: RGBA255): + def color(self, color: RGBOrA255): if color == self._color: return From 00a256d14e3c99db94a4a5b08b3fdc8b04d5ce61 Mon Sep 17 00:00:00 2001 From: Paul <36696816+pushfoo@users.noreply.github.com> Date: Thu, 21 Mar 2024 01:34:08 -0400 Subject: [PATCH 5/5] Improve docstring + comments for BasicSprite.visible (#4) * Correct and expand docstring for BasicSprite.visible * Add comment explaining that SpriteList handles the alpha/visible interaction --- arcade/sprite/base.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/arcade/sprite/base.py b/arcade/sprite/base.py index e8226c9077..a1f878b4a9 100644 --- a/arcade/sprite/base.py +++ b/arcade/sprite/base.py @@ -296,17 +296,32 @@ def top(self, amount: float): @property def visible(self) -> bool: - """ - Get or set the visibility of this sprite. - This is a shortcut for changing the alpha value of a sprite - to 0 or 255:: + """Get or set the visibility of this sprite. + + When set to ``False``, each :py:class:`~arcade.SpriteList` and + its attached shaders will treat the sprite as if has an + :py:attr:`.alpha` of 0. However, the sprite's actual values for + :py:attr:`.alpha` and :py:attr:`.color` will not change. + + .. code-block:: python + + # The initial color of the sprite + >>> sprite.color + Color(255, 255, 255, 255) # Make the sprite invisible - sprite.visible = False - # Change back to visible - sprite.visible = True - # Toggle visible - sprite.visible = not sprite.visible + >>> sprite.visible = False + # The sprite's color value has not changed + >>> sprite.color + Color(255, 255, 255, 255) + # The sprite's alpha value hasn't either + >>> sprite.alpha + 255 + + # Restore visibility + >>> sprite.visible = True + # Shorthand to toggle visible + >>> sprite.visible = not sprite.visible """ return self._visible @@ -361,6 +376,8 @@ def color(self, color: RGBOrA255): else: a = self._color.a + # We don't handle alpha and .visible interactions here + # because it's implemented in SpriteList._update_color self._color = Color(r, g, b, a) for sprite_list in self.sprite_lists: