Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_render/src/sync_component.rs
9324 views
1
use core::marker::PhantomData;
2
3
use bevy_app::{App, Plugin};
4
use bevy_ecs::{
5
bundle::{Bundle, NoBundleEffect},
6
component::Component,
7
};
8
9
use crate::sync_world::{EntityRecord, PendingSyncEntity, SyncToRenderWorld};
10
11
/// Plugin that registers a component for automatic sync to the render world. See [`SyncWorldPlugin`] for more information.
12
///
13
/// This plugin is automatically added by [`ExtractComponentPlugin`], and only needs to be added for manual extraction implementations.
14
///
15
/// # Implementation details
16
///
17
/// It adds [`SyncToRenderWorld`] as a required component to make the [`SyncWorldPlugin`] aware of the component, and
18
/// handles cleanup of the component in the render world when it is removed from an entity.
19
///
20
/// [`ExtractComponentPlugin`]: crate::extract_component::ExtractComponentPlugin
21
/// [`SyncWorldPlugin`]: crate::sync_world::SyncWorldPlugin
22
pub struct SyncComponentPlugin<C, Marker = ()>(PhantomData<(C, Marker)>);
23
24
impl<C: SyncComponent<Marker>, Marker> Default for SyncComponentPlugin<C, Marker> {
25
fn default() -> Self {
26
Self(PhantomData)
27
}
28
}
29
30
/// Trait that links components from the main world with output components in
31
/// the render world. It is used by [`SyncComponentPlugin`].
32
///
33
/// This trait is a subtrait of [`ExtractComponent`], which uses it to determine
34
/// which components to extract.
35
///
36
/// The marker type is only used as a way to bypass the orphan rules. To
37
/// implement the trait for a foreign type you can use a local type as the
38
/// marker, e.g. the type of the plugin that calls [`SyncComponentPlugin`].
39
///
40
/// [`ExtractComponent`]: crate::extract_component::ExtractComponent
41
pub trait SyncComponent<Marker = ()>: Component {
42
/// Describes what components should be removed from the render world if the
43
/// implementing component is removed.
44
///
45
/// It is also used by the [`ExtractComponent`] trait to determine which
46
/// components are generated during extraction.
47
///
48
/// [`ExtractComponent`]: crate::extract_component::ExtractComponent
49
type Out: Bundle<Effect: NoBundleEffect>;
50
// TODO: https://github.com/rust-lang/rust/issues/29661
51
// type Out: Component = Self;
52
}
53
54
impl<C: SyncComponent<Marker>, Marker: Send + Sync + 'static> Plugin
55
for SyncComponentPlugin<C, Marker>
56
{
57
fn build(&self, app: &mut App) {
58
app.register_required_components::<C, SyncToRenderWorld>();
59
60
app.world_mut()
61
.register_component_hooks::<C>()
62
.on_remove(|mut world, context| {
63
let mut pending = world.resource_mut::<PendingSyncEntity>();
64
pending.push(EntityRecord::ComponentRemoved(
65
context.entity,
66
|mut entity| {
67
entity.remove::<C::Out>();
68
},
69
));
70
});
71
}
72
}
73
74