Skip to main content

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}