Skip to main content

bevy_render_macros/
lib.rs

1#![expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4mod as_bind_group;
5mod extract_component;
6mod extract_resource;
7mod specializer;
8
9use bevy_macro_utils::{derive_label, BevyManifest};
10use proc_macro::TokenStream;
11use quote::format_ident;
12use syn::{parse_macro_input, DeriveInput};
13
14pub(crate) fn bevy_render_path() -> syn::Path {
15    BevyManifest::shared(|manifest| manifest.get_path("bevy_render"))
16}
17
18pub(crate) fn bevy_ecs_path() -> syn::Path {
19    BevyManifest::shared(|manifest| manifest.get_path("bevy_ecs"))
20}
21
22#[proc_macro_derive(ExtractResource)]
23pub fn derive_extract_resource(input: TokenStream) -> TokenStream {
24    extract_resource::derive_extract_resource(input)
25}
26
27/// Implements `ExtractComponent` trait for a component.
28///
29/// The component must implement [`Clone`].
30/// The component will be extracted into the render world via cloning.
31/// Note that this only enables extraction of the component, it does not execute the extraction.
32/// See `ExtractComponentPlugin` to actually perform the extraction.
33///
34/// If you only want to extract a component conditionally, you may use the `extract_component_filter` attribute.
35/// To specify `SyncComponent::Target`, you can use the `extract_component_sync_target` attribute.
36///
37/// # Example
38///
39/// ```no_compile
40/// use bevy_ecs::component::Component;
41/// use bevy_render_macros::ExtractComponent;
42///
43/// #[derive(Component, Clone, ExtractComponent)]
44/// #[extract_component_filter(With<Camera>)]
45/// #[extract_component_sync_target((Self, OtherNeedsCleanup))]
46/// pub struct Foo {
47///     pub should_foo: bool,
48/// }
49///
50/// // Without a filter (unconditional).
51/// #[derive(Component, Clone, ExtractComponent)]
52/// pub struct Bar {
53///     pub should_bar: bool,
54/// }
55/// ```
56#[proc_macro_derive(
57    ExtractComponent,
58    attributes(extract_component_filter, extract_component_sync_target)
59)]
60pub fn derive_extract_component(input: TokenStream) -> TokenStream {
61    extract_component::derive_extract_component(input)
62}
63
64#[proc_macro_derive(
65    AsBindGroup,
66    attributes(
67        uniform,
68        storage_texture,
69        texture,
70        sampler,
71        bind_group_data,
72        storage,
73        bindless,
74        data
75    )
76)]
77pub fn derive_as_bind_group(input: TokenStream) -> TokenStream {
78    let input = parse_macro_input!(input as DeriveInput);
79
80    as_bind_group::derive_as_bind_group(input).unwrap_or_else(|err| err.to_compile_error().into())
81}
82
83/// Derive macro generating an impl of the trait `RenderLabel`.
84///
85/// This does not work for unions.
86#[proc_macro_derive(RenderLabel)]
87pub fn derive_render_label(input: TokenStream) -> TokenStream {
88    let input = parse_macro_input!(input as DeriveInput);
89    let mut trait_path = bevy_render_path();
90    trait_path
91        .segments
92        .push(format_ident!("render_graph").into());
93    trait_path
94        .segments
95        .push(format_ident!("RenderLabel").into());
96    derive_label(input, "RenderLabel", &trait_path)
97}
98
99/// Derive macro generating an impl of the trait `Specializer`
100///
101/// This only works for structs whose members all implement `Specializer`
102#[proc_macro_derive(Specializer, attributes(specialize, key, base_descriptor))]
103pub fn derive_specialize(input: TokenStream) -> TokenStream {
104    specializer::impl_specializer(input)
105}
106
107/// Derive macro generating the most common impl of the trait `SpecializerKey`
108#[proc_macro_derive(SpecializerKey)]
109pub fn derive_specializer_key(input: TokenStream) -> TokenStream {
110    specializer::impl_specializer_key(input)
111}