Skip to content

Commit 89d4a4a

Browse files
authored
Add marker for ExtractResource (#22867)
# Objective - Followup to #22766 - Step towards #22852 ## Solution - Add marker to `ExtractResouce` - Pass marker to `SyncComponent` ## Testing - `cargo run --example animated_mesh`
1 parent d54e44f commit 89d4a4a

3 files changed

Lines changed: 35 additions & 21 deletions

File tree

crates/bevy_render/src/extract_component.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ impl<C: Component> DynamicUniformIndex<C> {
3838
///
3939
/// The Out type is defined in [`SyncComponent`].
4040
///
41-
/// The marker type is only used as a way to bypass the orphan rules. To
41+
/// The marker type `F` is only used as a way to bypass the orphan rules. To
4242
/// implement the trait for a foreign type you can use a local type as the
4343
/// marker, e.g. the type of the plugin that calls [`ExtractComponentPlugin`].
44-
pub trait ExtractComponent<Marker = ()>: SyncComponent {
44+
pub trait ExtractComponent<F = ()>: SyncComponent<F> {
4545
/// ECS [`ReadOnlyQueryData`] to fetch the components to extract.
4646
type QueryData: ReadOnlyQueryData;
4747
/// Filters the entities with additional constraints.
@@ -151,6 +151,10 @@ fn prepare_uniform_components<C>(
151151
///
152152
/// It also registers [`SyncComponentPlugin`] to ensure the extracted components
153153
/// are deleted if the main world components are removed.
154+
///
155+
/// The marker type `F` is only used as a way to bypass the orphan rules. To
156+
/// implement the trait for a foreign type you can use a local type as the
157+
/// marker, e.g. the type of the plugin that calls [`ExtractComponentPlugin`].
154158
pub struct ExtractComponentPlugin<C, F = ()> {
155159
only_extract_visible: bool,
156160
marker: PhantomData<fn() -> (C, F)>,
@@ -174,22 +178,22 @@ impl<C, F> ExtractComponentPlugin<C, F> {
174178
}
175179
}
176180

177-
impl<C: ExtractComponent<Marker>, Marker: 'static> Plugin for ExtractComponentPlugin<C, Marker> {
181+
impl<C: ExtractComponent<F>, F: 'static + Send + Sync> Plugin for ExtractComponentPlugin<C, F> {
178182
fn build(&self, app: &mut App) {
179-
app.add_plugins(SyncComponentPlugin::<C>::default());
183+
app.add_plugins(SyncComponentPlugin::<C, F>::default());
180184

181185
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
182186
if self.only_extract_visible {
183-
render_app.add_systems(ExtractSchedule, extract_visible_components::<C, Marker>);
187+
render_app.add_systems(ExtractSchedule, extract_visible_components::<C, F>);
184188
} else {
185-
render_app.add_systems(ExtractSchedule, extract_components::<C, Marker>);
189+
render_app.add_systems(ExtractSchedule, extract_components::<C, F>);
186190
}
187191
}
188192
}
189193
}
190194

191195
/// This system extracts all components of the corresponding [`ExtractComponent`], for entities that are synced via [`crate::sync_world::SyncToRenderWorld`].
192-
fn extract_components<C: ExtractComponent<Marker>, Marker>(
196+
fn extract_components<C: ExtractComponent<F>, F>(
193197
mut commands: Commands,
194198
mut previous_len: Local<usize>,
195199
query: Extract<Query<(RenderEntity, C::QueryData), C::QueryFilter>>,
@@ -207,7 +211,7 @@ fn extract_components<C: ExtractComponent<Marker>, Marker>(
207211
}
208212

209213
/// This system extracts all components of the corresponding [`ExtractComponent`], for entities that are visible and synced via [`crate::sync_world::SyncToRenderWorld`].
210-
fn extract_visible_components<C: ExtractComponent<Marker>, Marker>(
214+
fn extract_visible_components<C: ExtractComponent<F>, F>(
211215
mut commands: Commands,
212216
mut previous_len: Local<usize>,
213217
query: Extract<Query<(RenderEntity, &ViewVisibility, C::QueryData), C::QueryFilter>>,

crates/bevy_render/src/extract_resource.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ use crate::{Extract, ExtractSchedule, RenderApp};
1111
///
1212
/// Therefore the resource is transferred from the "main world" into the "render world"
1313
/// in the [`ExtractSchedule`] step.
14-
pub trait ExtractResource: Resource {
14+
///
15+
/// The marker type `F` is only used as a way to bypass the orphan rules. To
16+
/// implement the trait for a foreign type you can use a local type as the
17+
/// marker, e.g. the type of the plugin that calls [`ExtractResourcePlugin`].
18+
pub trait ExtractResource<F = ()>: Resource {
1519
type Source: Resource;
1620

1721
/// Defines how the resource is transferred into the "render world".
@@ -22,18 +26,22 @@ pub trait ExtractResource: Resource {
2226
///
2327
/// Therefore it sets up the[`ExtractSchedule`] step
2428
/// for the specified [`Resource`].
25-
pub struct ExtractResourcePlugin<R: ExtractResource>(PhantomData<R>);
29+
///
30+
/// The marker type `F` is only used as a way to bypass the orphan rules. To
31+
/// implement the trait for a foreign type you can use a local type as the
32+
/// marker, e.g. the type of the plugin that calls [`ExtractResourcePlugin`].
33+
pub struct ExtractResourcePlugin<R: ExtractResource<F>, F = ()>(PhantomData<(R, F)>);
2634

27-
impl<R: ExtractResource> Default for ExtractResourcePlugin<R> {
35+
impl<R: ExtractResource<F>, F> Default for ExtractResourcePlugin<R, F> {
2836
fn default() -> Self {
2937
Self(PhantomData)
3038
}
3139
}
3240

33-
impl<R: ExtractResource> Plugin for ExtractResourcePlugin<R> {
41+
impl<R: ExtractResource<F>, F: 'static + Send + Sync> Plugin for ExtractResourcePlugin<R, F> {
3442
fn build(&self, app: &mut App) {
3543
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
36-
render_app.add_systems(ExtractSchedule, extract_resource::<R>);
44+
render_app.add_systems(ExtractSchedule, extract_resource::<R, F>);
3745
} else {
3846
once!(bevy_log::error!(
3947
"Render app did not exist when trying to add `extract_resource` for <{}>.",
@@ -44,7 +52,7 @@ impl<R: ExtractResource> Plugin for ExtractResourcePlugin<R> {
4452
}
4553

4654
/// This system extracts the resource of the corresponding [`Resource`] type
47-
pub fn extract_resource<R: ExtractResource>(
55+
pub fn extract_resource<R: ExtractResource<F>, F>(
4856
mut commands: Commands,
4957
main_resource: Extract<Option<Res<R::Source>>>,
5058
target_resource: Option<ResMut<R>>,

crates/bevy_render/src/sync_component.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@ use crate::sync_world::{EntityRecord, PendingSyncEntity, SyncToRenderWorld};
1212
///
1313
/// This plugin is automatically added by [`ExtractComponentPlugin`], and only needs to be added for manual extraction implementations.
1414
///
15+
/// The marker type `F` is only used as a way to bypass the orphan rules. To
16+
/// implement the trait for a foreign type you can use a local type as the
17+
/// marker, e.g. the type of the plugin that calls [`SyncComponentPlugin`].
18+
///
1519
/// # Implementation details
1620
///
1721
/// It adds [`SyncToRenderWorld`] as a required component to make the [`SyncWorldPlugin`] aware of the component, and
1822
/// handles cleanup of the component in the render world when it is removed from an entity.
1923
///
2024
/// [`ExtractComponentPlugin`]: crate::extract_component::ExtractComponentPlugin
2125
/// [`SyncWorldPlugin`]: crate::sync_world::SyncWorldPlugin
22-
pub struct SyncComponentPlugin<C, Marker = ()>(PhantomData<(C, Marker)>);
26+
pub struct SyncComponentPlugin<C, F = ()>(PhantomData<(C, F)>);
2327

24-
impl<C: SyncComponent<Marker>, Marker> Default for SyncComponentPlugin<C, Marker> {
28+
impl<C: SyncComponent<F>, F> Default for SyncComponentPlugin<C, F> {
2529
fn default() -> Self {
2630
Self(PhantomData)
2731
}
@@ -33,12 +37,12 @@ impl<C: SyncComponent<Marker>, Marker> Default for SyncComponentPlugin<C, Marker
3337
/// This trait is a subtrait of [`ExtractComponent`], which uses it to determine
3438
/// which components to extract.
3539
///
36-
/// The marker type is only used as a way to bypass the orphan rules. To
40+
/// The marker type `F` is only used as a way to bypass the orphan rules. To
3741
/// implement the trait for a foreign type you can use a local type as the
3842
/// marker, e.g. the type of the plugin that calls [`SyncComponentPlugin`].
3943
///
4044
/// [`ExtractComponent`]: crate::extract_component::ExtractComponent
41-
pub trait SyncComponent<Marker = ()>: Component {
45+
pub trait SyncComponent<F = ()>: Component {
4246
/// Describes what components should be removed from the render world if the
4347
/// implementing component is removed.
4448
///
@@ -51,9 +55,7 @@ pub trait SyncComponent<Marker = ()>: Component {
5155
// type Out: Component = Self;
5256
}
5357

54-
impl<C: SyncComponent<Marker>, Marker: Send + Sync + 'static> Plugin
55-
for SyncComponentPlugin<C, Marker>
56-
{
58+
impl<C: SyncComponent<F>, F: Send + Sync + 'static> Plugin for SyncComponentPlugin<C, F> {
5759
fn build(&self, app: &mut App) {
5860
app.register_required_components::<C, SyncToRenderWorld>();
5961

0 commit comments

Comments
 (0)