Path: blob/main/crates/bevy_render/src/sync_component.rs
9324 views
use core::marker::PhantomData;12use bevy_app::{App, Plugin};3use bevy_ecs::{4bundle::{Bundle, NoBundleEffect},5component::Component,6};78use crate::sync_world::{EntityRecord, PendingSyncEntity, SyncToRenderWorld};910/// Plugin that registers a component for automatic sync to the render world. See [`SyncWorldPlugin`] for more information.11///12/// This plugin is automatically added by [`ExtractComponentPlugin`], and only needs to be added for manual extraction implementations.13///14/// # Implementation details15///16/// It adds [`SyncToRenderWorld`] as a required component to make the [`SyncWorldPlugin`] aware of the component, and17/// handles cleanup of the component in the render world when it is removed from an entity.18///19/// [`ExtractComponentPlugin`]: crate::extract_component::ExtractComponentPlugin20/// [`SyncWorldPlugin`]: crate::sync_world::SyncWorldPlugin21pub struct SyncComponentPlugin<C, Marker = ()>(PhantomData<(C, Marker)>);2223impl<C: SyncComponent<Marker>, Marker> Default for SyncComponentPlugin<C, Marker> {24fn default() -> Self {25Self(PhantomData)26}27}2829/// Trait that links components from the main world with output components in30/// the render world. It is used by [`SyncComponentPlugin`].31///32/// This trait is a subtrait of [`ExtractComponent`], which uses it to determine33/// which components to extract.34///35/// The marker type is only used as a way to bypass the orphan rules. To36/// implement the trait for a foreign type you can use a local type as the37/// marker, e.g. the type of the plugin that calls [`SyncComponentPlugin`].38///39/// [`ExtractComponent`]: crate::extract_component::ExtractComponent40pub trait SyncComponent<Marker = ()>: Component {41/// Describes what components should be removed from the render world if the42/// implementing component is removed.43///44/// It is also used by the [`ExtractComponent`] trait to determine which45/// components are generated during extraction.46///47/// [`ExtractComponent`]: crate::extract_component::ExtractComponent48type Out: Bundle<Effect: NoBundleEffect>;49// TODO: https://github.com/rust-lang/rust/issues/2966150// type Out: Component = Self;51}5253impl<C: SyncComponent<Marker>, Marker: Send + Sync + 'static> Plugin54for SyncComponentPlugin<C, Marker>55{56fn build(&self, app: &mut App) {57app.register_required_components::<C, SyncToRenderWorld>();5859app.world_mut()60.register_component_hooks::<C>()61.on_remove(|mut world, context| {62let mut pending = world.resource_mut::<PendingSyncEntity>();63pending.push(EntityRecord::ComponentRemoved(64context.entity,65|mut entity| {66entity.remove::<C::Out>();67},68));69});70}71}727374