Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Extract component derive #7399

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{clear_color::ClearColorConfig, tonemapping::Tonemapping};
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_ecs::prelude::*;
use bevy_reflect::Reflect;
use bevy_render::{
camera::{Camera, CameraProjection, CameraRenderGraph, OrthographicProjection},
Expand All @@ -9,22 +9,13 @@ use bevy_render::{
};
use bevy_transform::prelude::{GlobalTransform, Transform};

#[derive(Component, Default, Reflect, Clone)]
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component)]
pub struct Camera2d {
pub clear_color: ClearColorConfig,
}

impl ExtractComponent for Camera2d {
type Query = &'static Self;
type Filter = With<Camera>;
type Out = Self;

fn extract_component(item: QueryItem<'_, Self::Query>) -> Option<Self> {
Some(item.clone())
}
}

#[derive(Bundle)]
pub struct Camera2dBundle {
pub camera: Camera,
Expand Down
15 changes: 3 additions & 12 deletions crates/bevy_core_pipeline/src/core_3d/camera_3d.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{clear_color::ClearColorConfig, tonemapping::Tonemapping};
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_ecs::prelude::*;
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
use bevy_render::{
camera::{Camera, CameraRenderGraph, Projection},
Expand All @@ -12,7 +12,8 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
use serde::{Deserialize, Serialize};

/// Configuration for the "main 3d render graph".
#[derive(Component, Reflect, Clone, Default)]
#[derive(Component, Reflect, Clone, Default, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component)]
pub struct Camera3d {
/// The clear color operation to perform for the main 3d pass.
Expand Down Expand Up @@ -47,16 +48,6 @@ impl From<Camera3dDepthLoadOp> for LoadOp<f32> {
}
}

impl ExtractComponent for Camera3d {
type Query = &'static Self;
type Filter = With<Camera>;
type Out = Self;

fn extract_component(item: QueryItem<'_, Self::Query>) -> Option<Self> {
Some(item.clone())
}
}

#[derive(Bundle)]
pub struct Camera3dBundle {
pub camera: Camera,
Expand Down
15 changes: 3 additions & 12 deletions crates/bevy_core_pipeline/src/fxaa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{core_2d, core_3d, fullscreen_vertex_shader::fullscreen_shader_vertex
use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, HandleUntyped};
use bevy_derive::Deref;
use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_ecs::prelude::*;
use bevy_reflect::TypeUuid;
use bevy_render::{
extract_component::{ExtractComponent, ExtractComponentPlugin},
Expand Down Expand Up @@ -40,7 +40,8 @@ impl Sensitivity {
}
}

#[derive(Component, Clone)]
#[derive(Component, Clone, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
pub struct Fxaa {
/// Enable render passes for FXAA.
pub enabled: bool,
Expand All @@ -67,16 +68,6 @@ impl Default for Fxaa {
}
}

impl ExtractComponent for Fxaa {
type Query = &'static Self;
type Filter = With<Camera>;
type Out = Self;

fn extract_component(item: QueryItem<Self::Query>) -> Option<Self> {
Some(item.clone())
}
}

const FXAA_SHADER_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 4182761465141723543);

Expand Down
14 changes: 2 additions & 12 deletions crates/bevy_core_pipeline/src/tonemapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, HandleUntyped};
use bevy_ecs::prelude::*;
use bevy_ecs::query::QueryItem;
use bevy_reflect::{Reflect, TypeUuid};
use bevy_render::camera::Camera;
use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin};
Expand Down Expand Up @@ -145,7 +144,8 @@ pub fn queue_view_tonemapping_pipelines(
}
}

#[derive(Component, Clone, Reflect, Default)]
#[derive(Component, Clone, Reflect, Default, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
#[reflect(Component)]
pub enum Tonemapping {
#[default]
Expand All @@ -160,13 +160,3 @@ impl Tonemapping {
matches!(self, Tonemapping::Enabled { .. })
}
}

impl ExtractComponent for Tonemapping {
type Query = &'static Self;
type Filter = With<Camera>;
type Out = Self;

fn extract_component(item: QueryItem<Self::Query>) -> Option<Self::Out> {
Some(item.clone())
}
}
14 changes: 4 additions & 10 deletions crates/bevy_pbr/src/wireframe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use bevy_core_pipeline::core_3d::Opaque3d;
use bevy_ecs::{prelude::*, reflect::ReflectComponent};
use bevy_reflect::std_traits::ReflectDefault;
use bevy_reflect::{Reflect, TypeUuid};
use bevy_render::Extract;
use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin};
use bevy_render::{
extract_resource::{ExtractResource, ExtractResourcePlugin},
mesh::{Mesh, MeshVertexBufferLayout},
Expand Down Expand Up @@ -39,27 +39,21 @@ impl Plugin for WireframePlugin {
app.register_type::<Wireframe>()
.register_type::<WireframeConfig>()
.init_resource::<WireframeConfig>()
.add_plugin(ExtractResourcePlugin::<WireframeConfig>::default());
.add_plugin(ExtractResourcePlugin::<WireframeConfig>::default())
.add_plugin(ExtractComponentPlugin::<Wireframe>::default());

if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
.add_render_command::<Opaque3d, DrawWireframes>()
.init_resource::<WireframePipeline>()
.init_resource::<SpecializedMeshPipelines<WireframePipeline>>()
.add_system_to_stage(RenderStage::Extract, extract_wireframes)
.add_system_to_stage(RenderStage::Queue, queue_wireframes);
}
}
}

