diff --git a/Cargo.toml b/Cargo.toml index c4436bb370..edaba72b0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,10 @@ edition = "2018" [features] default = ["headless", "wgpu", "winit"] -headless = ["asset", "component_registry", "core", "derive", "diagnostic", "gltf", "input", "pbr", "property", "render", "scene", "text", "transform", "ui", "window"] +headless = ["asset", "type_registry", "core", "derive", "diagnostic", "gltf", "input", "pbr", "property", "render", "scene", "text", "transform", "ui", "window"] asset = ["bevy_asset"] core = ["bevy_core"] -component_registry = ["bevy_component_registry"] +type_registry = ["bevy_type_registry"] derive = ["bevy_derive"] diagnostic = ["bevy_diagnostic"] gltf = ["bevy_gltf"] @@ -36,7 +36,7 @@ members = [ # bevy bevy_app = { path = "crates/bevy_app" } bevy_asset = { path = "crates/bevy_asset", optional = true } -bevy_component_registry = { path = "crates/bevy_component_registry", optional = true } +bevy_type_registry = { path = "crates/bevy_type_registry", optional = true } bevy_core = { path = "crates/bevy_core", optional = true } bevy_derive = { path = "crates/bevy_derive", optional = true } bevy_diagnostic = { path = "crates/bevy_diagnostic", optional = true } diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index bc7cbc7287..5ee5efda57 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -11,7 +11,7 @@ filesystem_watcher = ["notify"] [dependencies] bevy_app = { path = "../bevy_app" } bevy_core = { path = "../bevy_core" } -bevy_component_registry = { path = "../bevy_component_registry" } +bevy_type_registry = { path = "../bevy_type_registry" } bevy_property = { path = "../bevy_property" } legion = { path = "../bevy_legion" } diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 729ac0188d..41512f548b 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -3,7 +3,7 @@ use crate::{ Handle, HandleId, }; use bevy_app::{AppBuilder, Events, FromResources}; -use bevy_component_registry::RegisterComponent; +use bevy_type_registry::RegisterType; use bevy_core::bytes::GetBytes; use legion::prelude::*; use std::{ diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 4d6b440f2a..1438973d60 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -13,7 +13,7 @@ pub use load_request::*; pub use loader::*; use bevy_app::{AppBuilder, AppPlugin}; -use bevy_component_registry::RegisterComponent; +use bevy_type_registry::RegisterType; use legion::prelude::IntoSystem; pub mod stage { diff --git a/crates/bevy_component_registry/src/component_registry.rs b/crates/bevy_component_registry/src/component_registry.rs deleted file mode 100644 index d28ed1fc7c..0000000000 --- a/crates/bevy_component_registry/src/component_registry.rs +++ /dev/null @@ -1,85 +0,0 @@ -use bevy_property::{Properties, Property, PropertyTypeRegistry}; -use legion::{ - prelude::{Entity, World, Resources}, - storage::{Component, ComponentResourceSet, ComponentTypeId}, -}; -use std::{ - collections::HashMap, - sync::{Arc, RwLock}, -}; -use bevy_app::FromResources; - -#[derive(Clone, Default)] -pub struct PropertyTypeRegistryContext { - pub value: Arc>, -} - -#[derive(Default)] -pub struct ComponentRegistryContext { - pub value: Arc>, -} - -#[derive(Default)] -pub struct ComponentRegistry { - pub registrations: HashMap, - pub short_names: HashMap, - pub full_names: HashMap, -} - -impl ComponentRegistry { - pub fn register(&mut self) - where - T: Properties + Component + FromResources, - { - let registration = ComponentRegistration::of::(); - self.short_names - .insert(registration.short_name.to_string(), registration.ty); - self.full_names - .insert(registration.ty.0.to_string(), registration.ty); - self.registrations.insert(registration.ty, registration); - } - - pub fn get(&self, type_id: &ComponentTypeId) -> Option<&ComponentRegistration> { - self.registrations.get(type_id) - } - - pub fn get_with_full_name(&self, full_name: &str) -> Option<&ComponentRegistration> { - self.full_names - .get(full_name) - .and_then(|id| self.registrations.get(id)) - } - - pub fn get_with_short_name(&self, short_name: &str) -> Option<&ComponentRegistration> { - self.short_names - .get(short_name) - .and_then(|id| self.registrations.get(id)) - } -} - -#[derive(Clone)] -pub struct ComponentRegistration { - pub ty: ComponentTypeId, - pub component_add_fn: fn(&mut World, resources: &Resources, Entity, &dyn Property), - pub component_properties_fn: fn(&ComponentResourceSet, usize) -> &dyn Properties, - pub short_name: &'static str, -} - -impl ComponentRegistration { - pub fn of() -> Self { - let ty = ComponentTypeId::of::(); - Self { - ty, - component_add_fn: |world: &mut World, resources: &Resources, entity: Entity, property: &dyn Property| { - let mut component = T::from_resources(resources); - component.apply(property); - world.add_component(entity, component).unwrap(); - }, - component_properties_fn: |component_resource_set: &ComponentResourceSet, - index: usize| { - // the type has been looked up by the caller, so this is safe - unsafe { &component_resource_set.data_slice::()[index] } - }, - short_name: ty.0.split("::").last().unwrap(), - } - } -} diff --git a/crates/bevy_component_registry/src/lib.rs b/crates/bevy_component_registry/src/lib.rs deleted file mode 100644 index 4e253222c6..0000000000 --- a/crates/bevy_component_registry/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -mod component_registry; -mod register_component; - -pub use component_registry::*; -pub use register_component::*; - -use bevy_app::{AppBuilder, AppPlugin}; - -#[derive(Default)] -pub struct ComponentRegistryPlugin; - -impl AppPlugin for ComponentRegistryPlugin { - fn build(&self, app: &mut AppBuilder) { - app.init_resource::() - .init_resource::(); - } -} diff --git a/crates/bevy_core/Cargo.toml b/crates/bevy_core/Cargo.toml index 7ec7585f04..c2e534397d 100644 --- a/crates/bevy_core/Cargo.toml +++ b/crates/bevy_core/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] bevy_app = { path = "../bevy_app" } -bevy_component_registry = { path = "../bevy_component_registry" } +bevy_type_registry = { path = "../bevy_type_registry" } bevy_transform = { path = "../bevy_transform" } legion = { path = "../bevy_legion" } glam = { path = "../bevy_glam" } diff --git a/crates/bevy_core/src/lib.rs b/crates/bevy_core/src/lib.rs index dd4eb1513d..7bf8c705fb 100644 --- a/crates/bevy_core/src/lib.rs +++ b/crates/bevy_core/src/lib.rs @@ -3,7 +3,7 @@ pub mod time; pub mod transform; use bevy_app::{stage, AppBuilder, AppPlugin}; -use bevy_component_registry::RegisterComponent; +use bevy_type_registry::RegisterType; use bevy_transform::{ components::{ Children, LocalToParent, LocalToWorld, NonUniformScale, Rotation, Scale, Translation, diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index c3f19db5b3..06612145ed 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] bevy_app = { path = "../bevy_app" } bevy_asset = { path = "../bevy_asset" } -bevy_component_registry = { path = "../bevy_component_registry" } +bevy_type_registry = { path = "../bevy_type_registry" } bevy_core = { path = "../bevy_core" } bevy_derive = { path = "../bevy_derive" } bevy_render = { path = "../bevy_render" } diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 72fce9d0b2..662b4bc168 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -9,7 +9,7 @@ pub use forward_pbr_render_graph::*; use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_asset::AddAsset; -use bevy_component_registry::RegisterComponent; +use bevy_type_registry::RegisterType; use bevy_render::{render_graph::RenderGraph, shader}; use legion::prelude::IntoSystem; use light::Light; diff --git a/crates/bevy_property/bevy_property_derive/src/lib.rs b/crates/bevy_property/bevy_property_derive/src/lib.rs index f31db7f191..301b3edde5 100644 --- a/crates/bevy_property/bevy_property_derive/src/lib.rs +++ b/crates/bevy_property/bevy_property_derive/src/lib.rs @@ -150,6 +150,18 @@ pub fn derive_properties(input: TokenStream) -> TokenStream { } } + impl #impl_generics #bevy_property_path::DeserializeProperty for #struct_name#ty_generics { + fn deserialize( + deserializer: &mut dyn #bevy_property_path::erased_serde::Deserializer, + property_type_registry: &#bevy_property_path::PropertyTypeRegistry) -> + Result, #bevy_property_path::erased_serde::Error> { + use #bevy_property_path::serde::de::DeserializeSeed; + let dynamic_properties_deserializer = #bevy_property_path::property_serde::DynamicPropertiesDeserializer::new(property_type_registry); + let dynamic_properties: #bevy_property_path::DynamicProperties = dynamic_properties_deserializer.deserialize(deserializer)?; + Ok(Box::new(dynamic_properties)) + } + } + impl #impl_generics #bevy_property_path::Property for #struct_name#ty_generics { #[inline] fn type_name(&self) -> &str { @@ -198,8 +210,8 @@ pub fn derive_properties(input: TokenStream) -> TokenStream { Some(self) } - fn serializable(&self) -> #bevy_property_path::property_serde::Serializable { - #bevy_property_path::property_serde::Serializable::Owned(Box::new(#bevy_property_path::property_serde::MapSerializer::new(self))) + fn serializable<'a>(&'a self, registry: &'a #bevy_property_path::PropertyTypeRegistry) -> #bevy_property_path::property_serde::Serializable<'a> { + #bevy_property_path::property_serde::Serializable::Owned(Box::new(#bevy_property_path::property_serde::MapSerializer::new(self, registry))) } fn property_type(&self) -> #bevy_property_path::PropertyType { @@ -258,10 +270,8 @@ pub fn derive_property(input: TokenStream) -> TokenStream { } #[inline] - fn serializable(&self) -> #bevy_property_path::property_serde::Serializable { - #bevy_property_path::property_serde::Serializable::Owned(Box::new(#bevy_property_path::property_serde::PropertyValueSerializer { - property: self, - })) + fn serializable<'a>(&'a self, registry: &'a #bevy_property_path::PropertyTypeRegistry) -> #bevy_property_path::property_serde::Serializable<'a> { + #bevy_property_path::property_serde::Serializable::Owned(Box::new(#bevy_property_path::property_serde::PropertyValueSerializer::new(self, registry))) } fn property_type(&self) -> #bevy_property_path::PropertyType { @@ -274,7 +284,7 @@ pub fn derive_property(input: TokenStream) -> TokenStream { deserializer: &mut dyn #bevy_property_path::erased_serde::Deserializer, property_type_registry: &#bevy_property_path::PropertyTypeRegistry) -> Result, #bevy_property_path::erased_serde::Error> { - let property = <#struct_name#ty_generics as Deserialize>::deserialize(deserializer)?; + let property = <#struct_name#ty_generics as #bevy_property_path::serde::Deserialize>::deserialize(deserializer)?; Ok(Box::new(property)) } } @@ -343,9 +353,7 @@ pub fn impl_property(input: TokenStream) -> TokenStream { quote! { #serialize_fn(self) } } else { quote! { - #bevy_property_path::property_serde::Serializable::Owned(Box::new(#bevy_property_path::property_serde::PropertyValueSerializer { - property: self, - })) + #bevy_property_path::property_serde::Serializable::Owned(Box::new(#bevy_property_path::property_serde::PropertyValueSerializer::new(self, registry))) } }; let deserialize_fn = if let Some(deserialize_fn) = property_def.deserialize_fn { @@ -395,7 +403,7 @@ pub fn impl_property(input: TokenStream) -> TokenStream { } #[inline] - fn serializable(&self) -> #bevy_property_path::property_serde::Serializable { + fn serializable<'a>(&'a self, registry: &'a #bevy_property_path::PropertyTypeRegistry) -> #bevy_property_path::property_serde::Serializable<'a> { #serialize_fn } diff --git a/crates/bevy_property/src/dynamic_properties.rs b/crates/bevy_property/src/dynamic_properties.rs index 948f40f2f6..096beabd8f 100644 --- a/crates/bevy_property/src/dynamic_properties.rs +++ b/crates/bevy_property/src/dynamic_properties.rs @@ -1,5 +1,6 @@ -use crate::{property_serde::Serializable, Properties, Property, PropertyIter, PropertyType}; +use crate::{property_serde::{DynamicPropertiesSerializer, Serializable, DynamicPropertiesDeserializer}, Properties, Property, PropertyIter, PropertyType, PropertyTypeRegistry, DeserializeProperty}; use std::{any::Any, borrow::Cow, collections::HashMap}; +use serde::de::DeserializeSeed; pub struct DynamicProperties { pub type_name: String, @@ -168,11 +169,23 @@ impl Property for DynamicProperties { Some(self) } - fn serializable(&self) -> Serializable { - Serializable::Borrowed(self) + fn serializable<'a>(&'a self, registry: &'a PropertyTypeRegistry) -> Serializable<'a> { + Serializable::Owned(Box::new(DynamicPropertiesSerializer::new(self, registry))) } fn property_type(&self) -> PropertyType { self.property_type } } + +impl DeserializeProperty for DynamicProperties { + fn deserialize( + deserializer: &mut dyn erased_serde::Deserializer, + property_type_registry: &PropertyTypeRegistry, + ) -> Result, erased_serde::Error> { + let dynamic_properties_deserializer = DynamicPropertiesDeserializer::new(property_type_registry); + let dynamic_properties: DynamicProperties = dynamic_properties_deserializer.deserialize(deserializer)?; + Ok(Box::new(dynamic_properties)) + } + +} diff --git a/crates/bevy_property/src/impl_property/impl_property_smallvec.rs b/crates/bevy_property/src/impl_property/impl_property_smallvec.rs index cf9d0d1bd7..75c9adb5b8 100644 --- a/crates/bevy_property/src/impl_property/impl_property_smallvec.rs +++ b/crates/bevy_property/src/impl_property/impl_property_smallvec.rs @@ -1,4 +1,4 @@ -use crate::{Property, PropertyType, property_serde::Serializable}; +use crate::{Property, PropertyType, property_serde::Serializable, PropertyTypeRegistry}; use serde::Serialize; use smallvec::{Array, SmallVec}; use std::any::Any; @@ -40,7 +40,7 @@ where } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } diff --git a/crates/bevy_property/src/impl_property/impl_property_std.rs b/crates/bevy_property/src/impl_property/impl_property_std.rs index 1bde946c13..9a62c29b93 100644 --- a/crates/bevy_property/src/impl_property/impl_property_std.rs +++ b/crates/bevy_property/src/impl_property/impl_property_std.rs @@ -1,7 +1,7 @@ use crate::{ impl_property, property_serde::{SeqSerializer, Serializable}, - Properties, Property, PropertyIter, PropertyType, + Properties, Property, PropertyIter, PropertyType, PropertyTypeRegistry, }; use serde::{Deserialize, Serialize}; use std::{ @@ -79,8 +79,8 @@ where Some(self) } - fn serializable(&self) -> Serializable { - Serializable::Owned(Box::new(SeqSerializer::new(self))) + fn serializable<'a>(&'a self, registry: &'a PropertyTypeRegistry) -> Serializable<'a> { + Serializable::Owned(Box::new(SeqSerializer::new(self, registry))) } fn property_type(&self) -> PropertyType { @@ -134,7 +134,7 @@ impl Property for String { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -174,7 +174,7 @@ impl Property for bool { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -232,7 +232,7 @@ impl Property for usize { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -290,7 +290,7 @@ impl Property for u64 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -348,7 +348,7 @@ impl Property for u32 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -406,7 +406,7 @@ impl Property for u16 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -464,7 +464,7 @@ impl Property for u8 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -522,7 +522,7 @@ impl Property for isize { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -580,7 +580,7 @@ impl Property for i64 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -638,7 +638,7 @@ impl Property for i32 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -696,7 +696,7 @@ impl Property for i16 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -754,7 +754,7 @@ impl Property for i8 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -796,7 +796,7 @@ impl Property for f32 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } @@ -838,7 +838,7 @@ impl Property for f64 { } } - fn serializable(&self) -> Serializable { + fn serializable<'a>(&'a self, _registry: &'a PropertyTypeRegistry) -> Serializable<'a> { Serializable::Borrowed(self) } } diff --git a/crates/bevy_property/src/property.rs b/crates/bevy_property/src/property.rs index 8d162f3161..6385531f75 100644 --- a/crates/bevy_property/src/property.rs +++ b/crates/bevy_property/src/property.rs @@ -23,7 +23,7 @@ pub trait Property: Send + Sync + Any + 'static { fn as_properties(&self) -> Option<&dyn Properties> { None } - fn serializable(&self) -> Serializable; + fn serializable<'a>(&'a self, registry: &'a PropertyTypeRegistry) -> Serializable<'a>; } pub trait DeserializeProperty { diff --git a/crates/bevy_property/src/property_serde.rs b/crates/bevy_property/src/property_serde.rs index b5658537de..61e4523738 100644 --- a/crates/bevy_property/src/property_serde.rs +++ b/crates/bevy_property/src/property_serde.rs @@ -29,14 +29,15 @@ where T: Property + Serialize, { pub property: &'a T, + pub registry: &'a PropertyTypeRegistry, } impl<'a, T> PropertyValueSerializer<'a, T> where T: Property + Serialize, { - pub fn new(property: &'a T) -> Self { - PropertyValueSerializer { property } + pub fn new(property: &'a T, registry: &'a PropertyTypeRegistry) -> Self { + PropertyValueSerializer { property, registry } } } @@ -49,20 +50,41 @@ where S: serde::Serializer, { let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(TYPE_FIELD, self.property.type_name())?; + state.serialize_entry(TYPE_FIELD, format_type_name(self.registry, self.property.type_name()))?; state.serialize_entry(VALUE_FIELD, self.property)?; state.end() } } -impl Serialize for DynamicProperties { +pub struct DynamicPropertiesSerializer<'a> { + pub dynamic_properties: &'a DynamicProperties, + pub registry: &'a PropertyTypeRegistry, +} + +impl<'a> DynamicPropertiesSerializer<'a> { + pub fn new( + dynamic_properties: &'a DynamicProperties, + registry: &'a PropertyTypeRegistry, + ) -> Self { + DynamicPropertiesSerializer { + dynamic_properties, + registry, + } + } +} + +impl<'a> Serialize for DynamicPropertiesSerializer<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - match self.property_type { - PropertyType::Map => MapSerializer::new(self).serialize(serializer), - PropertyType::Seq => SeqSerializer::new(self).serialize(serializer), + match self.dynamic_properties.property_type { + PropertyType::Map => { + MapSerializer::new(self.dynamic_properties, self.registry).serialize(serializer) + } + PropertyType::Seq => { + SeqSerializer::new(self.dynamic_properties, self.registry).serialize(serializer) + } _ => { return Err(serde::ser::Error::custom( "DynamicProperties cannot be Value type", @@ -74,25 +96,40 @@ impl Serialize for DynamicProperties { pub struct MapSerializer<'a> { pub properties: &'a dyn Properties, + pub registry: &'a PropertyTypeRegistry, } impl<'a> MapSerializer<'a> { - pub fn new(properties: &'a dyn Properties) -> Self { - MapSerializer { properties } + pub fn new(properties: &'a dyn Properties, registry: &'a PropertyTypeRegistry) -> Self { + MapSerializer { + properties, + registry, + } } } +fn format_type_name<'a>(registry: &'a PropertyTypeRegistry, type_name: &'a str) -> &'a str { + registry + .format_type_name(type_name) + .unwrap_or_else(|| type_name) +} + impl<'a> Serialize for MapSerializer<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(TYPE_FIELD, self.properties.type_name())?; + + state.serialize_entry( + TYPE_FIELD, + format_type_name(self.registry, self.properties.type_name()), + )?; state.serialize_entry( MAP_FIELD, &MapValueSerializer { properties: self.properties, + registry: self.registry, }, )?; state.end() @@ -101,6 +138,7 @@ impl<'a> Serialize for MapSerializer<'a> { pub struct MapValueSerializer<'a> { pub properties: &'a dyn Properties, + pub registry: &'a PropertyTypeRegistry, } impl<'a> Serialize for MapValueSerializer<'a> { @@ -111,7 +149,7 @@ impl<'a> Serialize for MapValueSerializer<'a> { let mut state = serializer.serialize_map(Some(self.properties.prop_len()))?; for (index, property) in self.properties.iter_props().enumerate() { let name = self.properties.prop_name(index).unwrap(); - state.serialize_entry(name, property.serializable().borrow())?; + state.serialize_entry(name, property.serializable(self.registry).borrow())?; } state.end() } @@ -119,11 +157,15 @@ impl<'a> Serialize for MapValueSerializer<'a> { pub struct SeqSerializer<'a> { pub properties: &'a dyn Properties, + pub registry: &'a PropertyTypeRegistry, } impl<'a> SeqSerializer<'a> { - pub fn new(properties: &'a dyn Properties) -> Self { - SeqSerializer { properties } + pub fn new(properties: &'a dyn Properties, registry: &'a PropertyTypeRegistry) -> Self { + SeqSerializer { + properties, + registry, + } } } @@ -133,11 +175,12 @@ impl<'a> Serialize for SeqSerializer<'a> { S: serde::Serializer, { let mut state = serializer.serialize_map(Some(2))?; - state.serialize_entry(TYPE_FIELD, self.properties.type_name())?; + state.serialize_entry(TYPE_FIELD, format_type_name(self.registry, self.properties.type_name()))?; state.serialize_entry( SEQ_FIELD, &SeqValueSerializer { properties: self.properties, + registry: self.registry, }, )?; state.end() @@ -146,6 +189,7 @@ impl<'a> Serialize for SeqSerializer<'a> { pub struct SeqValueSerializer<'a> { pub properties: &'a dyn Properties, + pub registry: &'a PropertyTypeRegistry, } impl<'a> Serialize for SeqValueSerializer<'a> { @@ -155,13 +199,12 @@ impl<'a> Serialize for SeqValueSerializer<'a> { { let mut state = serializer.serialize_seq(Some(self.properties.prop_len()))?; for prop in self.properties.iter_props() { - state.serialize_element(prop.serializable().borrow())?; + state.serialize_element(prop.serializable(self.registry).borrow())?; } state.end() } } - pub struct DynamicPropertiesDeserializer<'a> { registry: &'a PropertyTypeRegistry, } @@ -200,12 +243,11 @@ impl<'a, 'de> Visitor<'de> for DynamicPropertiesVisiter<'a> { { match visit_map(map, self.registry)? { DynamicPropertiesOrProperty::DynamicProperties(value) => Ok(value), - _ => Err(de::Error::custom("Expected DynamicProperties")) + _ => Err(de::Error::custom("Expected DynamicProperties")), } } } - pub struct PropertyDeserializer<'a> { type_name: Option<&'a str>, registry: &'a PropertyTypeRegistry, @@ -221,9 +263,7 @@ impl<'a, 'de> DeserializeSeed<'de> for PropertyDeserializer<'a> { let registration = self.registry.get(type_name).ok_or_else(|| { de::Error::custom(format!("TypeRegistration is missing for {}", type_name)) })?; - let mut erased = erased_serde::Deserializer::erase(deserializer); - (registration.deserialize)(&mut erased, self.registry) - .map_err(<>::Error as serde::de::Error>::custom) + registration.deserialize(deserializer, self.registry) } else { deserializer.deserialize_any(AnyPropVisiter { registry: self.registry, diff --git a/crates/bevy_property/src/type_registry.rs b/crates/bevy_property/src/type_registry.rs index b4d20ddb92..6ce844dd2f 100644 --- a/crates/bevy_property/src/type_registry.rs +++ b/crates/bevy_property/src/type_registry.rs @@ -1,10 +1,14 @@ use crate::{DeserializeProperty, Property}; -use std::{any::TypeId, collections::HashMap}; +use std::{ + any::TypeId, + collections::{HashMap, HashSet}, +}; #[derive(Default)] pub struct PropertyTypeRegistry { - pub registrations: HashMap, - pub short_names: HashMap, + registrations: HashMap, + short_names: HashMap, + ambigous_names: HashSet, } impl PropertyTypeRegistry { @@ -13,44 +17,97 @@ impl PropertyTypeRegistry { T: Property + DeserializeProperty, { let registration = PropertyTypeRegistration::of::(); - self.short_names - .insert(registration.short_name.to_string(), registration.name.to_string()); + self.add_registration(registration); + } + + fn add_registration(&mut self, registration: PropertyTypeRegistration) { + let short_name = registration.short_name.to_string(); + if self.short_names.contains_key(&short_name) || self.ambigous_names.contains(&short_name) { + // name is ambiguous. fall back to long names for all ambiguous types + self.short_names.remove(&short_name); + self.ambigous_names.insert(short_name); + } else { + self.short_names + .insert(short_name, registration.name.to_string()); + } self.registrations .insert(registration.name.to_string(), registration); } pub fn get(&self, type_name: &str) -> Option<&PropertyTypeRegistration> { - self.registrations.get(type_name) + if let Some(long_name) = self.short_names.get(type_name) { + self.registrations.get(long_name) + } else { + self.registrations.get(type_name) + } } - pub fn get_short(&self, short_type_name: &str) -> Option<&PropertyTypeRegistration> { + pub fn format_type_name(&self, type_name: &str) -> Option<&str> { + self.get(type_name).map(|registration| { + if self.short_names.contains_key(®istration.short_name) { + ®istration.short_name + } else { + registration.name + } + }) + } + + pub fn get_with_short_name(&self, short_type_name: &str) -> Option<&PropertyTypeRegistration> { self.short_names .get(short_type_name) .and_then(|name| self.registrations.get(name)) } + + pub fn get_with_full_name(&self, type_name: &str) -> Option<&PropertyTypeRegistration> { + self.registrations.get(type_name) + } } #[derive(Clone)] pub struct PropertyTypeRegistration { pub ty: TypeId, - pub deserialize: fn( + deserialize_fn: fn( deserializer: &mut dyn erased_serde::Deserializer, property_type_registry: &PropertyTypeRegistry, ) -> Result, erased_serde::Error>, - pub short_name: &'static str, + pub short_name: String, pub name: &'static str, } impl PropertyTypeRegistration { pub fn of() -> Self { let ty = TypeId::of::(); + let type_name = std::any::type_name::(); Self { ty, - deserialize: |deserializer: &mut dyn erased_serde::Deserializer, property_type_registry: &PropertyTypeRegistry| { - T::deserialize(deserializer, property_type_registry) - }, - name: std::any::type_name::(), - short_name: std::any::type_name::().split("::").last().unwrap(), + deserialize_fn: + |deserializer: &mut dyn erased_serde::Deserializer, + property_type_registry: &PropertyTypeRegistry| { + T::deserialize(deserializer, property_type_registry) + }, + name: type_name, + short_name: Self::get_short_name(type_name), } } + + pub fn get_short_name(full_name: &str) -> String { + full_name + .split("<") + .map(|p| p.split("::").last().unwrap().to_string()) + .collect::>() + .join("<") + } + + pub fn deserialize<'de, D>( + &self, + deserializer: D, + registry: &PropertyTypeRegistry, + ) -> Result, D::Error> + where + D: serde::Deserializer<'de>, + { + let mut erased = erased_serde::Deserializer::erase(deserializer); + (self.deserialize_fn)(&mut erased, registry) + .map_err(<>::Error as serde::de::Error>::custom) + } } diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index f85b764c18..93633cc008 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" # bevy bevy_app = { path = "../bevy_app" } bevy_asset = { path = "../bevy_asset" } -bevy_component_registry = { path = "../bevy_component_registry" } +bevy_type_registry = { path = "../bevy_type_registry" } bevy_core = { path = "../bevy_core" } bevy_derive = { path = "../bevy_derive" } bevy_property = { path = "../bevy_property" } diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index eeb0008c3f..6622ec83b2 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -42,7 +42,7 @@ use self::{ use base_render_graph::{BaseRenderGraphBuilder, BaseRenderGraphConfig}; use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_asset::AddAsset; -use bevy_component_registry::RegisterComponent; +use bevy_type_registry::RegisterType; use legion::prelude::IntoSystem; use mesh::mesh_resource_provider_system; use render_graph::RenderGraph; diff --git a/crates/bevy_scene/Cargo.toml b/crates/bevy_scene/Cargo.toml index c036086e6f..e45502b5a5 100644 --- a/crates/bevy_scene/Cargo.toml +++ b/crates/bevy_scene/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] bevy_app = { path = "../bevy_app" } bevy_asset = { path = "../bevy_asset" } -bevy_component_registry = { path = "../bevy_component_registry" } +bevy_type_registry = { path = "../bevy_type_registry" } bevy_property = { path = "../bevy_property" } legion = { path = "../bevy_legion", features = ["serialize"] } serde = { version = "1.0", features = ["derive"]} diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 117b55de02..367a98f232 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -1,19 +1,19 @@ use anyhow::Result; -use bevy_component_registry::ComponentRegistry; -use bevy_property::DynamicProperties; +use bevy_type_registry::ComponentRegistry; +use bevy_property::{PropertyTypeRegistry, DynamicProperties}; use legion::prelude::{Resources, World}; use serde::Serialize; use std::num::Wrapping; use thiserror::Error; +use crate::serde::SceneSerializer; #[derive(Default)] pub struct Scene { pub entities: Vec, } -#[derive(Serialize)] pub struct Entity { - pub id: u32, + pub entity: u32, pub components: Vec, } @@ -40,12 +40,12 @@ impl Scene { for (index, entity) in component_storage.entities().iter().enumerate() { if index == entities.len() { entities.push(Entity { - id: entity.index(), + entity: entity.index(), components: Vec::new(), }) } - let properties = (component_registration.component_properties_fn)( + let properties = component_registration.get_component_properties( &component_resource_set, index, ); @@ -72,18 +72,18 @@ impl Scene { world.entity_allocator.push_next_ids( self.entities .iter() - .map(|e| legion::prelude::Entity::new(e.id, Wrapping(1))), + .map(|e| legion::prelude::Entity::new(e.entity, Wrapping(1))), ); for scene_entity in self.entities.iter() { // TODO: use EntityEntry when legion refactor is finished let entity = world.insert((), vec![()])[0]; for component in scene_entity.components.iter() { let component_registration = component_registry - .get_with_full_name(&component.type_name) + .get_with_name(&component.type_name) .ok_or_else(|| SceneAddError::UnregisteredComponent { type_name: component.type_name.to_string(), })?; - (component_registration.component_add_fn)(world, resources, entity, component); + component_registration.add_component_to_entity(world, resources, entity, component); } } @@ -91,14 +91,15 @@ impl Scene { } // TODO: move to AssetSaver when it is implemented - pub fn serialize_ron(&self) -> Result { + pub fn serialize_ron(&self, registry: &PropertyTypeRegistry) -> Result { let pretty_config = ron::ser::PrettyConfig::default() .with_decimal_floats(true) .with_indentor(" ".to_string()) .with_new_line("\n".to_string()); let mut buf = Vec::new(); - let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), true)?; - self.serialize(&mut serializer)?; + let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), false)?; + let scene_serializer = SceneSerializer::new(self, registry); + scene_serializer.serialize(&mut serializer)?; Ok(String::from_utf8(buf).unwrap()) } } diff --git a/crates/bevy_scene/src/scene_loader.rs b/crates/bevy_scene/src/scene_loader.rs index 0ee4fc5650..4e7531a440 100644 --- a/crates/bevy_scene/src/scene_loader.rs +++ b/crates/bevy_scene/src/scene_loader.rs @@ -2,27 +2,28 @@ use crate::{serde::SceneDeserializer, Scene}; use anyhow::Result; use bevy_app::FromResources; use bevy_asset::AssetLoader; -use bevy_component_registry::PropertyTypeRegistryContext; +use bevy_property::PropertyTypeRegistry; use legion::prelude::Resources; use serde::de::DeserializeSeed; -use std::path::Path; +use std::{sync::{Arc, RwLock}, path::Path}; +use bevy_type_registry::TypeRegistry; pub struct SceneLoader { - property_type_registry: PropertyTypeRegistryContext, + property_type_registry: Arc>, } impl FromResources for SceneLoader { fn from_resources(resources: &Resources) -> Self { - let property_type_registry = resources.get::().unwrap(); + let type_registry = resources.get::().unwrap(); SceneLoader { - property_type_registry: property_type_registry.clone(), + property_type_registry: type_registry.property.clone(), } } } impl AssetLoader for SceneLoader { fn from_bytes(&self, _asset_path: &Path, bytes: Vec) -> Result { - let registry = self.property_type_registry.value.read().unwrap(); + let registry = self.property_type_registry.read().unwrap(); let mut deserializer = ron::de::Deserializer::from_bytes(&bytes).unwrap(); let scene_deserializer = SceneDeserializer { property_type_registry: ®istry, diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index 22622d996b..426597c104 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -1,22 +1,84 @@ use crate::{Entity, Scene}; use anyhow::Result; use bevy_property::{ - property_serde::DynamicPropertiesDeserializer, DynamicProperties, PropertyTypeRegistry, + property_serde::{DynamicPropertiesSerializer, DynamicPropertiesDeserializer}, DynamicProperties, PropertyTypeRegistry, }; use serde::{ de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}, + ser::{SerializeSeq, SerializeStruct}, Deserialize, Serialize, }; -impl Serialize for Scene { +pub struct SceneSerializer<'a> { + pub scene: &'a Scene, + pub registry: &'a PropertyTypeRegistry, +} + +impl<'a> SceneSerializer<'a> { + pub fn new(scene: &'a Scene, registry: &'a PropertyTypeRegistry) -> Self { + SceneSerializer { + scene, + registry, + } + } +} + +impl<'a> Serialize for SceneSerializer<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - self.entities.serialize(serializer) + let mut state = serializer.serialize_seq(Some(self.scene.entities.len()))?; + for entity in self.scene.entities.iter() { + state.serialize_element(&EntitySerializer { + entity, + registry: self.registry, + })?; + } + state.end() } } +pub struct EntitySerializer<'a> { + pub entity: &'a Entity, + pub registry: &'a PropertyTypeRegistry, +} + +impl<'a> Serialize for EntitySerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_struct(ENTITY_STRUCT, 2)?; + state.serialize_field(ENTITY_FIELD_ENTITY, &self.entity.entity)?; + state.serialize_field(ENTITY_FIELD_COMPONENTS, &ComponentsSerializer { + components: &self.entity.components, + registry: self.registry, + })?; + state.end() + } +} + + +pub struct ComponentsSerializer<'a> { + pub components: &'a [DynamicProperties], + pub registry: &'a PropertyTypeRegistry, +} + +impl<'a> Serialize for ComponentsSerializer<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_seq(Some(self.components.len()))?; + for dynamic_properties in self.components.iter() { + state.serialize_element(&DynamicPropertiesSerializer::new(dynamic_properties, self.registry))?; + } + state.end() + } +} + + pub struct SceneDeserializer<'a> { pub property_type_registry: &'a PropertyTypeRegistry, } @@ -72,8 +134,8 @@ impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> { D: serde::Deserializer<'de>, { deserializer.deserialize_struct( - "Entity", - &["id", "components"], + ENTITY_STRUCT, + &[ENTITY_FIELD_ENTITY, ENTITY_FIELD_COMPONENTS], SceneEntityVisiter { registry: self.property_type_registry, }, @@ -84,11 +146,12 @@ impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> { #[derive(Deserialize)] #[serde(field_identifier, rename_all = "lowercase")] enum EntityField { - Id, + Entity, Components, } -pub const ENTITY_FIELD_ID: &str = "id"; +pub const ENTITY_STRUCT: &str = "Entity"; +pub const ENTITY_FIELD_ENTITY: &str = "entity"; pub const ENTITY_FIELD_COMPONENTS: &str = "components"; struct SceneEntityVisiter<'a> { @@ -109,9 +172,9 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> { let mut components = None; while let Some(key) = map.next_key()? { match key { - EntityField::Id => { + EntityField::Entity => { if id.is_some() { - return Err(Error::duplicate_field(ENTITY_FIELD_ID)); + return Err(Error::duplicate_field(ENTITY_FIELD_ENTITY)); } id = Some(map.next_value::()?); } @@ -129,13 +192,13 @@ impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> { let entity = id .as_ref() - .ok_or_else(|| Error::missing_field(ENTITY_FIELD_ID))?; + .ok_or_else(|| Error::missing_field(ENTITY_FIELD_ENTITY))?; let components = components .take() .ok_or_else(|| Error::missing_field(ENTITY_FIELD_COMPONENTS))?; Ok(Entity { - id: *entity, + entity: *entity, components, }) } diff --git a/crates/bevy_component_registry/Cargo.toml b/crates/bevy_type_registry/Cargo.toml similarity index 91% rename from crates/bevy_component_registry/Cargo.toml rename to crates/bevy_type_registry/Cargo.toml index 7e50888490..ae170654ad 100644 --- a/crates/bevy_component_registry/Cargo.toml +++ b/crates/bevy_type_registry/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "bevy_component_registry" +name = "bevy_type_registry" version = "0.1.0" authors = ["Carter Anderson "] edition = "2018" diff --git a/crates/bevy_type_registry/src/lib.rs b/crates/bevy_type_registry/src/lib.rs new file mode 100644 index 0000000000..16f4d5c5db --- /dev/null +++ b/crates/bevy_type_registry/src/lib.rs @@ -0,0 +1,18 @@ +mod type_registry; +mod register_type; + +pub use type_registry::*; +pub use register_type::*; + +use bevy_app::{AppBuilder, AppPlugin}; +use bevy_property::DynamicProperties; + +#[derive(Default)] +pub struct TypeRegistryPlugin; + +impl AppPlugin for TypeRegistryPlugin { + fn build(&self, app: &mut AppBuilder) { + app.init_resource::() + .register_property_type::(); + } +} diff --git a/crates/bevy_component_registry/src/register_component.rs b/crates/bevy_type_registry/src/register_type.rs similarity index 50% rename from crates/bevy_component_registry/src/register_component.rs rename to crates/bevy_type_registry/src/register_type.rs index b636de3051..7c65bc5609 100644 --- a/crates/bevy_component_registry/src/register_component.rs +++ b/crates/bevy_type_registry/src/register_type.rs @@ -1,43 +1,43 @@ use bevy_property::{Property, Properties, DeserializeProperty}; use legion::storage::Component; -use crate::{PropertyTypeRegistryContext, ComponentRegistryContext}; use bevy_app::{FromResources, AppBuilder}; +use crate::TypeRegistry; -pub trait RegisterComponent { +pub trait RegisterType { fn register_component(&mut self) -> &mut Self where - T: Properties + Component + FromResources; + T: Properties + DeserializeProperty + Component + FromResources; fn register_property_type(&mut self) -> &mut Self where T: Property + DeserializeProperty; } -impl RegisterComponent for AppBuilder { +impl RegisterType for AppBuilder { fn register_component(&mut self) -> &mut Self where - T: Properties + Component + FromResources, + T: Properties + DeserializeProperty + Component + FromResources, { { - let registry_context = self + let type_registry = self .resources() - .get_mut::() + .get_mut::() .unwrap(); - registry_context.value.write().unwrap().register::(); + type_registry.component.write().unwrap().register::(); + type_registry.property.write().unwrap().register::(); } self } fn register_property_type(&mut self) -> &mut Self where - T: Property + DeserializeProperty, - { + T: Property + DeserializeProperty { { - let registry_context = self + let type_registry = self .resources() - .get_mut::() + .get_mut::() .unwrap(); - registry_context.value.write().unwrap().register::(); + type_registry.property.write().unwrap().register::(); } self } diff --git a/crates/bevy_type_registry/src/type_registry.rs b/crates/bevy_type_registry/src/type_registry.rs new file mode 100644 index 0000000000..c5074f6ff7 --- /dev/null +++ b/crates/bevy_type_registry/src/type_registry.rs @@ -0,0 +1,123 @@ +use bevy_app::FromResources; +use bevy_property::{Properties, Property, PropertyTypeRegistration, PropertyTypeRegistry}; +use legion::{ + prelude::{Entity, Resources, World}, + storage::{Component, ComponentResourceSet, ComponentTypeId}, +}; +use std::{ + collections::{HashMap, HashSet}, + sync::{Arc, RwLock}, +}; + +#[derive(Clone, Default)] +pub struct TypeRegistry { + pub property: Arc>, + pub component: Arc>, +} + +#[derive(Default)] +pub struct ComponentRegistry { + pub registrations: HashMap, + pub short_names: HashMap, + pub full_names: HashMap, + pub ambigous_names: HashSet, +} + +impl ComponentRegistry { + pub fn register(&mut self) + where + T: Properties + Component + FromResources, + { + let registration = ComponentRegistration::of::(); + let short_name = registration.short_name.to_string(); + self.full_names + .insert(registration.ty.0.to_string(), registration.ty); + if self.short_names.contains_key(&short_name) || self.ambigous_names.contains(&short_name) { + // name is ambiguous. fall back to long names for all ambiguous types + self.short_names.remove(&short_name); + self.ambigous_names.insert(short_name); + } else { + self.short_names + .insert(short_name, registration.ty); + } + self.registrations.insert(registration.ty, registration); + } + + pub fn get(&self, type_id: &ComponentTypeId) -> Option<&ComponentRegistration> { + self.registrations.get(type_id) + } + + pub fn get_with_full_name(&self, full_name: &str) -> Option<&ComponentRegistration> { + self.full_names + .get(full_name) + .and_then(|id| self.registrations.get(id)) + } + + pub fn get_with_short_name(&self, short_name: &str) -> Option<&ComponentRegistration> { + self.short_names + .get(short_name) + .and_then(|id| self.registrations.get(id)) + } + + pub fn get_with_name(&self, type_name: &str) -> Option<&ComponentRegistration> { + let mut registration = self.get_with_short_name(type_name); + if registration.is_none() { + registration = self.get_with_full_name(type_name); + if registration.is_none() { + if self.ambigous_names.contains(type_name) { + panic!("Type name is ambiguous: {}", type_name); + } + } + } + registration + } +} + +#[derive(Clone)] +pub struct ComponentRegistration { + pub ty: ComponentTypeId, + component_add_fn: fn(&mut World, resources: &Resources, Entity, &dyn Property), + component_properties_fn: fn(&ComponentResourceSet, usize) -> &dyn Properties, + pub short_name: String, +} + +impl ComponentRegistration { + pub fn of() -> Self { + let ty = ComponentTypeId::of::(); + Self { + ty, + component_add_fn: |world: &mut World, + resources: &Resources, + entity: Entity, + property: &dyn Property| { + let mut component = T::from_resources(resources); + component.apply(property); + world.add_component(entity, component).unwrap(); + }, + component_properties_fn: |component_resource_set: &ComponentResourceSet, + index: usize| { + // the type has been looked up by the caller, so this is safe + unsafe { &component_resource_set.data_slice::()[index] } + }, + short_name: PropertyTypeRegistration::get_short_name(ty.0), + } + } + + pub fn add_component_to_entity( + &self, + world: &mut World, + resources: &Resources, + entity: Entity, + property: &dyn Property, + ) { + (self.component_add_fn)(world, resources, entity, property); + } + + pub fn get_component_properties<'a>( + &self, + component_resource_set: &'a ComponentResourceSet, + entity_index: usize, + ) -> &'a dyn Properties { + (self.component_properties_fn)(component_resource_set, entity_index) + } +} diff --git a/crates/bevy_ui/Cargo.toml b/crates/bevy_ui/Cargo.toml index 33dab00c42..01dbc54fae 100644 --- a/crates/bevy_ui/Cargo.toml +++ b/crates/bevy_ui/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] bevy_app = { path = "../bevy_app" } bevy_asset = { path = "../bevy_asset" } -bevy_component_registry = { path = "../bevy_component_registry" } +bevy_type_registry = { path = "../bevy_type_registry" } bevy_core = { path = "../bevy_core" } bevy_derive = { path = "../bevy_derive" } bevy_text = { path = "../bevy_text" } diff --git a/examples/scene/load_scene.rs b/examples/scene/load_scene.rs index 48333084cc..25a4b7314f 100644 --- a/examples/scene/load_scene.rs +++ b/examples/scene/load_scene.rs @@ -1,7 +1,4 @@ -use bevy::{ - component_registry::ComponentRegistryContext, input::keyboard::KeyboardInput, prelude::*, -}; -use bevy_app::FromResources; +use bevy::{input::keyboard::KeyboardInput, prelude::*, type_registry::TypeRegistry}; fn main() { App::build() @@ -64,11 +61,16 @@ fn save_scene_system(world: &mut World, resources: &mut Resources) { .add(ComponentA { x: 3.0, y: 4.0 }); // The component registry resource contains information about all registered components. This is used to construct scenes. - let component_registry = resources.get::().unwrap(); - let scene = Scene::from_world(world, &component_registry.value.read().unwrap()); + let type_registry = resources.get::().unwrap(); + let scene = Scene::from_world(world, &type_registry.component.read().unwrap()); // Scenes can be serialized like this: - println!("{}", scene.serialize_ron().unwrap()); + println!( + "{}", + scene + .serialize_ron(&type_registry.property.read().unwrap()) + .unwrap() + ); // TODO: save scene } @@ -76,16 +78,16 @@ fn save_scene_system(world: &mut World, resources: &mut Resources) { fn load_scene_system(world: &mut World, resources: &mut Resources) { let asset_server = resources.get::().unwrap(); let mut scenes = resources.get_mut::>().unwrap(); - + // Scenes are loaded just like any other asset. let scene_handle: Handle = asset_server .load_sync(&mut scenes, "assets/scene/load_scene_example.scn") .unwrap(); let scene = scenes.get(&scene_handle).unwrap(); - // Scenes can be added to any ECS World. Adding scenes also uses the component registry. - let component_registry = resources.get::().unwrap(); + // Scenes can be added to any ECS World. Adding scenes also uses the component registry. + let type_registry = resources.get::().unwrap(); scene - .add_to_world(world, resources, &component_registry.value.read().unwrap()) + .add_to_world(world, resources, &type_registry.component.read().unwrap()) .unwrap(); } diff --git a/examples/scene/properties.rs b/examples/scene/properties.rs index 3a4e9b86df..e9a56ec744 100644 --- a/examples/scene/properties.rs +++ b/examples/scene/properties.rs @@ -1,7 +1,7 @@ use bevy::{ - component_registry::PropertyTypeRegistryContext, prelude::*, - property::{ron::deserialize_dynamic_properties}, + property::{ron::deserialize_dynamic_properties, PropertyTypeRegistry}, + type_registry::TypeRegistry, }; use serde::{Deserialize, Serialize}; @@ -9,6 +9,8 @@ fn main() { App::build() .add_default_plugins() // If you need to deserialize custom property types, register them like this: + .register_property_type::() + .register_property_type::() .register_property_type::() .add_startup_system(setup.system()) .run(); @@ -31,7 +33,7 @@ pub struct CustomProperty { a: usize, } -fn setup(property_type_registry: Res) { +fn setup(type_registry: Res) { let mut test = Test { a: 1, custom: CustomProperty { a: 10 }, @@ -58,15 +60,14 @@ fn setup(property_type_registry: Res) { // All properties can be serialized. // If you #[derive(Properties)] your type doesn't even need to directly implement the Serde trait! - let ron_string = serialize_ron(&test.serializable().borrow()).unwrap(); + let registry = type_registry.property.read().unwrap(); + let ron_string = serialize_ron(&test, ®istry).unwrap(); println!("{}\n", ron_string); // Dynamic properties can be deserialized - let dynamic_properties = - deserialize_dynamic_properties(&ron_string, &property_type_registry.value.read().unwrap()) - .unwrap(); + let dynamic_properties = deserialize_dynamic_properties(&ron_string, ®istry).unwrap(); - let round_tripped = serialize_ron(&dynamic_properties).unwrap(); + let round_tripped = serialize_ron(&dynamic_properties, ®istry).unwrap(); println!("{}", round_tripped); assert_eq!(ron_string, round_tripped); @@ -81,23 +82,24 @@ fn setup(property_type_registry: Res) { seq.apply(&patch); assert_eq!(seq[0], 3); - let ron_string = serialize_ron(&patch.serializable().borrow()).unwrap(); + let ron_string = serialize_ron(&patch, ®istry).unwrap(); println!("{}\n", ron_string); - let dynamic_properties = - deserialize_dynamic_properties(&ron_string, &property_type_registry.value.read().unwrap()) - .unwrap(); - let round_tripped = serialize_ron(&dynamic_properties).unwrap(); + let dynamic_properties = deserialize_dynamic_properties(&ron_string, ®istry).unwrap(); + let round_tripped = serialize_ron(&dynamic_properties, ®istry).unwrap(); assert_eq!(ron_string, round_tripped); } -fn serialize_ron(properties: &T) -> Result +fn serialize_ron(property: &T, registry: &PropertyTypeRegistry) -> Result where - T: Serialize, + T: Property, { let pretty_config = ron::ser::PrettyConfig::default().with_decimal_floats(true); let mut buf = Vec::new(); - let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), true)?; - properties.serialize(&mut serializer)?; + let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), false)?; + property + .serializable(registry) + .borrow() + .serialize(&mut serializer)?; let ron_string = String::from_utf8(buf).unwrap(); Ok(ron_string) } diff --git a/src/add_default_plugins.rs b/src/add_default_plugins.rs index 76260ca37a..96f8cb72a3 100644 --- a/src/add_default_plugins.rs +++ b/src/add_default_plugins.rs @@ -6,8 +6,8 @@ pub trait AddDefaultPlugins { impl AddDefaultPlugins for AppBuilder { fn add_default_plugins(&mut self) -> &mut Self { - #[cfg(feature = "component_registry")] - self.add_plugin(bevy_component_registry::ComponentRegistryPlugin::default()); + #[cfg(feature = "type_registry")] + self.add_plugin(bevy_type_registry::TypeRegistryPlugin::default()); #[cfg(feature = "core")] self.add_plugin(bevy_core::CorePlugin::default()); diff --git a/src/lib.rs b/src/lib.rs index ec7d0361e2..0f8fa9c2bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,8 +49,8 @@ pub use legion; #[cfg(feature = "asset")] pub use bevy_asset as asset; -#[cfg(feature = "component_registry")] -pub use bevy_component_registry as component_registry; +#[cfg(feature = "type_registry")] +pub use bevy_type_registry as type_registry; #[cfg(feature = "core")] pub use bevy_core as core; #[cfg(feature = "derive")] diff --git a/src/prelude.rs b/src/prelude.rs index 21eeb330e4..bb0ac0b517 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,7 +1,6 @@ +pub use crate::app::FromResources; #[cfg(feature = "asset")] pub use crate::asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle}; -#[cfg(feature = "component_registry")] -pub use crate::component_registry::RegisterComponent; #[cfg(feature = "core")] pub use crate::core::{ time::Time, @@ -39,6 +38,8 @@ pub use crate::scene::Scene; pub use crate::text::Font; #[cfg(feature = "transform")] pub use crate::transform::prelude::*; +#[cfg(feature = "type_registry")] +pub use crate::type_registry::RegisterType; #[cfg(feature = "ui")] pub use crate::ui::{ entity::*, widget::Label, Anchors, ColorMaterial, Margins, Node, Rect, Sprite,