From 4c306e6d48c11f59716d4c5ee20e469e068c1446 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 23 May 2020 22:07:17 -0700 Subject: [PATCH] props: migrate scenes to props. loading / saving worlds from / to props. --- assets/scene/load_scene_example.scn | 38 ++- crates/bevy_property/src/properties.rs | 6 +- crates/bevy_scene/Cargo.toml | 4 +- crates/bevy_scene/src/component_registry.rs | 69 ++--- crates/bevy_scene/src/lib.rs | 2 - crates/bevy_scene/src/scene.rs | 121 +++++--- crates/bevy_scene/src/serde/mod.rs | 6 - crates/bevy_scene/src/serde/scene_de.rs | 288 -------------------- crates/bevy_scene/src/serde/scene_ser.rs | 165 ----------- crates/bevy_scene/src/serde/world.rs | 236 ---------------- examples/scene/load_scene.rs | 55 +++- examples/scene/properties.rs | 64 ++--- 12 files changed, 195 insertions(+), 859 deletions(-) delete mode 100644 crates/bevy_scene/src/serde/mod.rs delete mode 100644 crates/bevy_scene/src/serde/scene_de.rs delete mode 100644 crates/bevy_scene/src/serde/scene_ser.rs delete mode 100644 crates/bevy_scene/src/serde/world.rs diff --git a/assets/scene/load_scene_example.scn b/assets/scene/load_scene_example.scn index 7cb5237e5c..1d3c695c67 100644 --- a/assets/scene/load_scene_example.scn +++ b/assets/scene/load_scene_example.scn @@ -1,32 +1,26 @@ [ ( - entity: 2309003120, + entity: 3072676124, components: [ - ( - type: "Test", - data: ( - x: 3, - y: 4, - ), - ), - ( - type: "Foo", - data: ( - value: "hi", - ), - ), + { + "type": "load_scene::Test", + "x": 3.0, + "y": 4.0, + }, ], ), ( - entity: 4238063392, + entity: 3949176536, components: [ - ( - type: "Test", - data: ( - x: 3, - y: 4, - ), - ), + { + "type": "load_scene::Test", + "x": 1.0, + "y": 2.0, + }, + { + "type": "load_scene::Foo", + "value": "hello", + }, ], ), ] \ No newline at end of file diff --git a/crates/bevy_property/src/properties.rs b/crates/bevy_property/src/properties.rs index 97ff5221b8..8bd9b814a3 100644 --- a/crates/bevy_property/src/properties.rs +++ b/crates/bevy_property/src/properties.rs @@ -1,7 +1,7 @@ use crate::{DynamicProperties, Property, PropertyVal}; use serde::{ser::SerializeMap, Serialize}; -pub trait Properties { +pub trait Properties: Property { fn type_name(&self) -> &str; fn prop(&self, name: &str) -> Option<&dyn Property>; fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Property>; @@ -63,11 +63,11 @@ impl

PropertiesVal for P where P: Properties, { - // #[inline] + #[inline] fn prop_val(&self, name: &str) -> Option<&T> { self.prop(name).and_then(|p| p.any().downcast_ref::()) } - // #[inline] + #[inline] fn set_prop_val(&mut self, name: &str, value: T) { if let Some(prop) = self.prop_mut(name) { prop.set_val(value); diff --git a/crates/bevy_scene/Cargo.toml b/crates/bevy_scene/Cargo.toml index 527c6a0dfc..8909c16d6a 100644 --- a/crates/bevy_scene/Cargo.toml +++ b/crates/bevy_scene/Cargo.toml @@ -12,5 +12,5 @@ legion = { path = "../bevy_legion", features = ["serialize"] } serde = { version = "1.0", features = ["derive"]} erased-serde = "0.3" ron = { path = "../ron" } -uuid = { version = "0.8", features = ["v4", "serde"] } -anyhow = "1.0" \ No newline at end of file +anyhow = "1.0" +thiserror = "1.0" \ No newline at end of file diff --git a/crates/bevy_scene/src/component_registry.rs b/crates/bevy_scene/src/component_registry.rs index 2362be8785..43aad69c3f 100644 --- a/crates/bevy_scene/src/component_registry.rs +++ b/crates/bevy_scene/src/component_registry.rs @@ -1,15 +1,17 @@ use bevy_app::AppBuilder; +use bevy_property::{Properties, Property}; use legion::{ prelude::{Entity, World}, - storage::{ArchetypeDescription, ComponentResourceSet, ComponentTypeId}, + storage::{Component, ComponentTypeId, ComponentResourceSet}, +}; +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, }; -use serde::{de::DeserializeSeed, ser::Serialize, Deserialize}; -use std::{collections::HashMap, marker::PhantomData, ptr::NonNull, sync::{RwLock, Arc}}; -use crate::world::ComponentSeqDeserializer; #[derive(Default)] pub struct ComponentRegistryContext { - pub value: Arc>, + pub value: Arc>, } #[derive(Default)] @@ -22,7 +24,7 @@ pub struct ComponentRegistry { impl ComponentRegistry { pub fn register(&mut self) where - T: Clone + Send + Sync + 'static + Serialize + for<'de> Deserialize<'de>, + T: Properties + Component + Default, { let registration = ComponentRegistration::of::(); self.short_names @@ -52,52 +54,24 @@ impl ComponentRegistry { #[derive(Clone)] pub struct ComponentRegistration { pub ty: ComponentTypeId, - pub comp_serialize_fn: fn(&ComponentResourceSet, &mut dyn FnMut(&dyn erased_serde::Serialize)), - pub individual_comp_serialize_fn: - fn(&ComponentResourceSet, usize, &mut dyn FnMut(&dyn erased_serde::Serialize)), - pub comp_deserialize_fn: fn( - deserializer: &mut dyn erased_serde::Deserializer, - get_next_storage_fn: &mut dyn FnMut() -> Option<(NonNull, usize)>, - ) -> Result<(), erased_serde::Error>, - pub individual_comp_deserialize_fn: fn( - deserializer: &mut dyn erased_serde::Deserializer, - &mut World, - Entity, - ) -> Result<(), erased_serde::Error>, - pub register_comp_fn: fn(&mut ArchetypeDescription), + pub component_add_fn: fn(&mut World, Entity, &dyn Property), + pub component_properties_fn: fn(&ComponentResourceSet, usize) -> &dyn Properties, pub short_name: &'static str, } impl ComponentRegistration { - pub fn of Deserialize<'de> + Send + Sync + 'static>() -> Self { + pub fn of() -> Self { let ty = ComponentTypeId::of::(); Self { ty, - comp_serialize_fn: |comp_storage, serialize_fn| { - // it's safe because we know this is the correct type due to lookup - let slice = unsafe { comp_storage.data_slice::() }; - serialize_fn(&*slice); - }, - individual_comp_serialize_fn: |comp_storage, index: usize, serialize_fn| { - // it's safe because we know this is the correct type due to lookup - let slice = unsafe { comp_storage.data_slice::() }; - serialize_fn(&slice[index]); - }, - comp_deserialize_fn: |deserializer, get_next_storage_fn| { - let comp_seq_deser = ComponentSeqDeserializer:: { - get_next_storage_fn, - _marker: PhantomData, - }; - comp_seq_deser.deserialize(deserializer)?; - Ok(()) - }, - individual_comp_deserialize_fn: |deserializer, world, entity| { - let component = erased_serde::deserialize::(deserializer)?; + component_add_fn: |world: &mut World, entity: Entity, property: &dyn Property| { + let mut component = T::default(); + component.apply(property); world.add_component(entity, component).unwrap(); - Ok(()) }, - register_comp_fn: |desc| { - desc.register_component::(); + 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(), } @@ -107,16 +81,19 @@ impl ComponentRegistration { pub trait RegisterComponent { fn register_component(&mut self) -> &mut Self where - T: Clone + Send + Sync + 'static + Serialize + for<'de> Deserialize<'de>; + T: Properties + Component + Default; } impl RegisterComponent for AppBuilder { fn register_component(&mut self) -> &mut Self where - T: Clone + Send + Sync + 'static + Serialize + for<'de> Deserialize<'de>, + T: Properties + Component + Default, { { - let registry_context = self.resources().get_mut::().unwrap(); + let registry_context = self + .resources() + .get_mut::() + .unwrap(); registry_context.value.write().unwrap().register::(); } self diff --git a/crates/bevy_scene/src/lib.rs b/crates/bevy_scene/src/lib.rs index 6dda3ba2fe..1d4eb7c5d1 100644 --- a/crates/bevy_scene/src/lib.rs +++ b/crates/bevy_scene/src/lib.rs @@ -1,7 +1,5 @@ mod component_registry; mod scene; -mod serde; -pub use crate::serde::*; pub use component_registry::*; pub use scene::*; diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 0d6942fdf2..cfdf858b6b 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -1,59 +1,104 @@ -use crate::{ComponentRegistry, ComponentRegistryContext, SceneDeserializer}; +use crate::ComponentRegistry; use anyhow::Result; -use bevy_app::FromResources; use bevy_asset::AssetLoader; use bevy_property::DynamicProperties; -use legion::prelude::{Resources, World}; -use serde::de::DeserializeSeed; -use serde::{Serialize, Deserialize}; -use std::{ - path::Path, - sync::{Arc, RwLock}, -}; +use legion::prelude::{Entity, World}; +use serde::{Deserialize, Serialize}; +use std::{num::Wrapping, path::Path}; +use thiserror::Error; -pub struct DynamicScene { +#[derive(Serialize, Deserialize, Default)] +pub struct Scene { pub entities: Vec, } +#[derive(Error, Debug)] +pub enum SceneAddError { + #[error("Scene contains an unregistered component.")] + UnregisteredComponent { type_name: String }, +} + +impl Scene { + pub fn from_world(world: &World, component_registry: &ComponentRegistry) -> Self { + let mut scene = Scene::default(); + for archetype in world.storage().archetypes() { + for chunkset in archetype.chunksets() { + for component_storage in chunkset.occupied() { + let mut entities = Vec::new(); + for (component_type_id, _component_meta) in archetype.description().components() + { + if let Some(component_registration) = + component_registry.get(component_type_id) + { + let component_resource_set = + component_storage.components(*component_type_id).unwrap(); + for (index, entity) in component_storage.entities().iter().enumerate() { + if index == entities.len() { + entities.push(SceneEntity { + entity: entity.index(), + components: Vec::new(), + }) + } + + let properties = (component_registration.component_properties_fn)( + &component_resource_set, + index, + ); + + entities[index].components.push(properties.to_dynamic()); + } + } + } + + scene.entities.extend(entities.drain(..)); + } + } + } + + scene + } + + pub fn add_to_world( + &self, + world: &mut World, + component_registry: &ComponentRegistry, + ) -> Result<(), SceneAddError> { + world.entity_allocator.push_next_ids( + self.entities + .iter() + .map(|e| 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) + .ok_or_else(|| SceneAddError::UnregisteredComponent { + type_name: component.type_name.to_string(), + })?; + (component_registration.component_add_fn)(world, entity, component); + } + } + + Ok(()) + } +} + #[derive(Serialize, Deserialize)] pub struct SceneEntity { pub entity: u32, pub components: Vec, } - #[derive(Default)] -pub struct Scene { - pub world: World, -} - -pub struct SceneLoader { - component_registry: Arc>, -} - -impl FromResources for SceneLoader { - fn from_resources(resources: &Resources) -> Self { - let component_registry = resources - .get::() - .expect("SceneLoader requires the ComponentRegistry resource."); - SceneLoader { - component_registry: component_registry.value.clone(), - } - } -} +pub struct SceneLoader; impl AssetLoader for SceneLoader { fn from_bytes(&self, _asset_path: &Path, bytes: Vec) -> Result { let mut deserializer = ron::de::Deserializer::from_bytes(&bytes).unwrap(); - let mut scene = Scene::default(); - let scene_deserializer = SceneDeserializer { - component_registry: &self.component_registry.read().unwrap(), - scene: &mut scene, - }; - - scene_deserializer.deserialize(&mut deserializer).unwrap(); - - Ok(scene) + let entities = Vec::::deserialize(&mut deserializer).unwrap(); + Ok(Scene { entities }) } fn extensions(&self) -> &[&str] { static EXTENSIONS: &[&str] = &["scn"]; diff --git a/crates/bevy_scene/src/serde/mod.rs b/crates/bevy_scene/src/serde/mod.rs deleted file mode 100644 index 775bbd2964..0000000000 --- a/crates/bevy_scene/src/serde/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod scene_de; -mod scene_ser; -pub mod world; - -pub use scene_de::*; -pub use scene_ser::*; \ No newline at end of file diff --git a/crates/bevy_scene/src/serde/scene_de.rs b/crates/bevy_scene/src/serde/scene_de.rs deleted file mode 100644 index 2d610dc1ba..0000000000 --- a/crates/bevy_scene/src/serde/scene_de.rs +++ /dev/null @@ -1,288 +0,0 @@ -use crate::{ComponentRegistration, ComponentRegistry, Scene}; -use legion::prelude::{Entity, World}; -use serde::{ - de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor}, - Deserialize, -}; -use std::num::Wrapping; - -pub struct SceneDeserializer<'a> { - pub component_registry: &'a ComponentRegistry, - pub scene: &'a mut Scene, -} - -impl<'de> DeserializeSeed<'de> for SceneDeserializer<'de> { - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_seq(EntitySeqVisiter { - world: &mut self.scene.world, - component_registry: &self.component_registry, - })?; - - Ok(()) - } -} - -struct EntitySeqVisiter<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, -} - -impl<'a, 'de> Visitor<'de> for EntitySeqVisiter<'a> { - type Value = (); - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("list of entities") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - while let Some(()) = seq.next_element_seed(EntityDeserializer { - world: self.world, - component_registry: self.component_registry, - })? {} - - Ok(()) - } -} - -struct EntityDeserializer<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, -} - - -pub const ENTITY_FIELD_ENTITY: &str = "entity"; -pub const ENTITY_FIELD_COMPONENTS: &str = "components"; - -impl<'a, 'de> DeserializeSeed<'de> for EntityDeserializer<'a> { - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_struct( - "Entity", - &[ENTITY_FIELD_ENTITY, ENTITY_FIELD_COMPONENTS], - EntityVisiter { - world: self.world, - component_registry: self.component_registry, - }, - ) - } -} - -struct EntityVisiter<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, -} - -impl<'a, 'de> Visitor<'de> for EntityVisiter<'a> { - type Value = (); - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("entity struct") - } - - fn visit_map(self, mut map: V) -> Result<(), V::Error> - where - V: MapAccess<'de>, - { - let mut entity = None; - let mut components = false; - while let Some(key) = map.next_key()? { - match key { - EntityField::Entity => { - if entity.is_some() { - return Err(Error::duplicate_field(ENTITY_FIELD_ENTITY)); - } - let id = map.next_value()?; - self.world - .entity_allocator - .push_next_ids((&[Entity::new(id, Wrapping(1))]).iter().map(|e| (*e))); - entity = Some(self.world.insert((), vec![()])[0]); - } - EntityField::Components => { - if components { - return Err(Error::duplicate_field(ENTITY_FIELD_COMPONENTS)); - } - - let entity = entity.ok_or_else(|| Error::missing_field(ENTITY_FIELD_ENTITY))?; - // this is just a placeholder value to protect against duplicates - components = true; - map.next_value_seed(ComponentSeqDeserializer { - entity, - world: self.world, - component_registry: self.component_registry, - })?; - } - } - } - Ok(()) - } -} - -#[derive(Deserialize)] -#[serde(field_identifier, rename_all = "lowercase")] -enum EntityField { - Entity, - Components, -} - -struct ComponentSeqDeserializer<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, - pub entity: Entity, -} - -impl<'a, 'de> DeserializeSeed<'de> for ComponentSeqDeserializer<'a> { - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_seq(ComponentSeqVisiter { - entity: self.entity, - world: self.world, - component_registry: self.component_registry, - }) - } -} - -struct ComponentSeqVisiter<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, - pub entity: Entity, -} - -impl<'a, 'de> Visitor<'de> for ComponentSeqVisiter<'a> { - type Value = (); - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("list of components") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - while let Some(()) = seq.next_element_seed(ComponentDeserializer { - entity: self.entity, - world: self.world, - component_registry: self.component_registry, - })? {} - - Ok(()) - } -} -struct ComponentDeserializer<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, - pub entity: Entity, -} - -impl<'a, 'de> DeserializeSeed<'de> for ComponentDeserializer<'a> { - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_struct( - "Component", - &[COMPONENT_FIELD_TYPE, COMPONENT_FIELD_DATA], - ComponentVisiter { - entity: self.entity, - world: self.world, - component_registry: self.component_registry, - }, - ) - } -} - -#[derive(Deserialize)] -#[serde(field_identifier, rename_all = "lowercase")] -enum ComponentField { - Type, - Data, -} - -pub const COMPONENT_FIELD_TYPE: &str = "type"; -pub const COMPONENT_FIELD_DATA: &str = "data"; - -struct ComponentVisiter<'a> { - pub component_registry: &'a ComponentRegistry, - pub world: &'a mut World, - pub entity: Entity, -} - -impl<'a, 'de> Visitor<'de> for ComponentVisiter<'a> { - type Value = (); - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("component") - } - - fn visit_map(self, mut map: V) -> Result<(), V::Error> - where - V: MapAccess<'de>, - { - let mut component_type = None; - let mut component_data = false; - while let Some(key) = map.next_key()? { - match key { - ComponentField::Type => { - if component_type.is_some() { - return Err(Error::duplicate_field(COMPONENT_FIELD_TYPE)); - } - component_type = Some(map.next_value::()?); - } - ComponentField::Data => { - if component_data { - return Err(Error::duplicate_field(COMPONENT_FIELD_DATA)); - } - - let component_type = component_type - .as_ref() - .ok_or_else(|| Error::missing_field(COMPONENT_FIELD_TYPE))?; - let component_registration = self - .component_registry - .get_with_short_name(component_type) - .ok_or_else(|| Error::custom(format!("Component '{}' has not been registered. Consider registering it with AppBuilder::register_component::<{}>()", component_type, component_type)))?; - // this is just a placeholder value to protect against duplicates - component_data = true; - map.next_value_seed(ComponentDataDeserializer { - entity: self.entity, - world: self.world, - component_registration, - })?; - } - } - } - Ok(()) - } -} - -struct ComponentDataDeserializer<'a> { - pub component_registration: &'a ComponentRegistration, - pub world: &'a mut World, - pub entity: Entity, -} - -impl<'a, 'de> DeserializeSeed<'de> for ComponentDataDeserializer<'a> { - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - if let Err(err) = (self.component_registration.individual_comp_deserialize_fn)( - &mut erased_serde::Deserializer::erase(deserializer), - self.world, - self.entity, - ) { - return Err(Error::custom(err.to_string())); - } - - Ok(()) - } -} diff --git a/crates/bevy_scene/src/serde/scene_ser.rs b/crates/bevy_scene/src/serde/scene_ser.rs deleted file mode 100644 index 793882b68e..0000000000 --- a/crates/bevy_scene/src/serde/scene_ser.rs +++ /dev/null @@ -1,165 +0,0 @@ -use crate::{ComponentRegistry, Scene, ComponentRegistration}; -use legion::{ - prelude::Entity, - storage::{ComponentMeta, ComponentResourceSet, ComponentStorage, ComponentTypeId}, -}; -use serde::ser::{Serialize, SerializeSeq, SerializeStruct}; -use std::cell::RefCell; - -pub struct SerializableScene<'a> { - pub scene: &'a Scene, - pub component_registry: &'a ComponentRegistry, -} - -impl<'a> SerializableScene<'a> { - pub fn new(scene: &'a Scene, component_registry: &'a ComponentRegistry) -> Self { - SerializableScene { - scene, - component_registry, - } - } -} - -impl<'a> Serialize for SerializableScene<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut seq = serializer.serialize_seq(Some(self.scene.world.iter_entities().count()))?; - for archetype in self.scene.world.storage().archetypes() { - for chunkset in archetype.chunksets() { - for component_storage in chunkset.occupied() { - for (index, entity) in component_storage.entities().iter().enumerate() { - seq.serialize_element(&WorldEntity { - index, - archetype_components: archetype.description().components(), - component_registry: &self.component_registry, - component_storage, - entity: *entity, - })?; - } - } - } - } - - seq.end() - } -} - -struct WorldEntity<'a> { - archetype_components: &'a [(ComponentTypeId, ComponentMeta)], - component_registry: &'a ComponentRegistry, - component_storage: &'a ComponentStorage, - entity: Entity, - index: usize, -} - -impl<'a> Serialize for WorldEntity<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_struct("Entity", 2)?; - state.serialize_field("entity", &self.entity.index())?; - state.serialize_field( - "components", - &EntityComponents { - archetype_components: self.archetype_components, - component_registry: self.component_registry, - component_storage: self.component_storage, - index: self.index, - }, - )?; - state.end() - } -} - -struct EntityComponents<'a> { - index: usize, - archetype_components: &'a [(ComponentTypeId, ComponentMeta)], - component_storage: &'a ComponentStorage, - component_registry: &'a ComponentRegistry, -} - -impl<'a> Serialize for EntityComponents<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut seq = serializer.serialize_seq(Some(self.archetype_components.len()))?; - for (component_type, _) in self.archetype_components.iter() { - seq.serialize_element(&EntityComponent { - index: self.index, - component_resource_set: self.component_storage.components(*component_type).unwrap(), - component_registration: self.component_registry.get(component_type).unwrap(), - })?; - } - seq.end() - } -} - -struct EntityComponent<'a> { - index: usize, - component_resource_set: &'a ComponentResourceSet, - component_registration: &'a ComponentRegistration, -} - -impl<'a> Serialize for EntityComponent<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_struct("Component", 2)?; - state.serialize_field( - "type", - &ComponentName(self.component_registration.short_name), - )?; - state.serialize_field( - "data", - &ComponentData { - index: self.index, - component_registration: self.component_registration, - component_resource_set: self.component_resource_set, - }, - )?; - state.end() - } -} - -struct ComponentName(&'static str); - -impl<'a> Serialize for ComponentName { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(self.0) - } -} -struct ComponentData<'a> { - index: usize, - component_resource_set: &'a ComponentResourceSet, - component_registration: &'a ComponentRegistration, -} - -impl<'a> Serialize for ComponentData<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut result = None; - let serializer = RefCell::new(Some(serializer)); - (self.component_registration.individual_comp_serialize_fn)( - self.component_resource_set, - self.index, - &mut |serialize| { - result = Some(erased_serde::serialize( - serialize, - serializer.borrow_mut().take().unwrap(), - )); - }, - ); - - result.unwrap() - } -} diff --git a/crates/bevy_scene/src/serde/world.rs b/crates/bevy_scene/src/serde/world.rs deleted file mode 100644 index a8af2d5be7..0000000000 --- a/crates/bevy_scene/src/serde/world.rs +++ /dev/null @@ -1,236 +0,0 @@ -// adapted from https://github.com/TomGillen/legion/blob/master/examples/serde.rs - -use crate::ComponentRegistry; -use legion::{ - entity::EntityIndex, - guid_entity_allocator::GuidEntityAllocator, - prelude::*, - storage::{ - ArchetypeDescription, ComponentMeta, ComponentResourceSet, ComponentTypeId, TagMeta, - TagStorage, TagTypeId, - }, -}; -use serde::{ - de::{self, DeserializeSeed, IgnoredAny, Visitor}, - Deserialize, Deserializer, Serialize, Serializer, -}; -use std::{cell::RefCell, marker::PhantomData, num::Wrapping, ptr::NonNull}; - -struct ComponentDeserializer<'de, T: Deserialize<'de>> { - ptr: *mut T, - _marker: PhantomData<&'de T>, -} - -impl<'de, T: Deserialize<'de> + 'static> DeserializeSeed<'de> for ComponentDeserializer<'de, T> { - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let value = >::deserialize(deserializer)?; - unsafe { - std::ptr::write(self.ptr, value); - } - Ok(()) - } -} - -pub(crate) struct ComponentSeqDeserializer<'a, T> { - pub get_next_storage_fn: &'a mut dyn FnMut() -> Option<(NonNull, usize)>, - pub _marker: PhantomData, -} - -impl<'de, 'a, T: for<'b> Deserialize<'b> + 'static> DeserializeSeed<'de> - for ComponentSeqDeserializer<'a, T> -{ - type Value = (); - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - deserializer.deserialize_seq(self) - } -} -impl<'de, 'a, T: for<'b> Deserialize<'b> + 'static> Visitor<'de> - for ComponentSeqDeserializer<'a, T> -{ - type Value = (); - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("sequence of objects") - } - fn visit_seq(self, mut seq: A) -> Result - where - A: de::SeqAccess<'de>, - { - let size = seq.size_hint(); - for _ in 0..size.unwrap_or(std::usize::MAX) { - match (self.get_next_storage_fn)() { - Some((storage_ptr, storage_len)) => { - let storage_ptr = storage_ptr.as_ptr() as *mut T; - for idx in 0..storage_len { - let element_ptr = unsafe { storage_ptr.offset(idx as isize) }; - - if let None = seq.next_element_seed(ComponentDeserializer { - ptr: element_ptr, - _marker: PhantomData, - })? { - panic!( - "expected {} elements in chunk but only {} found", - storage_len, idx - ); - } - } - } - None => { - if let Some(_) = seq.next_element::()? { - panic!("unexpected element when there was no storage space available"); - } else { - // No more elements and no more storage - that's what we want! - break; - } - } - } - } - Ok(()) - } -} - -#[derive(Serialize, Deserialize)] -struct SerializedArchetypeDescription { - tag_types: Vec, - component_types: Vec, -} - -impl legion::serialize::ser::WorldSerializer for ComponentRegistry { - fn can_serialize_tag(&self, _ty: &TagTypeId, _meta: &TagMeta) -> bool { - false - } - fn can_serialize_component(&self, ty: &ComponentTypeId, _meta: &ComponentMeta) -> bool { - self.get(ty).is_some() - } - fn serialize_archetype_description( - &self, - serializer: S, - archetype_desc: &ArchetypeDescription, - ) -> Result { - let tags_to_serialize = archetype_desc - .tags() - .iter() - .map(|(tag_type_id, _)| tag_type_id.0.to_string()) - .collect::>(); - let components_to_serialize = archetype_desc - .components() - .iter() - .map(|(component_type_id, _)| component_type_id.0.to_string()) - .collect::>(); - SerializedArchetypeDescription { - tag_types: tags_to_serialize, - component_types: components_to_serialize, - } - .serialize(serializer) - } - fn serialize_components( - &self, - serializer: S, - component_type: &ComponentTypeId, - _component_meta: &ComponentMeta, - components: &ComponentResourceSet, - ) -> Result { - if let Some(reg) = self.get(component_type) { - let result = RefCell::new(None); - let serializer = RefCell::new(Some(serializer)); - { - let mut result_ref = result.borrow_mut(); - (reg.comp_serialize_fn)(components, &mut |serialize| { - result_ref.replace(erased_serde::serialize( - serialize, - serializer.borrow_mut().take().unwrap(), - )); - }); - } - return result.borrow_mut().take().unwrap(); - } - panic!( - "received unserializable type {:?}, this should be filtered by can_serialize", - component_type - ); - } - fn serialize_tags( - &self, - _serializer: S, - tag_type: &TagTypeId, - _tag_meta: &TagMeta, - _tags: &TagStorage, - ) -> Result { - panic!( - "received unserializable type {:?}, this should be filtered by can_serialize", - tag_type - ); - } - fn serialize_entities( - &self, - serializer: S, - entities: &[Entity], - ) -> Result { - serializer.collect_seq(entities.iter().map(|e| e.index())) - } -} - -impl<'a> legion::serialize::de::WorldDeserializer for ComponentRegistry { - fn deserialize_archetype_description<'de, D: Deserializer<'de>>( - &self, - deserializer: D, - ) -> Result>::Error> { - let serialized_desc = - ::deserialize(deserializer)?; - let mut desc = ArchetypeDescription::default(); - - for comp in serialized_desc.component_types { - if let Some(reg) = self.get_with_full_name(&comp) { - (reg.register_comp_fn)(&mut desc); - } - } - Ok(desc) - } - fn deserialize_components<'de, D: Deserializer<'de>>( - &self, - deserializer: D, - component_type: &ComponentTypeId, - _component_meta: &ComponentMeta, - get_next_storage_fn: &mut dyn FnMut() -> Option<(NonNull, usize)>, - ) -> Result<(), >::Error> { - if let Some(reg) = self.get(component_type) { - let mut erased = erased_serde::Deserializer::erase(deserializer); - (reg.comp_deserialize_fn)(&mut erased, get_next_storage_fn) - .map_err(<>::Error as serde::de::Error>::custom)?; - } else { - ::deserialize(deserializer)?; - } - Ok(()) - } - fn deserialize_tags<'de, D: Deserializer<'de>>( - &self, - deserializer: D, - _tag_type: &TagTypeId, - _tag_meta: &TagMeta, - _tags: &mut TagStorage, - ) -> Result<(), >::Error> { - ::deserialize(deserializer)?; - Ok(()) - } - fn deserialize_entities<'de, D: Deserializer<'de>>( - &self, - deserializer: D, - entity_allocator: &GuidEntityAllocator, - entities: &mut Vec, - ) -> Result<(), >::Error> { - let entity_indices = as Deserialize>::deserialize(deserializer)?; - entity_allocator.push_next_ids(entity_indices.iter().map(|i| Entity::new(*i, Wrapping(0)))); - for _index in entity_indices { - let entity = entity_allocator.create_entity(); - entities.push(entity); - } - Ok(()) - } -} diff --git a/examples/scene/load_scene.rs b/examples/scene/load_scene.rs index 2bae30c9e2..fcf4baa540 100644 --- a/examples/scene/load_scene.rs +++ b/examples/scene/load_scene.rs @@ -1,36 +1,73 @@ use bevy::prelude::*; -use serde::{Deserialize, Serialize}; +use bevy_scene::ComponentRegistryContext; +use serde::Serialize; fn main() { App::build() .add_default_plugins() - // Registering components informs Bevy that they exist. This allows them to be used when loading/saving scenes - // This step is only required if you want to load/save your components. + // Registering components informs Bevy that they exist. This allows them to be used when loading scenes + // This step is only required if you want to load your components from scene files. .register_component::() .register_component::() - // .add_startup_system(setup) .add_startup_system(load_scene) + // .add_startup_system(serialize_scene) .run(); } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Properties, Default)] struct Test { pub x: f32, pub y: f32, } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Properties, Default)] struct Foo { pub value: String, } -fn load_scene(_world: &mut World, resources: &mut Resources) { +#[derive(Serialize)] +struct Ahh { + pub x: Vec, +} + +#[derive(Serialize)] +struct A { + pub x: f32, +} + +fn load_scene(world: &mut World, resources: &mut Resources) { let asset_server = resources.get::().unwrap(); let mut scenes = resources.get_mut::>().unwrap(); + let component_registry = resources.get::().unwrap(); let scene_handle: Handle = asset_server .load_sync(&mut scenes, "assets/scene/load_scene_example.scn") .unwrap(); - let _scene= scenes.get(&scene_handle).unwrap(); - // world.merge(scene) + let scene= scenes.get(&scene_handle).unwrap(); + scene.add_to_world(world, &component_registry.value.read().unwrap()).unwrap(); +} + +#[allow(dead_code)] +fn serialize_scene(world: &mut World, resources: &mut Resources) { + let component_registry = resources.get::().unwrap(); + world.build() + .build_entity() + .add(Test { + x: 1.0, + y: 2.0, + }) + .add(Foo { + value: "hello".to_string() + }) + .build_entity() + .add(Test { + x: 3.0, + y: 4.0, + }); + + let scene = Scene::from_world(world, &component_registry.value.read().unwrap()); + let pretty_config = ron::ser::PrettyConfig::default().with_decimal_floats(true); + let ron_string = ron::ser::to_string_pretty(&scene, pretty_config).unwrap(); + println!("{}", ron_string); + } \ No newline at end of file diff --git a/examples/scene/properties.rs b/examples/scene/properties.rs index 4cfd30f3bc..164d13ca7b 100644 --- a/examples/scene/properties.rs +++ b/examples/scene/properties.rs @@ -1,9 +1,7 @@ use bevy::{ prelude::*, property::SerializableProperties, - scene::{DynamicScene, SceneEntity}, }; -use serde::{de::Deserialize, ser::Serialize}; fn main() { App::build() @@ -15,71 +13,53 @@ fn main() { #[derive(Properties, Default)] pub struct Test { a: usize, - b: String, - c: f32, - nest: Nested, + nested: Nested, } #[derive(Properties, Default)] pub struct Nested { - d: usize, + b: usize, } fn setup() { let mut test = Test { a: 1, - b: "hi".to_string(), - c: 1.0, - nest: Nested { - d: 8, + nested: Nested { + b: 8, } }; + // You can set a property value like this. The type must match exactly or this will fail. test.set_prop_val::("a", 2); assert_eq!(test.a, 2); + + // You can also set properties dynamically. set_prop accepts any type that implements Property let x: u32 = 3; test.set_prop("a", &x); assert_eq!(test.a, 3); - test.set_prop_val::("c", 2.0); - let x: f64 = 3.0; - test.set_prop("c", &x); - assert_eq!(test.c, 3.0); - + // DynamicProperties also implements the Properties trait. let mut patch = DynamicProperties::default(); - patch.set::("a", 3); + patch.set::("a", 4); + + // You can "apply" Properties on top of other Properties. This will only set properties with the same name and type. + // You can use this to "patch" your components with new values. test.apply(&patch); + assert_eq!(test.a, 4); - assert_eq!(test.a, 3); - + // Properties implement the serde Serialize trait. You don't need to derive it yourself! let ser = SerializableProperties { props: &test }; 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.clone()), false).unwrap(); - ser.serialize(&mut serializer).unwrap(); - let ron_string = String::from_utf8(buf).unwrap(); - println!("{}", ron_string); + let ron_string = ron::ser::to_string_pretty(&ser, pretty_config.clone()).unwrap(); + println!("{}\n", ron_string); - // let dynamic_scene = DynamicScene { - // entities: vec![SceneEntity { - // entity: 12345, - // components: vec![patch], - // }], - // }; - - // let mut serializer = ron::ser::Serializer::new(Some(ron::ser::PrettyConfig::default()), false); - // dynamic_scene.entities.serialize(&mut serializer).unwrap(); - // println!("{}", serializer.into_output_string()); - - let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap(); - let dynamic_properties = DynamicProperties::deserialize(&mut deserializer).unwrap(); - let mut buf = Vec::new(); - let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), false).unwrap(); - dynamic_properties.serialize(&mut serializer).unwrap(); - let round_tripped = String::from_utf8(buf).unwrap(); - println!(); + // Dynamic properties can be deserialized + let dynamic_properties = ron::from_str::(&ron_string).unwrap(); + let round_tripped = ron::ser::to_string_pretty(&dynamic_properties, pretty_config).unwrap(); println!("{}", round_tripped); assert_eq!(ron_string, round_tripped); + + // This means you can patch Properties with dynamic properties deserialized from a string + test.apply(&dynamic_properties); }