mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
scene: type registry refactor. use short type names when possible
This commit is contained in:
parent
91af49ede3
commit
830565ae2b
33 changed files with 489 additions and 262 deletions
|
@ -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 }
|
||||
|
|
|
@ -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" }
|
||||
|
||||
|
|
|
@ -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::{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<RwLock<PropertyTypeRegistry>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ComponentRegistryContext {
|
||||
pub value: Arc<RwLock<ComponentRegistry>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ComponentRegistry {
|
||||
pub registrations: HashMap<ComponentTypeId, ComponentRegistration>,
|
||||
pub short_names: HashMap<String, ComponentTypeId>,
|
||||
pub full_names: HashMap<String, ComponentTypeId>,
|
||||
}
|
||||
|
||||
impl ComponentRegistry {
|
||||
pub fn register<T>(&mut self)
|
||||
where
|
||||
T: Properties + Component + FromResources,
|
||||
{
|
||||
let registration = ComponentRegistration::of::<T>();
|
||||
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<T: Properties + Component + FromResources>() -> Self {
|
||||
let ty = ComponentTypeId::of::<T>();
|
||||
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::<T>()[index] }
|
||||
},
|
||||
short_name: ty.0.split("::").last().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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::<ComponentRegistryContext>()
|
||||
.init_resource::<PropertyTypeRegistryContext>();
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Box<dyn #bevy_property_path::Property>, #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<Box<dyn #bevy_property_path::Property>, #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
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Box<dyn Property>, 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))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
|
||||
registration.deserialize(deserializer, self.registry)
|
||||
} else {
|
||||
deserializer.deserialize_any(AnyPropVisiter {
|
||||
registry: self.registry,
|
||||
|
|
|
@ -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<String, PropertyTypeRegistration>,
|
||||
pub short_names: HashMap<String, String>,
|
||||
registrations: HashMap<String, PropertyTypeRegistration>,
|
||||
short_names: HashMap<String, String>,
|
||||
ambigous_names: HashSet<String>,
|
||||
}
|
||||
|
||||
impl PropertyTypeRegistry {
|
||||
|
@ -13,44 +17,97 @@ impl PropertyTypeRegistry {
|
|||
T: Property + DeserializeProperty,
|
||||
{
|
||||
let registration = PropertyTypeRegistration::of::<T>();
|
||||
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<Box<dyn Property>, erased_serde::Error>,
|
||||
pub short_name: &'static str,
|
||||
pub short_name: String,
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
impl PropertyTypeRegistration {
|
||||
pub fn of<T: Property + DeserializeProperty>() -> Self {
|
||||
let ty = TypeId::of::<T>();
|
||||
let type_name = std::any::type_name::<T>();
|
||||
Self {
|
||||
ty,
|
||||
deserialize: |deserializer: &mut dyn erased_serde::Deserializer, property_type_registry: &PropertyTypeRegistry| {
|
||||
T::deserialize(deserializer, property_type_registry)
|
||||
},
|
||||
name: std::any::type_name::<T>(),
|
||||
short_name: std::any::type_name::<T>().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::<Vec<String>>()
|
||||
.join("<")
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(
|
||||
&self,
|
||||
deserializer: D,
|
||||
registry: &PropertyTypeRegistry,
|
||||
) -> Result<Box<dyn Property>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let mut erased = erased_serde::Deserializer::erase(deserializer);
|
||||
(self.deserialize_fn)(&mut erased, registry)
|
||||
.map_err(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"]}
|
||||
|
|
|
@ -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<Entity>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Entity {
|
||||
pub id: u32,
|
||||
pub entity: u32,
|
||||
pub components: Vec<DynamicProperties>,
|
||||
}
|
||||
|
||||
|
@ -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<String, ron::Error> {
|
||||
pub fn serialize_ron(&self, registry: &PropertyTypeRegistry) -> Result<String, ron::Error> {
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RwLock<PropertyTypeRegistry>>,
|
||||
}
|
||||
|
||||
impl FromResources for SceneLoader {
|
||||
fn from_resources(resources: &Resources) -> Self {
|
||||
let property_type_registry = resources.get::<PropertyTypeRegistryContext>().unwrap();
|
||||
let type_registry = resources.get::<TypeRegistry>().unwrap();
|
||||
SceneLoader {
|
||||
property_type_registry: property_type_registry.clone(),
|
||||
property_type_registry: type_registry.property.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AssetLoader<Scene> for SceneLoader {
|
||||
fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
|
||||
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,
|
||||
|
|
|
@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
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::<u32>()?);
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "bevy_component_registry"
|
||||
name = "bevy_type_registry"
|
||||
version = "0.1.0"
|
||||
authors = ["Carter Anderson <mcanders1@gmail.com>"]
|
||||
edition = "2018"
|
18
crates/bevy_type_registry/src/lib.rs
Normal file
18
crates/bevy_type_registry/src/lib.rs
Normal file
|
@ -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::<TypeRegistry>()
|
||||
.register_property_type::<DynamicProperties>();
|
||||
}
|
||||
}
|
|
@ -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<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Properties + Component + FromResources;
|
||||
T: Properties + DeserializeProperty + Component + FromResources;
|
||||
fn register_property_type<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Property + DeserializeProperty;
|
||||
}
|
||||
|
||||
impl RegisterComponent for AppBuilder {
|
||||
impl RegisterType for AppBuilder {
|
||||
fn register_component<T>(&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::<ComponentRegistryContext>()
|
||||
.get_mut::<TypeRegistry>()
|
||||
.unwrap();
|
||||
registry_context.value.write().unwrap().register::<T>();
|
||||
type_registry.component.write().unwrap().register::<T>();
|
||||
type_registry.property.write().unwrap().register::<T>();
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn register_property_type<T>(&mut self) -> &mut Self
|
||||
where
|
||||
T: Property + DeserializeProperty,
|
||||
{
|
||||
T: Property + DeserializeProperty {
|
||||
{
|
||||
let registry_context = self
|
||||
let type_registry = self
|
||||
.resources()
|
||||
.get_mut::<PropertyTypeRegistryContext>()
|
||||
.get_mut::<TypeRegistry>()
|
||||
.unwrap();
|
||||
registry_context.value.write().unwrap().register::<T>();
|
||||
type_registry.property.write().unwrap().register::<T>();
|
||||
}
|
||||
self
|
||||
}
|
123
crates/bevy_type_registry/src/type_registry.rs
Normal file
123
crates/bevy_type_registry/src/type_registry.rs
Normal file
|
@ -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<RwLock<PropertyTypeRegistry>>,
|
||||
pub component: Arc<RwLock<ComponentRegistry>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ComponentRegistry {
|
||||
pub registrations: HashMap<ComponentTypeId, ComponentRegistration>,
|
||||
pub short_names: HashMap<String, ComponentTypeId>,
|
||||
pub full_names: HashMap<String, ComponentTypeId>,
|
||||
pub ambigous_names: HashSet<String>,
|
||||
}
|
||||
|
||||
impl ComponentRegistry {
|
||||
pub fn register<T>(&mut self)
|
||||
where
|
||||
T: Properties + Component + FromResources,
|
||||
{
|
||||
let registration = ComponentRegistration::of::<T>();
|
||||
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<T: Properties + Component + FromResources>() -> Self {
|
||||
let ty = ComponentTypeId::of::<T>();
|
||||
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::<T>()[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)
|
||||
}
|
||||
}
|
|
@ -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" }
|
||||
|
|
|
@ -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::<ComponentRegistryContext>().unwrap();
|
||||
let scene = Scene::from_world(world, &component_registry.value.read().unwrap());
|
||||
let type_registry = resources.get::<TypeRegistry>().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::<AssetServer>().unwrap();
|
||||
let mut scenes = resources.get_mut::<Assets<Scene>>().unwrap();
|
||||
|
||||
|
||||
// Scenes are loaded just like any other asset.
|
||||
let scene_handle: Handle<Scene> = 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::<ComponentRegistryContext>().unwrap();
|
||||
// Scenes can be added to any ECS World. Adding scenes also uses the component registry.
|
||||
let type_registry = resources.get::<TypeRegistry>().unwrap();
|
||||
scene
|
||||
.add_to_world(world, resources, &component_registry.value.read().unwrap())
|
||||
.add_to_world(world, resources, &type_registry.component.read().unwrap())
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -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::<Test>()
|
||||
.register_property_type::<Nested>()
|
||||
.register_property_type::<CustomProperty>()
|
||||
.add_startup_system(setup.system())
|
||||
.run();
|
||||
|
@ -31,7 +33,7 @@ pub struct CustomProperty {
|
|||
a: usize,
|
||||
}
|
||||
|
||||
fn setup(property_type_registry: Res<PropertyTypeRegistryContext>) {
|
||||
fn setup(type_registry: Res<TypeRegistry>) {
|
||||
let mut test = Test {
|
||||
a: 1,
|
||||
custom: CustomProperty { a: 10 },
|
||||
|
@ -58,15 +60,14 @@ fn setup(property_type_registry: Res<PropertyTypeRegistryContext>) {
|
|||
|
||||
// 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<PropertyTypeRegistryContext>) {
|
|||
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<T>(properties: &T) -> Result<String, ron::Error>
|
||||
fn serialize_ron<T>(property: &T, registry: &PropertyTypeRegistry) -> Result<String, ron::Error>
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue