mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
add uniform field attribute
This commit is contained in:
parent
c1bac8869e
commit
4a12d16307
7 changed files with 80 additions and 7 deletions
|
@ -13,5 +13,6 @@ proc-macro = true
|
|||
syn = "1.0"
|
||||
quote = "1.0"
|
||||
Inflector = { version = "0.11.4", default-features = false }
|
||||
darling = "0.10.2"
|
||||
|
||||
[dev-dependencies]
|
|
@ -1,9 +1,10 @@
|
|||
extern crate proc_macro;
|
||||
|
||||
use darling::FromMeta;
|
||||
use inflector::Inflector;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
|
||||
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields};
|
||||
|
||||
#[proc_macro_derive(EntityArchetype)]
|
||||
pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
||||
|
@ -29,10 +30,19 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
})
|
||||
}
|
||||
#[derive(FromMeta, Debug, Default)]
|
||||
struct UniformAttributeArgs {
|
||||
#[darling(default)]
|
||||
pub ignore: Option<bool>,
|
||||
#[darling(default)]
|
||||
pub shader_def: Option<String>,
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Uniforms)]
|
||||
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
||||
pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
||||
const UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let fields = match &ast.data {
|
||||
Data::Struct(DataStruct {
|
||||
fields: Fields::Named(fields),
|
||||
|
@ -41,19 +51,67 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
_ => panic!("expected a struct with named fields"),
|
||||
};
|
||||
|
||||
let uniform_fields = fields
|
||||
.iter()
|
||||
.map(|f| {
|
||||
(
|
||||
f,
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| {
|
||||
a.path.get_ident().as_ref().unwrap().to_string() == UNIFORM_ATTRIBUTE_NAME
|
||||
})
|
||||
.map(|a| {
|
||||
UniformAttributeArgs::from_meta(&a.parse_meta().unwrap())
|
||||
.unwrap_or_else(|_err| UniformAttributeArgs::default())
|
||||
}),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<(&Field, Option<UniformAttributeArgs>)>>();
|
||||
|
||||
let active_uniform_fields = uniform_fields
|
||||
.iter()
|
||||
.filter(|(_field, attrs)| {
|
||||
attrs.is_none()
|
||||
|| match attrs.as_ref().unwrap().ignore {
|
||||
Some(ignore) => !ignore,
|
||||
None => true,
|
||||
}
|
||||
})
|
||||
.map(|(f, _attr)| *f)
|
||||
.collect::<Vec<&Field>>();
|
||||
|
||||
let shader_defs = uniform_fields
|
||||
.iter()
|
||||
.filter(|(_f, attrs)| match attrs {
|
||||
Some(attrs) => attrs.shader_def.is_some(),
|
||||
None => false,
|
||||
})
|
||||
.map(|(f, attrs)| {
|
||||
// attrs is guaranteed to be set because we checked in filter
|
||||
let shader_def = attrs.as_ref().unwrap().shader_def.as_ref().unwrap();
|
||||
if shader_def.len() == 0 {
|
||||
f.ident.as_ref().unwrap().to_string()
|
||||
} else {
|
||||
shader_def.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
let struct_name = &ast.ident;
|
||||
let struct_name_screaming_snake = struct_name.to_string().to_screaming_snake_case();
|
||||
let info_ident = format_ident!("{}_UNIFORM_INFO", struct_name_screaming_snake);
|
||||
let layout_ident = format_ident!("{}_UNIFORM_LAYOUTS", struct_name_screaming_snake);
|
||||
let layout_arrays = (0..fields.len()).map(|_| quote!(&[]));
|
||||
let uniform_name_uniform_info = fields
|
||||
let layout_arrays = (0..active_uniform_fields.len()).map(|_| quote!(&[]));
|
||||
let uniform_name_uniform_info = active_uniform_fields
|
||||
.iter()
|
||||
.map(|field| format!("{}_{}", struct_name, field.ident.as_ref().unwrap()))
|
||||
.collect::<Vec<String>>();
|
||||
let get_uniform_bytes_field_name = fields.iter().map(|field| &field.ident);
|
||||
let get_uniform_bytes_field_name = active_uniform_fields.iter().map(|field| &field.ident);
|
||||
let get_uniform_bytes_uniform_name = uniform_name_uniform_info.clone();
|
||||
let get_uniform_info_uniform_name = uniform_name_uniform_info.clone();
|
||||
let get_uniform_info_array_refs = (0..fields.len()).map(|i| quote!(&#info_ident[#i]));
|
||||
let get_uniform_info_array_refs =
|
||||
(0..active_uniform_fields.len()).map(|i| quote!(&#info_ident[#i]));
|
||||
|
||||
TokenStream::from(quote! {
|
||||
const #info_ident: &[UniformInfo] = &[
|
||||
|
@ -92,6 +150,12 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_shader_defs(&self) -> Vec<&'static str> {
|
||||
vec![
|
||||
#(#shader_defs,)*
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1377,7 +1377,7 @@ pub struct ComponentResourceSet {
|
|||
|
||||
impl ComponentResourceSet {
|
||||
/// Gets the version of the component slice.
|
||||
pub fn version(&self) -> u64 { unsafe { (*self.version.get()) } }
|
||||
pub fn version(&self) -> u64 { unsafe { *self.version.get() } }
|
||||
|
||||
/// Gets a raw pointer to the start of the component slice.
|
||||
///
|
||||
|
|
|
@ -305,6 +305,7 @@ impl WgpuRenderer {
|
|||
}
|
||||
|
||||
// TODO: remove me
|
||||
#[allow(dead_code)]
|
||||
fn setup_dynamic_entity_shader_uniforms(
|
||||
&mut self,
|
||||
world: &World,
|
||||
|
|
|
@ -41,6 +41,7 @@ pub trait AsUniforms {
|
|||
fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>;
|
||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
||||
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
|
||||
fn get_shader_defs(&self) -> Vec<&'static str>;
|
||||
// TODO: support zero-copy uniforms
|
||||
// fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
|
||||
}
|
||||
|
|
|
@ -40,4 +40,8 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_shader_defs(&self) -> std::vec::Vec<&'static str> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
|
@ -11,4 +11,6 @@ use bevy_derive::Uniforms;
|
|||
#[derive(Uniforms)]
|
||||
pub struct StandardMaterial {
|
||||
pub albedo: Vec4,
|
||||
// #[uniform(ignore,shader_def="Hi")]
|
||||
// pub enable_thing: bool,
|
||||
}
|
Loading…
Reference in a new issue