fn extract_wireframes(mut commands: Commands, query: Extract<Query<Entity, With<Wireframe>>>) {
for entity in &query {
commands.get_or_spawn(entity).insert(Wireframe);
}
}

/// Controls whether an entity should rendered in wireframe-mode if the [`WireframePlugin`] is enabled
#[derive(Component, Debug, Clone, Default, Reflect)]
#[derive(Component, Debug, Clone, Default, ExtractComponent, Reflect)]
#[reflect(Component, Default)]
pub struct Wireframe;

Expand Down
51 changes: 51 additions & 0 deletions crates/bevy_render/macros/src/extract_component.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote, DeriveInput, Path};

pub fn derive_extract_component(input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput);
let bevy_render_path: Path = crate::bevy_render_path();
let bevy_ecs_path: Path = bevy_macro_utils::BevyManifest::default()
.maybe_get_path("bevy_ecs")
.expect("bevy_ecs should be found in manifest");

ast.generics
.make_where_clause()
.predicates
.push(parse_quote! { Self: Clone });

let struct_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

let filter = if let Some(attr) = ast
.attrs
.iter()
.find(|a| a.path.is_ident("extract_component_filter"))
{
let filter = match attr.parse_args::<syn::Type>() {
Ok(filter) => filter,
Err(e) => return e.to_compile_error().into(),
};

quote! {
#filter
}
} else {
quote! {
()
}
};

TokenStream::from(quote! {
impl #impl_generics #bevy_render_path::extract_component::ExtractComponent for #struct_name #type_generics #where_clause {
type Query = &'static Self;

type Filter = #filter;
type Out = Self;

fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, Self::Query>) -> Option<Self::Out> {
Some(item.clone())
}
}
})
}
32 changes: 32 additions & 0 deletions crates/bevy_render/macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod as_bind_group;
mod extract_component;
mod extract_resource;

use bevy_macro_utils::BevyManifest;
Expand All @@ -17,6 +18,37 @@ pub fn derive_extract_resource(input: TokenStream) -> TokenStream {
extract_resource::derive_extract_resource(input)
}

/// Implements `ExtractComponent` trait for a component.
torsteingrindvik marked this conversation as resolved.
Show resolved Hide resolved
/// The component must implement [`Clone`].
/// The component will be extracted into the render world via cloning.
/// Note that this only enables extraction of the component, it does not execute the extraction.
/// See `ExtractComponentPlugin` to actually perform the extraction.
///
/// If you only want to extract a component conditionally, you may use the `extract_component_filter` attribute.
///
/// # Example
///
/// ```rust
/// use bevy_ecs::component::Component;
/// use bevy_render_macros::ExtractComponent;
///
/// #[derive(Component, Clone, ExtractComponent)]
/// #[extract_component_filter(With<Camera>)]
/// pub struct Foo {
/// pub should_foo: bool,
/// }
///
/// // Without a filter (unconditional).
/// #[derive(Component, Clone, ExtractComponent)]
/// pub struct Bar {
/// pub should_bar: bool,
/// }
/// ```
#[proc_macro_derive(ExtractComponent, attributes(extract_component_filter))]
pub fn derive_extract_component(input: TokenStream) -> TokenStream {
extract_component::derive_extract_component(input)
}

#[proc_macro_derive(
AsBindGroup,
attributes(uniform, texture, sampler, bind_group_data, storage)
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_render/src/extract_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use bevy_ecs::{
};
use std::{marker::PhantomData, ops::Deref};

pub use bevy_render_macros::ExtractComponent;

/// Stores the index of a uniform inside of [`ComponentUniforms`].
#[derive(Component)]
pub struct DynamicUniformIndex<C: Component> {
Expand Down
14 changes: 2 additions & 12 deletions crates/bevy_ui/src/camera_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use bevy_ecs::component::Component;
use bevy_ecs::prelude::With;
use bevy_ecs::query::QueryItem;
use bevy_render::camera::Camera;
use bevy_render::extract_component::ExtractComponent;

Expand All @@ -11,7 +10,8 @@ use bevy_render::extract_component::ExtractComponent;
/// When a [`Camera`] doesn't have the [`UiCameraConfig`] component,
/// it will display the UI by default.
///
#[derive(Component, Clone)]
#[derive(Component, Clone, ExtractComponent)]
#[extract_component_filter(With<Camera>)]
pub struct UiCameraConfig {
/// Whether to output UI to this camera view.
///
Expand All @@ -25,13 +25,3 @@ impl Default for UiCameraConfig {
Self { show_ui: true }
}
}

impl ExtractComponent for UiCameraConfig {
type Query = &'static Self;
type Filter = With<Camera>;
type Out = Self;

fn extract_component(item: QueryItem<'_, Self::Query>) -> Option<Self> {
Some(item.clone())
}
}