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}