diff --git a/arcade/sprite_list/sprite_list.py b/arcade/sprite_list/sprite_list.py index d24641dea6..613e59702c 100644 --- a/arcade/sprite_list/sprite_list.py +++ b/arcade/sprite_list/sprite_list.py @@ -751,10 +751,15 @@ def insert(self, index: int, sprite: SpriteType) -> None: self._grow_index_buffer() self._sprite_index_data.insert(index, slot) self._sprite_index_data.pop() + self._sprite_index_changed = True if self.spatial_hash is not None: self.spatial_hash.add(sprite) + if self._initialized: + if sprite.texture is None: + raise ValueError("Sprite must have a texture when added to a SpriteList") + def reverse(self) -> None: """Reverses the current list in-place""" # Reverse the sprites and index buffer diff --git a/tests/unit/spritelist/test_spritelist.py b/tests/unit/spritelist/test_spritelist.py index b0f371eced..07277b4700 100644 --- a/tests/unit/spritelist/test_spritelist.py +++ b/tests/unit/spritelist/test_spritelist.py @@ -116,6 +116,23 @@ def test_it_can_insert_in_a_spritelist(): assert [spritelist.sprite_slot[s] for s in spritelist] == [0, 2, 1] # Index buffer should refer to the slots in the same order assert list(spritelist._sprite_index_data[:3]) == [0, 2, 1] + # insert() must flag the index buffer as changed so the sprite is + # actually uploaded to the GPU and rendered on the next draw (#2863) + assert spritelist._sprite_index_changed is True + + +def test_insert_requires_texture_when_initialized(ctx): + """insert() into an initialized list should validate the texture, like append()""" + spritelist = make_named_sprites(1) + # Force initialization (as a draw would do) + spritelist.draw() + + sprite = arcade.SpriteSolidColor(16, 16, color=arcade.color.RED) + # Bypass the texture setter to simulate a textureless sprite + sprite._texture = None + + with pytest.raises(ValueError): + spritelist.insert(0, sprite) def test_it_can_reverse_a_spritelist():