reflect: Implement reflect for glam types
This commit is contained in:
parent
eb44aba3dc
commit
544aee4a31
|
@ -5,6 +5,10 @@ edition = "2021"
|
|||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
math = ["dep:glam"]
|
||||
|
||||
[dependencies]
|
||||
lyra-reflect-derive = { path = "lyra-reflect-derive" }
|
||||
lyra-ecs = { path = "../lyra-ecs" }
|
||||
lyra-ecs = { path = "../lyra-ecs" }
|
||||
glam = { version = "0.24.0", optional = true }
|
|
@ -11,6 +11,52 @@ mod struct_derive;
|
|||
#[allow(unused_imports)]
|
||||
use struct_derive::*;
|
||||
|
||||
mod struct_macro;
|
||||
|
||||
/* #[proc_macro_attribute(attributes(reflect))]
|
||||
pub fn reflect(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
item
|
||||
} */
|
||||
|
||||
pub(crate) struct FieldAttributes(Vec<ReflectAttribute>);
|
||||
|
||||
impl FieldAttributes {
|
||||
/// Searches for a usage of the 'reflect' attribute and returns a list of the
|
||||
/// things used in the usage.
|
||||
pub fn from_vec(v: &Vec<syn::Attribute>) -> Result<Self, syn::Error> {
|
||||
let s: Result<Vec<ReflectAttribute>, _> = v.iter().filter_map(|att| match &att.meta {
|
||||
syn::Meta::Path(_) => None,
|
||||
syn::Meta::List(l) => {
|
||||
Some(syn::parse::<ReflectAttribute>(l.tokens.clone().into()))
|
||||
}
|
||||
syn::Meta::NameValue(_) => None
|
||||
}).collect();
|
||||
|
||||
Ok(Self(s?))
|
||||
}
|
||||
|
||||
pub fn has_skip(&self) -> bool {
|
||||
self.0.iter().any(|a| *a == ReflectAttribute::Skip)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum ReflectAttribute {
|
||||
Skip
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for ReflectAttribute {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let ident: Ident = input.parse()?;
|
||||
let ident_str = ident.to_string().to_lowercase();
|
||||
|
||||
match ident_str.as_str() {
|
||||
"skip" => Ok(Self::Skip),
|
||||
_ => Err(syn::Error::new(ident.span(), "Unknown reflect attribute flag"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) struct ReflectDef {
|
||||
//pub ident: Ident,
|
||||
|
@ -36,7 +82,7 @@ impl syn::parse::Parse for ReflectDef {
|
|||
}
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Reflect)]
|
||||
#[proc_macro_derive(Reflect, attributes(reflect))]
|
||||
pub fn derive_reflect(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
|
@ -127,4 +173,9 @@ pub(crate) fn add_trait_bounds(mut generics: Generics, add_bounds: Vec<TypeParam
|
|||
}
|
||||
}
|
||||
generics
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn impl_reflect_simple_struct(input: TokenStream) -> TokenStream {
|
||||
struct_macro::impl_reflect_simple_struct(input)
|
||||
}
|
|
@ -1,7 +1,28 @@
|
|||
use quote::{quote, ToTokens};
|
||||
use syn::{DeriveInput, parse_quote, DataStruct};
|
||||
|
||||
use crate::add_trait_bounds;
|
||||
use crate::{add_trait_bounds, FieldAttributes};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum StructType {
|
||||
Unit,
|
||||
Named,
|
||||
Tuple,
|
||||
}
|
||||
|
||||
impl StructType {
|
||||
pub fn new(data: &DataStruct) -> Self {
|
||||
if let Some(first) = data.fields.iter().next() {
|
||||
if first.ident.is_some() {
|
||||
Self::Named
|
||||
} else {
|
||||
Self::Tuple
|
||||
}
|
||||
} else {
|
||||
Self::Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates code that matches a string with a struct's field name, and returns an Option that
|
||||
/// contains a borrow (mutable borrow if `is_mut` is true) to the matching struct field.
|
||||
|
@ -22,28 +43,42 @@ use crate::add_trait_bounds;
|
|||
/// _ => None,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If the struct is a unit or tuple struct, None will always be returned
|
||||
fn gen_struct_field_match(data: &DataStruct, is_mut: bool) -> proc_macro2::TokenStream {
|
||||
let mut_tkn = if is_mut {
|
||||
quote! {
|
||||
mut
|
||||
}
|
||||
} else { quote!{} };
|
||||
|
||||
let field_arms = data.fields.iter().map(|field| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
|
||||
quote! {
|
||||
#field_name_str => Some(&#mut_tkn self.#field_ident)
|
||||
}
|
||||
});
|
||||
let ty = StructType::new(data);
|
||||
|
||||
quote! {
|
||||
match name {
|
||||
#(#field_arms,)*
|
||||
_ => None,
|
||||
if ty == StructType::Named {
|
||||
let mut_tkn = if is_mut {
|
||||
quote! {
|
||||
mut
|
||||
}
|
||||
} else { quote!{} };
|
||||
|
||||
let field_arms = data.fields.iter().map(|field| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
|
||||
let attrs = FieldAttributes::from_vec(&field.attrs)
|
||||
.expect("Failure to parse reflect attributes");
|
||||
if attrs.has_skip() {
|
||||
quote! {
|
||||
#field_name_str => None
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#field_name_str => Some(&#mut_tkn self.#field_ident)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match name {
|
||||
#(#field_arms,)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { quote!(None) }
|
||||
}
|
||||
|
||||
/// Generates code that matches a string with a struct's field name, and sets that field value
|
||||
|
@ -64,27 +99,41 @@ fn gen_struct_field_match(data: &DataStruct, is_mut: bool) -> proc_macro2::Token
|
|||
/// }
|
||||
/// ```
|
||||
fn gen_struct_set_field_match(data: &DataStruct) -> proc_macro2::TokenStream {
|
||||
let field_arms = data.fields.iter().map(|field| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
let field_ty = &field.ty;
|
||||
|
||||
quote! {
|
||||
#field_name_str => self.#field_ident = any_val.downcast_ref::<#field_ty>()
|
||||
.expect(&format!("Cannot set struct's field of {} type to the provided type of {}", #field_name_str, val.name()))
|
||||
.clone() //Some(&#mut_tkn self.#field_ident)
|
||||
}
|
||||
});
|
||||
let ty = StructType::new(data);
|
||||
|
||||
quote! {
|
||||
let any_val = val.as_any();
|
||||
match name {
|
||||
#(#field_arms,)*
|
||||
_ => {
|
||||
return false;
|
||||
},
|
||||
if ty == StructType::Named {
|
||||
let field_arms = data.fields.iter().map(|field| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
let field_ty = &field.ty;
|
||||
|
||||
let attrs = FieldAttributes::from_vec(&field.attrs)
|
||||
.expect("Failure to parse reflect attributes");
|
||||
if attrs.has_skip() {
|
||||
quote! {
|
||||
#field_name_str => {}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#field_name_str => self.#field_ident = any_val.downcast_ref::<#field_ty>()
|
||||
.expect(&format!("Cannot set struct's field of {} type to the provided type of {}", #field_name_str, val.name()))
|
||||
.clone() //Some(&#mut_tkn self.#field_ident)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
let any_val = val.as_any();
|
||||
match name {
|
||||
#(#field_arms,)*
|
||||
_ => {
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
} else { quote!(return false;) }
|
||||
}
|
||||
|
||||
/// Generates code that matches a string with a struct's field name, and returns a string that is
|
||||
|
@ -99,25 +148,29 @@ fn gen_struct_set_field_match(data: &DataStruct) -> proc_macro2::TokenStream {
|
|||
/// }
|
||||
/// ```
|
||||
fn gen_struct_field_name_match(data: &DataStruct) -> proc_macro2::TokenStream {
|
||||
let field_arms = data.fields.iter().map(|field| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
let ty = StructType::new(data);
|
||||
|
||||
if ty == StructType::Named {
|
||||
let field_arms = data.fields.iter().map(|field| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
|
||||
let mut field_ty_stream = proc_macro2::TokenStream::new();
|
||||
field.ty.to_tokens(&mut field_ty_stream);
|
||||
let s = field_ty_stream.to_string();
|
||||
|
||||
quote! {
|
||||
#field_name_str => Some(#s)
|
||||
}
|
||||
});
|
||||
|
||||
let mut field_ty_stream = proc_macro2::TokenStream::new();
|
||||
field.ty.to_tokens(&mut field_ty_stream);
|
||||
let s = field_ty_stream.to_string();
|
||||
|
||||
quote! {
|
||||
#field_name_str => Some(#s)
|
||||
match name {
|
||||
#(#field_arms,)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match name {
|
||||
#(#field_arms,)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
} else { quote!(None) }
|
||||
}
|
||||
|
||||
/// Generates code that matches a string with a struct's field name, and sets that field value
|
||||
|
@ -138,15 +191,38 @@ fn gen_struct_field_name_match(data: &DataStruct) -> proc_macro2::TokenStream {
|
|||
/// }
|
||||
/// ```
|
||||
fn gen_struct_set_field_match_idx(data: &DataStruct) -> proc_macro2::TokenStream {
|
||||
let ty = StructType::new(data);
|
||||
|
||||
if ty == StructType::Unit {
|
||||
return quote!( return false; );
|
||||
}
|
||||
|
||||
let field_arms = data.fields.iter().enumerate().map(|(idx, field)| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
let field_ty = &field.ty;
|
||||
|
||||
quote! {
|
||||
#idx => self.#field_ident = any_val.downcast_ref::<#field_ty>()
|
||||
.expect(&format!("Cannot set struct's field of {} type to the provided type of {}", #field_name_str, val.name()))
|
||||
.clone()
|
||||
|
||||
let attrs = FieldAttributes::from_vec(&field.attrs)
|
||||
.expect("Failure to parse reflect attributes");
|
||||
if attrs.has_skip() {
|
||||
return quote! {
|
||||
#idx => {}
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(field_ident) = &field.ident {
|
||||
let field_name_str = field_ident.to_string();
|
||||
|
||||
quote! {
|
||||
#idx => self.#field_ident = any_val.downcast_ref::<#field_ty>()
|
||||
.expect(&format!("Cannot set struct's field of {} to the provided type of {}", #field_name_str, val.name()))
|
||||
.clone()
|
||||
}
|
||||
} else {
|
||||
let sidx = syn::Index::from(idx);
|
||||
quote! {
|
||||
#idx => self.#sidx = any_val.downcast_ref::<#field_ty>()
|
||||
.expect(&format!("Cannot set struct's field at {} to the provided type of {}", #idx, val.name()))
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -158,6 +234,8 @@ fn gen_struct_set_field_match_idx(data: &DataStruct) -> proc_macro2::TokenStream
|
|||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,6 +290,12 @@ fn gen_struct_field_name_match_idx(data: &DataStruct) -> proc_macro2::TokenStrea
|
|||
/// }
|
||||
/// ```
|
||||
fn gen_struct_field_match_idx(data: &DataStruct, is_mut: bool) -> proc_macro2::TokenStream {
|
||||
let ty = StructType::new(data);
|
||||
|
||||
if ty == StructType::Unit {
|
||||
return quote!(None);
|
||||
}
|
||||
|
||||
let mut_tkn = if is_mut {
|
||||
quote! {
|
||||
mut
|
||||
|
@ -219,10 +303,23 @@ fn gen_struct_field_match_idx(data: &DataStruct, is_mut: bool) -> proc_macro2::T
|
|||
} else { quote!{} };
|
||||
|
||||
let field_arms = data.fields.iter().enumerate().map(|(idx, field)| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let attrs = FieldAttributes::from_vec(&field.attrs)
|
||||
.expect("Failure to parse reflect attributes");
|
||||
if attrs.has_skip() {
|
||||
return quote! {
|
||||
#idx => None
|
||||
};
|
||||
}
|
||||
|
||||
quote! {
|
||||
#idx => Some(&#mut_tkn self.#field_ident)
|
||||
if let Some(field_ident) = &field.ident {
|
||||
quote! {
|
||||
#idx => Some(&#mut_tkn self.#field_ident)
|
||||
}
|
||||
} else {
|
||||
let sidx = syn::Index::from(idx);
|
||||
quote! {
|
||||
#idx => Some(&#mut_tkn self.#sidx)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -246,20 +343,26 @@ fn gen_struct_field_match_idx(data: &DataStruct, is_mut: bool) -> proc_macro2::T
|
|||
/// }
|
||||
/// ```
|
||||
fn gen_struct_field_name_idx(data: &DataStruct) -> proc_macro2::TokenStream {
|
||||
let field_arms = data.fields.iter().enumerate().map(|(idx, field)| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
|
||||
quote! {
|
||||
#idx => Some(#field_name_str)
|
||||
}
|
||||
});
|
||||
let ty = StructType::new(data);
|
||||
|
||||
quote! {
|
||||
match idx {
|
||||
#(#field_arms,)*
|
||||
_ => None,
|
||||
if ty == StructType::Named {
|
||||
let field_arms = data.fields.iter().enumerate().map(|(idx, field)| {
|
||||
let field_ident = field.ident.as_ref().expect("Struct is missing field ident!");
|
||||
let field_name_str = field_ident.to_string();
|
||||
|
||||
quote! {
|
||||
#idx => Some(#field_name_str)
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match idx {
|
||||
#(#field_arms,)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote!(None)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,12 +464,10 @@ pub fn derive_reflect_struct(input: &DeriveInput, data_struct: &DataStruct) -> p
|
|||
|
||||
fn set_field(&mut self, name: &str, val: &dyn lyra_engine::reflect::Reflect) -> bool {
|
||||
#set_field_named
|
||||
true
|
||||
}
|
||||
|
||||
fn set_field_at(&mut self, idx: usize, val: &dyn lyra_engine::reflect::Reflect) -> bool {
|
||||
#set_field_idx
|
||||
true
|
||||
}
|
||||
|
||||
fn field_type(&self, name: &str) -> Option<&'static str> {
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
use quote::quote;
|
||||
use syn::{Token, parenthesized, punctuated::Punctuated};
|
||||
|
||||
struct Field {
|
||||
name: syn::Ident,
|
||||
_eq: Token![=],
|
||||
ty: syn::Ident,
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for Field {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
Ok(Self {
|
||||
name: input.parse()?,
|
||||
_eq: input.parse()?,
|
||||
ty: input.parse()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct SimpleStruct {
|
||||
type_path: syn::Path,
|
||||
pub generics: syn::Generics,
|
||||
fields: Vec<Field>,
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for SimpleStruct {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
//let type_path = syn::Path::parse_mod_style(input)?;
|
||||
let type_path: syn::Path = input.parse()?;
|
||||
/* let mut generics = input.parse::<syn::Generics>()?;
|
||||
generics.where_clause = input.parse()?; */
|
||||
|
||||
let mut fields = vec![];
|
||||
|
||||
// parse fields if a comma is found
|
||||
if input.peek(Token![,]) {
|
||||
let _: Token![,] = input.parse()?;
|
||||
let ident: syn::Ident = input.parse()?;
|
||||
let ident_str = ident.to_string();
|
||||
|
||||
match ident_str.as_str() {
|
||||
"fields" => {
|
||||
let content;
|
||||
let _parens: syn::token::Paren = parenthesized!(content in input);
|
||||
|
||||
let f: Punctuated<Field, Token![,]> = content.parse_terminated(Field::parse, Token![,])?;
|
||||
fields = f.into_iter().collect();
|
||||
},
|
||||
_ => return Err(syn::Error::new(ident.span(), "Unknown macro command, expected `fields`")),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
type_path,
|
||||
generics: syn::Generics::default(),
|
||||
fields,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn gen_match_field_name_arm(simple: &SimpleStruct, default: &proc_macro2::TokenStream, arm_gen: fn(field: &Field) -> proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||
let field_arms_iter = simple.fields.iter().map(|f| {
|
||||
let fname = &f.name;
|
||||
let arm = arm_gen(f);
|
||||
|
||||
quote! {
|
||||
stringify!(#fname) => #arm
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match name {
|
||||
#(#field_arms_iter,)*
|
||||
_ => #default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_match_field_index_arm(simple: &SimpleStruct, default: &proc_macro2::TokenStream, arm_gen: fn(field: &Field) -> proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||
let field_arms_iter = simple.fields.iter().enumerate().map(|(idx, f)| {
|
||||
let arm = arm_gen(f);
|
||||
|
||||
quote! {
|
||||
#idx => #arm
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
match idx {
|
||||
#(#field_arms_iter,)*
|
||||
_ => #default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn impl_reflect_simple_struct(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let simple = syn::parse_macro_input!(input as SimpleStruct);
|
||||
|
||||
let type_path = &simple.type_path;
|
||||
let (impl_generics, ty_generics, where_clause) = simple.generics.split_for_impl();
|
||||
// convert the type path to a string. This would not create a leading separator
|
||||
/* let type_path_str = {
|
||||
let idents: Vec<String> = type_path.segments.iter()
|
||||
.map(|segment| segment.ident.to_string())
|
||||
.collect();
|
||||
idents.join("::")
|
||||
}; */
|
||||
|
||||
let borrow_fn = |field: &Field| {
|
||||
let name = &field.name;
|
||||
quote! {
|
||||
Some(&self.#name)
|
||||
}
|
||||
};
|
||||
|
||||
let borrow_mut_fn = |field: &Field| {
|
||||
let name = &field.name;
|
||||
quote! {
|
||||
Some(&mut self.#name)
|
||||
}
|
||||
};
|
||||
|
||||
let none_default = quote!(None);
|
||||
let false_return_default = quote!( { return false; });
|
||||
|
||||
let field_count = simple.fields.len();
|
||||
|
||||
let field_fn = gen_match_field_name_arm(&simple, &none_default, borrow_fn);
|
||||
let field_mut_fn = gen_match_field_name_arm(&simple, &none_default, borrow_mut_fn);
|
||||
let field_at_fn = gen_match_field_index_arm(&simple, &none_default, borrow_fn);
|
||||
let field_at_mut_fn = gen_match_field_index_arm(&simple, &none_default, borrow_mut_fn);
|
||||
let field_name_at_fn = gen_match_field_index_arm(&simple, &none_default, |f| {
|
||||
let name = &f.name;
|
||||
quote! {
|
||||
Some(stringify!(#name))
|
||||
}
|
||||
});
|
||||
|
||||
let set_field_arm = |f: &Field| {
|
||||
let name = &f.name;
|
||||
let ty = &f.ty;
|
||||
quote! {
|
||||
self.#name = any_val.downcast_ref::<#ty>()
|
||||
.expect(&format!("Cannot set struct's field of {} type to the provided type of {}", stringify!(#name), val.name()))
|
||||
.clone() //Some(&#mut_tkn self.#field_ident)
|
||||
}
|
||||
};
|
||||
|
||||
let set_field_fn = gen_match_field_name_arm(&simple, &false_return_default, set_field_arm);
|
||||
let set_field_at_fn = gen_match_field_index_arm(&simple, &false_return_default, set_field_arm);
|
||||
|
||||
let get_field_ty_arm = |f: &Field| {
|
||||
let fty = &f.ty;
|
||||
quote! {
|
||||
Some(stringify!(#fty))
|
||||
}
|
||||
};
|
||||
let field_type_fn = gen_match_field_name_arm(&simple, &none_default, get_field_ty_arm);
|
||||
let field_type_at_fn = gen_match_field_index_arm(&simple, &none_default, get_field_ty_arm);
|
||||
|
||||
proc_macro::TokenStream::from(quote! {
|
||||
impl #impl_generics lyra_engine::reflect::Reflect for #type_path #ty_generics #where_clause {
|
||||
fn name(&self) -> ::std::string::String {
|
||||
stringify!(#type_path).to_string()
|
||||
}
|
||||
|
||||
fn type_id(&self) -> std::any::TypeId {
|
||||
std::any::TypeId::of::<#type_path #ty_generics>()
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn apply(&mut self, val: &dyn lyra_engine::reflect::Reflect) {
|
||||
let val = val.as_any().downcast_ref::<Self>()
|
||||
.expect("The type of `val` is not the same as `self`");
|
||||
*self = val.clone();
|
||||
}
|
||||
|
||||
fn clone_inner(&self) -> Box<dyn lyra_engine::reflect::Reflect> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn reflect_ref(&self) -> lyra_engine::reflect::ReflectRef {
|
||||
lyra_engine::reflect::ReflectRef::Value(self)
|
||||
}
|
||||
|
||||
fn reflect_mut(&mut self) -> lyra_engine::reflect::ReflectMut {
|
||||
lyra_engine::reflect::ReflectMut::Value(self)
|
||||
}
|
||||
|
||||
fn reflect_val(&self) -> &dyn lyra_engine::reflect::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn reflect_val_mut(&mut self) -> &mut dyn lyra_engine::reflect::Reflect {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics lyra_engine::reflect::Struct for #type_path #ty_generics #where_clause {
|
||||
fn field(&self, name: &str) -> Option<&dyn Reflect> {
|
||||
#field_fn
|
||||
}
|
||||
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
|
||||
#field_mut_fn
|
||||
}
|
||||
|
||||
fn fields_len(&self) -> usize {
|
||||
#field_count
|
||||
}
|
||||
|
||||
fn field_at(&self, idx: usize) -> Option<&dyn Reflect> {
|
||||
#field_at_fn
|
||||
}
|
||||
|
||||
fn field_at_mut(&mut self, idx: usize) -> Option<&mut dyn Reflect> {
|
||||
#field_at_mut_fn
|
||||
}
|
||||
|
||||
fn field_name_at(&self, idx: usize) -> Option<&str> {
|
||||
#field_name_at_fn
|
||||
}
|
||||
|
||||
fn set_field(&mut self, name: &str, val: &dyn Reflect) -> bool {
|
||||
let any_val = val.as_any();
|
||||
|
||||
#set_field_fn
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn set_field_at(&mut self, idx: usize, val: &dyn Reflect) -> bool {
|
||||
let any_val = val.as_any();
|
||||
|
||||
#set_field_at_fn
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn field_type(&self, name: &str) -> Option<&'static str> {
|
||||
#field_type_fn
|
||||
}
|
||||
|
||||
fn field_type_at(&self, idx: usize) -> Option<&'static str> {
|
||||
#field_type_at_fn
|
||||
}
|
||||
|
||||
fn method(&self, name: &str) -> Option<&Method> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn method_at(&self, idx: usize) -> Option<&Method> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn methods_len(&self) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
use lyra_reflect_derive::{impl_reflect_simple_struct, impl_reflect_trait_value};
|
||||
|
||||
use crate::{lyra_engine, Reflect, Method};
|
||||
|
||||
impl_reflect_simple_struct!(glam::Vec2, fields(x=f32, y=f32));
|
||||
impl_reflect_simple_struct!(glam::Vec3, fields(x=f32, y=f32, z=f32));
|
||||
impl_reflect_simple_struct!(glam::Vec4, fields(x=f32, y=f32, z=f32, w=f32));
|
||||
impl_reflect_simple_struct!(glam::Quat, fields(x=f32, y=f32, z=f32, w=f32));
|
||||
|
||||
impl_reflect_trait_value!(glam::Mat4);
|
|
@ -4,7 +4,7 @@ use crate::List;
|
|||
|
||||
use crate::lyra_engine;
|
||||
|
||||
use super::{Reflect, ReflectRef, ReflectMut, util};
|
||||
use crate::{Reflect, ReflectRef, ReflectMut, util};
|
||||
|
||||
impl_reflect_trait_value!(bool);
|
||||
impl_reflect_trait_value!(char);
|
|
@ -0,0 +1,4 @@
|
|||
pub mod impl_std;
|
||||
|
||||
#[cfg(feature="math")]
|
||||
pub mod impl_math;
|
|
@ -6,6 +6,8 @@ use lyra_ecs::{world::World, DynamicBundle, Component, Entity, ComponentInfo};
|
|||
|
||||
extern crate self as lyra_reflect;
|
||||
|
||||
pub use lyra_reflect_derive::*;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) mod lyra_engine {
|
||||
pub(crate) mod reflect {
|
||||
|
@ -42,7 +44,7 @@ pub use method::*;
|
|||
pub mod registry;
|
||||
pub use registry::*;
|
||||
|
||||
pub mod impl_std;
|
||||
pub mod impls;
|
||||
|
||||
pub trait Reflect: Any {
|
||||
fn name(&self) -> String;
|
||||
|
|
|
@ -52,7 +52,6 @@ pub trait Enum: Reflect {
|
|||
#[allow(unused_variables)]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use lyra_reflect_derive::Reflect;
|
||||
|
||||
use super::EnumType;
|
||||
use crate::{lyra_engine, Reflect, ReflectRef};
|
||||
|
|
|
@ -41,7 +41,6 @@ pub trait Struct: Reflect {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use lyra_reflect_derive::Reflect;
|
||||
use crate::{Reflect, ReflectRef, ReflectMut};
|
||||
use crate::lyra_engine;
|
||||
|
||||
|
|
|
@ -21,6 +21,12 @@ impl TypeRegistry {
|
|||
self.inner.get_mut(&type_id)
|
||||
}
|
||||
|
||||
/// Get a registered type, or register a new type and return it.
|
||||
pub fn get_type_or_default(&mut self, type_id: TypeId) -> &mut RegisteredType {
|
||||
self.inner.entry(type_id)
|
||||
.or_insert(RegisteredType::default())
|
||||
}
|
||||
|
||||
pub fn register_type<T>(&mut self)
|
||||
where
|
||||
T: AsRegisteredType + 'static
|
||||
|
|
Loading…
Reference in New Issue