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 { Self(PhantomData) }
14}
15
16/// Trait that links components from the main world with output components in the render world. It is used by [`SyncComponentPlugin`].
17pub trait SyncComponent<F = ()>: Component {
18 /// Describes what components should be removed from the render world if the implementing component is removed.
19 type Target: Bundle<Effect: NoBundleEffect>;
20}
21impl<C: SyncComponent<F>, F: Send + Sync + 'static> Plugin for SyncComponentPlugin<C, F> {
22 fn build(&self, app: &mut App) {
23 // Register the SyncToRenderWorld component as required for this C component.
24 app.register_required_components::<C, SyncToRenderWorld>();
25
26 app.world_mut()
27 .register_component_hooks::<C>()
28 .on_remove(|mut world, context| {
29 let mut pending = world.resource_mut::<PendingSyncEntity>();
30 pending.push(EntityRecord::ComponentRemoved(
31 context.entity,
32 |mut entity| {
33 entity.remove::<C::Target>();
34 },
35 ));
36 });
37 }
38}