bevy/crates/bevy_sprite/src/bundle.rs
Kristoffer Søholm 2d1b4939d2
Synchronize removed components with the render world (#15582)
# Objective

Fixes #15560
Fixes (most of) #15570

Currently a lot of examples (and presumably some user code) depend on
toggling certain render features by adding/removing a single component
to an entity, e.g. `SpotLight` to toggle a light. Because of the
retained render world this no longer works: Extract will add any new
components, but when it is removed the entity persists unchanged in the
render world.

## Solution

Add `SyncComponentPlugin<C: Component>` that registers
`SyncToRenderWorld` as a required component for `C`, and adds a
component hook that will clear all components from the render world
entity when `C` is removed. We add this plugin to
`ExtractComponentPlugin` which fixes most instances of the problem. For
custom extraction logic we can manually add `SyncComponentPlugin` for
that component.

We also rename `WorldSyncPlugin` to `SyncWorldPlugin` so we start a
naming convention like all the `Extract` plugins.

In this PR I also fixed a bunch of breakage related to the retained
render world, stemming from old code that assumed that `Entity` would be
the same in both worlds.

I found that using the `RenderEntity` wrapper instead of `Entity` in
data structures when referring to render world entities makes intent
much clearer, so I propose we make this an official pattern.

## Testing

Run examples like

```
cargo run --features pbr_multi_layer_material_textures --example clearcoat
cargo run --example volumetric_fog
```

and see that they work, and that toggles work correctly. But really we
should test every single example, as we might not even have caught all
the breakage yet.

---

## Migration Guide

The retained render world notes should be updated to explain this edge
case and `SyncComponentPlugin`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Trashtalk217 <trashtalk217@gmail.com>
2024-10-08 22:23:17 +00:00

36 lines
1.6 KiB
Rust

use crate::Sprite;
use bevy_asset::Handle;
use bevy_ecs::bundle::Bundle;
use bevy_render::{
sync_world::SyncToRenderWorld,
texture::Image,
view::{InheritedVisibility, ViewVisibility, Visibility},
};
use bevy_transform::components::{GlobalTransform, Transform};
/// A [`Bundle`] of components for drawing a single sprite from an image.
///
/// # Extra behaviours
///
/// You may add one or both of the following components to enable additional behaviours:
/// - [`ImageScaleMode`](crate::ImageScaleMode) to enable either slicing or tiling of the texture
/// - [`TextureAtlas`](crate::TextureAtlas) to draw a specific section of the texture
#[derive(Bundle, Clone, Debug, Default)]
pub struct SpriteBundle {
/// Specifies the rendering properties of the sprite, such as color tint and flip.
pub sprite: Sprite,
/// The local transform of the sprite, relative to its parent.
pub transform: Transform,
/// The absolute transform of the sprite. This should generally not be written to directly.
pub global_transform: GlobalTransform,
/// A reference-counted handle to the image asset to be drawn.
pub texture: Handle<Image>,
/// User indication of whether an entity is visible
pub visibility: Visibility,
/// Inherited visibility of an entity.
pub inherited_visibility: InheritedVisibility,
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
pub view_visibility: ViewVisibility,
/// Marker component that indicates that its entity needs to be synchronized to the render world
pub sync: SyncToRenderWorld,
}