bevy_render/
sync_component.rs

1use core::marker::PhantomData;
2
3use bevy_app::{App, Plugin};
4use bevy_ecs::component::Component;
5
6use crate::sync_world::{EntityRecord, PendingSyncEntity, SyncToRenderWorld};
7
8/// Plugin that registers a component for automatic sync to the render world. See [`SyncWorldPlugin`] for more information.
9///
10/// This plugin is automatically added by [`ExtractComponentPlugin`], and only needs to be added for manual extraction implementations.
11///
12/// # Implementation details
13///
14/// It adds [`SyncToRenderWorld`] as a required component to make the [`SyncWorldPlugin`] aware of the component, and
15/// handles cleanup of the component in the render world when it is removed from an entity.
16///
17/// # Warning
18/// When the component is removed from the main world entity, all components are removed from the entity in the render world.
19/// This is done in order to handle components with custom extraction logic and derived state.
20///
21/// [`ExtractComponentPlugin`]: crate::extract_component::ExtractComponentPlugin
22/// [`SyncWorldPlugin`]: crate::sync_world::SyncWorldPlugin
23pub struct SyncComponentPlugin<C: Component>(PhantomData<C>);
24
25impl<C: Component> Default for SyncComponentPlugin<C> {
26    fn default() -> Self {
27        Self(PhantomData)
28    }
29}
30
31impl<C: Component> Plugin for SyncComponentPlugin<C> {
32    fn build(&self, app: &mut App) {
33        app.register_required_components::<C, SyncToRenderWorld>();
34
35        app.world_mut().register_component_hooks::<C>().on_remove(
36            |mut world, entity, _component_id| {
37                let mut pending = world.resource_mut::<PendingSyncEntity>();
38                pending.push(EntityRecord::ComponentRemoved(entity));
39            },
40        );
41    }
42}