wde_renderer/sync/mod.rs
1//! The sync module provides tools to synchronize entities, components and resources from the main world to the render world. This is useful for plugins that need to extract data from the main world and use it in the render world.
2//!
3//!
4//! # Extracting resources
5//! ## Manual extraction
6//! If you have a plugin that has resources that need to be extracted, you can implement the [`ExtractResource`] trait for those resources and add the corresponding [`ExtractResourcePlugin`] to your plugin. For example, if you have a plugin with a resource `MyResource`, you can do:
7//! ```
8//! app
9//! .insert_resource(MyResource { /* ... */ })
10//! .add_plugins(ExtractResourcePlugin::<MyResource>::default());
11//! ```
12//! This will automatically extract `MyResource` from the main world to the render world, and update it in the render world whenever it changes in the main world, without having to write the extraction system manually. The associated [`ExtractResource`] trait implementation will look like this:
13//! ```
14//! impl ExtractResource for MyResource {
15//! type Source = Self;
16//!
17//! fn extract(source: &Self::Source) -> Self {
18//! source.clone()
19//! }
20//! }
21//! ```
22//!
23//! ## ExtractResource macro
24//! If the extraction logic is simple, (i.e. when it only consists of cloning the resource), the trait implementation can be automatically derived using the [`ExtractResource`] derive macro. For example,
25//! ```
26//! #[derive(Resource, Clone, ExtractResource)]
27//! struct MyResource {
28//! value: i32,
29//! }
30//! ```
31//!
32//!
33//! # Syncing entities and components
34//! Entities from the main world can be synchronized to the render world by adding the [`SyncToRenderWorld`] component to them.
35//!
36//! ## Manual synchronization vs automatic synchronization
37//! One way to do this is to add the component manually to the entities that need to be synchronized. For example:
38//! ```
39//! commands.spawn((MyComponent { /* ... */ }, SyncToRenderWorld));
40//! ```
41//! Another way to synchronize entities is to use the [`SyncComponentPlugin`] for a component that is on those entities. For example, if you have a component `MyComponent` that is on the entities you want to synchronize, you can do:
42//! ```
43//! app.add_plugins(SyncComponentPlugin::<MyComponent>::default());
44//! ```
45//! This will automatically add the [`SyncToRenderWorld`] component to any entity that has `MyComponent`, which will trigger the synchronization of that entity to the render world.
46//!
47//! ## Synchronized entities
48//! After an entity is synchronized, it will have the following components in order to maintain the link between the main world and the render world:
49//! - In the main world, a [`RenderEntity`] component that stores the corresponding entity in the render world.
50//! - In the render world, a [`MainEntity`] component that stores the corresponding entity in the main world.
51//!
52//! You can access these components just like the [`Entity`] component (without &).
53//! For example, you can then create `extract` systems that query for every entity with `MyComponent` that changed in the main world (supposing you used [`SyncComponentPlugin`](crate::sync::SyncComponentPlugin) for `MyComponent`), and then extract these changes to their corresponding render world entities:
54//! ```rust
55//! fn extract_my_component(
56//! query: ExtractWorld<Query<(RenderEntity, &MyComponent), Changed<MyComponent>>>,
57//! mut commands: Commands
58//! ) {
59//! for (render_entity, my_component) in query.iter() {
60//! commands
61//! .entity(render_entity)
62//! .insert(MyComponent { /* ... */ });
63//! }
64//! }
65//! ```
66//! Note that one doesn't need to create this entity in the render world manually, as it is automatically managed by the synchronization system.
67//!
68//! ## Extracting components
69//! To simplify the process of extracting components, like the `extract_my_component` system in the example above, you can implement the [`ExtractComponent`] trait for a component and add the corresponding [`ExtractComponentPlugin`] to your plugin.
70//!
71//! For example, to implement the `extract_my_component` system above, first add the plugin:
72//! ```
73//! app.add_plugins(ExtractComponentPlugin::<MyComponent>::default());
74//! ```
75//! This will automatically add the [`SyncComponentPlugin`] for `MyComponent`.
76//! Then, you can implement the [`ExtractComponent`] and [`SyncComponent`] traits for `MyComponent`:
77//! ```
78//! impl SyncComponent for MyComponent {
79//! type Target = Self;
80//! }
81//! impl ExtractComponent for MyComponent {
82//! type QueryData = &'static Self;
83//! type QueryFilter = Changed<Self>;
84//! type Out = Self;
85//!!
86//! fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option<Self::Out> {
87//! Some(item.clone())
88//! // Note: If return None, remove the component from the entity in the render world
89//! }
90//! }
91//! ```
92//! This will automatically extract `MyComponent` from the main world to the render world for every entity that has `MyComponent` and for which `MyComponent` changed in the main world, without having to write the `extract_my_component` system manually.
93//!
94//! ## ExtractComponent macro
95//! When the extraction logic is simple, (i.e. when it only consists of cloning the component), the trait implementation of [`ExtractComponent`] and [`SyncComponent`] can be automatically derived using the [`ExtractComponent`] derive macro. For example,
96//! ```
97//! #[derive(Component, Clone, ExtractComponent)]
98//! #[extract_component_filter(Changed<Self>)]
99//! struct MyComponent {
100//! value: i32,
101//! }
102//! ```
103
104use bevy::prelude::*;
105
106mod extract_resource_plugin;
107mod extract_component_plugin;
108mod sync_worlds;
109mod sync_entities;
110mod sync_component;
111
112pub use extract_resource_plugin::*;
113pub use extract_component_plugin::*;
114pub use sync_worlds::*;
115pub use sync_entities::*;
116pub use sync_component::*;
117
118pub(crate) struct SyncPlugin;
119impl Plugin for SyncPlugin {
120 fn build(&self, app: &mut App) {
121 app.add_plugins(SyncWorldPlugin);
122 }
123}