wde_renderer/sync/sync_component.rs
1use std::marker::PhantomData;
2
3use bevy::{ecs::bundle::NoBundleEffect, prelude::*};
4
5use crate::sync::{EntityRecord, PendingSyncEntity, SyncToRenderWorld};
6
7/// Plugin that registers a component for automatic sync to the render world.
8///
9/// If an entity ([MainEntity](crate::sync::MainEntity)) has a component that implements [`SyncComponent`] it will automatically have the [`SyncToRenderWorld`] component added, which will trigger the synchronization of that entity to the render world ([RenderEntity](crate::sync::RenderEntity))).
10/// See [`sync`](crate::sync) for more details.
11pub struct SyncComponentPlugin<C, F = ()>(PhantomData<(C, F)>);
12impl<C: SyncComponent<F>, F> Default for SyncComponentPlugin<C, F> {
13 fn default() -> Self {
14 Self(PhantomData)
15 }
16}
17
18/// Trait that links components from the main world with output components in the render world. It is used by [`SyncComponentPlugin`].
19pub trait SyncComponent<F = ()>: Component {
20 /// Describes what components should be removed from the render world if the implementing component is removed.
21 type Target: Bundle<Effect: NoBundleEffect>;
22}
23impl<C: SyncComponent<F>, F: Send + Sync + 'static> Plugin for SyncComponentPlugin<C, F> {
24 fn build(&self, app: &mut App) {
25 // Register the SyncToRenderWorld component as required for this C component.
26 app.register_required_components::<C, SyncToRenderWorld>();
27
28 app.world_mut()
29 .register_component_hooks::<C>()
30 .on_remove(|mut world, context| {
31 let mut pending = world.resource_mut::<PendingSyncEntity>();
32 pending.push(EntityRecord::ComponentRemoved(
33 context.entity,
34 |mut entity| {
35 entity.remove::<C::Target>();
36 }
37 ));
38 });
39 }
40}