bevy_render_macros/
lib.rs

1// FIXME(3492): remove once docs are ready
2#![allow(missing_docs)]
3#![cfg_attr(docsrs, feature(doc_auto_cfg))]
4
5mod as_bind_group;
6mod extract_component;
7mod extract_resource;
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::default()
16        .maybe_get_path("bevy_render")
17        // NOTE: If the derivation is within bevy_render, then we need to return 'crate'
18        .unwrap_or_else(|| BevyManifest::parse_str("crate"))
19}
20
21#[proc_macro_derive(ExtractResource)]
22pub fn derive_extract_resource(input: TokenStream) -> TokenStream {
23    extract_resource::derive_extract_resource(input)
24}
25
26/// Implements `ExtractComponent` trait for a component.
27/// The component must implement [`Clone`].
28/// The component will be extracted into the render world via cloning.
29/// Note that this only enables extraction of the component, it does not execute the extraction.
30/// See `ExtractComponentPlugin` to actually perform the extraction.
31///
32/// If you only want to extract a component conditionally, you may use the `extract_component_filter` attribute.
33///
34/// # Example
35///
36/// ```no_compile
37/// use bevy_ecs::component::Component;
38/// use bevy_render_macros::ExtractComponent;
39///
40/// #[derive(Component, Clone, ExtractComponent)]
41/// #[extract_component_filter(With<Camera>)]
42/// pub struct Foo {
43///     pub should_foo: bool,
44/// }
45///
46/// // Without a filter (unconditional).
47/// #[derive(Component, Clone, ExtractComponent)]
48/// pub struct Bar {
49///     pub should_bar: bool,
50/// }
51/// ```
52#[proc_macro_derive(ExtractComponent, attributes(extract_component_filter))]
53pub fn derive_extract_component(input: TokenStream) -> TokenStream {
54    extract_component::derive_extract_component(input)
55}
56
57#[proc_macro_derive(
58    AsBindGroup,
59    attributes(uniform, storage_texture, texture, sampler, bind_group_data, storage)
60)]
61pub fn derive_as_bind_group(input: TokenStream) -> TokenStream {
62    let input = parse_macro_input!(input as DeriveInput);
63
64    as_bind_group::derive_as_bind_group(input).unwrap_or_else(|err| err.to_compile_error().into())
65}
66
67/// Derive macro generating an impl of the trait `RenderLabel`.
68///
69/// This does not work for unions.
70#[proc_macro_derive(RenderLabel)]
71pub fn derive_render_label(input: TokenStream) -> TokenStream {
72    let input = parse_macro_input!(input as DeriveInput);
73    let mut trait_path = bevy_render_path();
74    trait_path
75        .segments
76        .push(format_ident!("render_graph").into());
77    let mut dyn_eq_path = trait_path.clone();
78    trait_path
79        .segments
80        .push(format_ident!("RenderLabel").into());
81    dyn_eq_path.segments.push(format_ident!("DynEq").into());
82    derive_label(input, "RenderLabel", &trait_path, &dyn_eq_path)
83}
84
85/// Derive macro generating an impl of the trait `RenderSubGraph`.
86///
87/// This does not work for unions.
88#[proc_macro_derive(RenderSubGraph)]
89pub fn derive_render_sub_graph(input: TokenStream) -> TokenStream {
90    let input = parse_macro_input!(input as DeriveInput);
91    let mut trait_path = bevy_render_path();
92    trait_path
93        .segments
94        .push(format_ident!("render_graph").into());
95    let mut dyn_eq_path = trait_path.clone();
96    trait_path
97        .segments
98        .push(format_ident!("RenderSubGraph").into());
99    dyn_eq_path.segments.push(format_ident!("DynEq").into());
100    derive_label(input, "RenderSubGraph", &trait_path, &dyn_eq_path)
101}