minimal example auto registration for reflect types

This commit is contained in:
eugineerd 2024-09-02 21:56:25 +00:00
parent d2624765d0
commit 4b48e235bc
6 changed files with 49 additions and 1 deletions

View File

@ -92,8 +92,12 @@ impl Debug for App {
impl Default for App {
fn default() -> Self {
let mut app = App::empty();
app.sub_apps.main.update_schedule = Some(Main.intern());
#[cfg(feature = "bevy_reflect")]
bevy_reflect::wasm_init::wasm_init();
#[cfg(feature = "bevy_reflect")]
app.init_resource::<AppTypeRegistry>();

View File

@ -39,6 +39,8 @@ glam = { version = "0.28", features = ["serde"], optional = true }
petgraph = { version = "0.6", features = ["serde-1"], optional = true }
smol_str = { version = "0.2.0", optional = true }
uuid = { version = "1.0", optional = true, features = ["v4", "serde"] }
inventory = "0.3"
wasm-init = "0.2"
[dev-dependencies]
ron = "0.8.0"

View File

@ -60,6 +60,22 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
.generics()
.split_for_impl();
let auto_reflect = if ty_generics.clone().into_token_stream().is_empty() {
quote! {
#[cfg(target_arch = "wasm32")]
#bevy_reflect_path::wasm_init::wasm_init!{
#bevy_reflect_path::AUTOMATIC_REFLECT_TYPES
.write()
.unwrap()
.push(|reg: &mut #bevy_reflect_path::TypeRegistry| reg.register::<#struct_path>());
}
#[cfg(not(target_arch = "wasm32"))]
#bevy_reflect_path::inventory::submit!(#bevy_reflect_path::AUTOMATIC_REFLECT_TYPES(|reg: &mut #bevy_reflect_path::TypeRegistry| reg.register::<#struct_path>()));
}
} else {
quote! {}
};
let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
quote! {
@ -73,6 +89,8 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
#function_impls
#auto_reflect
impl #impl_generics #bevy_reflect_path::Struct for #struct_path #ty_generics #where_reflect_clause {
fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
match name {

View File

@ -597,6 +597,9 @@ pub use type_registry::*;
pub use bevy_reflect_derive::*;
pub use erased_serde;
pub extern crate inventory;
pub extern crate wasm_init;
extern crate alloc;
/// Exports used by the reflection macros.

View File

@ -9,6 +9,13 @@ use std::{
sync::{Arc, PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
#[cfg(target_arch = "wasm32")]
pub static AUTOMATIC_REFLECT_TYPES: RwLock<Vec<fn(&mut TypeRegistry)>> = RwLock::new(Vec::new());
#[cfg(not(target_arch = "wasm32"))]
pub struct AUTOMATIC_REFLECT_TYPES(pub fn(&mut TypeRegistry));
#[cfg(not(target_arch = "wasm32"))]
inventory::collect!(AUTOMATIC_REFLECT_TYPES);
/// A registry of [reflected] types.
///
/// This struct is used as the central store for type information.
@ -108,6 +115,14 @@ impl TypeRegistry {
registry.register::<f32>();
registry.register::<f64>();
registry.register::<String>();
#[cfg(target_arch = "wasm32")]
for f in AUTOMATIC_REFLECT_TYPES.read().unwrap().iter() {
f(&mut registry)
}
#[cfg(not(target_arch = "wasm32"))]
for f in inventory::iter::<AUTOMATIC_REFLECT_TYPES> {
f.0(&mut registry)
}
registry
}

View File

@ -4,6 +4,8 @@
//! by their string name. Reflection is a core part of Bevy and enables a number of interesting
//! features (like scenes).
use std::any::Any;
use bevy::{
prelude::*,
reflect::{
@ -17,7 +19,7 @@ fn main() {
App::new()
.add_plugins(DefaultPlugins)
// Bar will be automatically registered as it's a dependency of Foo
.register_type::<Foo>()
// .register_type::<Foo>()
.add_systems(Startup, setup)
.run();
}
@ -101,6 +103,8 @@ fn setup(type_registry: Res<AppTypeRegistry>) {
let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
assert!(type_registry.contains(value.type_id()));
// Deserializing returns a `Box<dyn PartialReflect>` value.
// Generally, deserializing a value will return the "dynamic" variant of a type.
// For example, deserializing a struct will return the DynamicStruct type.
@ -118,4 +122,6 @@ fn setup(type_registry: Res<AppTypeRegistry>) {
// By "patching" `Foo` with the deserialized DynamicStruct, we can "Deserialize" Foo.
// This means we can serialize and deserialize with a single `Reflect` derive!
value.apply(&*reflect_value);
info!("{}", type_registry.iter().collect::<Vec<_>>().len());
}