props: migrate scenes to props. loading / saving worlds from / to props.

This commit is contained in:
Carter Anderson 2020-05-23 22:07:17 -07:00
parent f36a67ee96
commit 4c306e6d48
12 changed files with 195 additions and 859 deletions

View file

@ -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",
},
],
),
]

View file

@ -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<P> PropertiesVal for P
where
P: Properties,
{
// #[inline]
#[inline]
fn prop_val<T: 'static>(&self, name: &str) -> Option<&T> {
self.prop(name).and_then(|p| p.any().downcast_ref::<T>())
}
// #[inline]
#[inline]
fn set_prop_val<T: 'static>(&mut self, name: &str, value: T) {
if let Some(prop) = self.prop_mut(name) {
prop.set_val(value);

View file

@ -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"
anyhow = "1.0"
thiserror = "1.0"

View file

@ -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<RwLock<ComponentRegistry>>,
pub value: Arc<RwLock<ComponentRegistry>>,
}
#[derive(Default)]
@ -22,7 +24,7 @@ pub struct ComponentRegistry {
impl ComponentRegistry {
pub fn register<T>(&mut self)
where
T: Clone + Send + Sync + 'static + Serialize + for<'de> Deserialize<'de>,
T: Properties + Component + Default,
{
let registration = ComponentRegistration::of::<T>();
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<u8>, 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<T: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static>() -> Self {
pub fn of<T: Properties + Component + Default>() -> Self {
let ty = ComponentTypeId::of::<T>();
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::<T>() };
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::<T>() };
serialize_fn(&slice[index]);
},
comp_deserialize_fn: |deserializer, get_next_storage_fn| {
let comp_seq_deser = ComponentSeqDeserializer::<T> {
get_next_storage_fn,
_marker: PhantomData,
};
comp_seq_deser.deserialize(deserializer)?;
Ok(())
},
individual_comp_deserialize_fn: |deserializer, world, entity| {
let component = erased_serde::deserialize::<T>(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::<T>();
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(),
}
@ -107,16 +81,19 @@ impl ComponentRegistration {
pub trait RegisterComponent {
fn register_component<T>(&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<T>(&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::<ComponentRegistryContext>().unwrap();
let registry_context = self
.resources()
.get_mut::<ComponentRegistryContext>()
.unwrap();
registry_context.value.write().unwrap().register::<T>();
}
self

View file

@ -1,7 +1,5 @@
mod component_registry;
mod scene;
mod serde;
pub use crate::serde::*;
pub use component_registry::*;
pub use scene::*;

View file

@ -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<SceneEntity>,
}
#[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<DynamicProperties>,
}
#[derive(Default)]
pub struct Scene {
pub world: World,
}
pub struct SceneLoader {
component_registry: Arc<RwLock<ComponentRegistry>>,
}
impl FromResources for SceneLoader {
fn from_resources(resources: &Resources) -> Self {
let component_registry = resources
.get::<ComponentRegistryContext>()
.expect("SceneLoader requires the ComponentRegistry resource.");
SceneLoader {
component_registry: component_registry.value.clone(),
}
}
}
pub struct SceneLoader;
impl AssetLoader<Scene> for SceneLoader {
fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
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::<SceneEntity>::deserialize(&mut deserializer).unwrap();
Ok(Scene { entities })
}
fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["scn"];

View file

@ -1,6 +0,0 @@
mod scene_de;
mod scene_ser;
pub mod world;
pub use scene_de::*;
pub use scene_ser::*;

View file

@ -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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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<V>(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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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<V>(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::<String>()?);
}
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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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(())
}
}

View file

@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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()
}
}

View file

@ -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<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
let value = <T as Deserialize<'de>>::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<u8>, usize)>,
pub _marker: PhantomData<T>,
}
impl<'de, 'a, T: for<'b> Deserialize<'b> + 'static> DeserializeSeed<'de>
for ComponentSeqDeserializer<'a, T>
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
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<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
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::<IgnoredAny>()? {
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<String>,
component_types: Vec<String>,
}
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<S: Serializer>(
&self,
serializer: S,
archetype_desc: &ArchetypeDescription,
) -> Result<S::Ok, S::Error> {
let tags_to_serialize = archetype_desc
.tags()
.iter()
.map(|(tag_type_id, _)| tag_type_id.0.to_string())
.collect::<Vec<_>>();
let components_to_serialize = archetype_desc
.components()
.iter()
.map(|(component_type_id, _)| component_type_id.0.to_string())
.collect::<Vec<_>>();
SerializedArchetypeDescription {
tag_types: tags_to_serialize,
component_types: components_to_serialize,
}
.serialize(serializer)
}
fn serialize_components<S: Serializer>(
&self,
serializer: S,
component_type: &ComponentTypeId,
_component_meta: &ComponentMeta,
components: &ComponentResourceSet,
) -> Result<S::Ok, S::Error> {
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<S: Serializer>(
&self,
_serializer: S,
tag_type: &TagTypeId,
_tag_meta: &TagMeta,
_tags: &TagStorage,
) -> Result<S::Ok, S::Error> {
panic!(
"received unserializable type {:?}, this should be filtered by can_serialize",
tag_type
);
}
fn serialize_entities<S: Serializer>(
&self,
serializer: S,
entities: &[Entity],
) -> Result<S::Ok, S::Error> {
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<ArchetypeDescription, <D as Deserializer<'de>>::Error> {
let serialized_desc =
<SerializedArchetypeDescription as Deserialize>::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<u8>, usize)>,
) -> Result<(), <D as Deserializer<'de>>::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(<<D as serde::Deserializer<'de>>::Error as serde::de::Error>::custom)?;
} else {
<IgnoredAny>::deserialize(deserializer)?;
}
Ok(())
}
fn deserialize_tags<'de, D: Deserializer<'de>>(
&self,
deserializer: D,
_tag_type: &TagTypeId,
_tag_meta: &TagMeta,
_tags: &mut TagStorage,
) -> Result<(), <D as Deserializer<'de>>::Error> {
<IgnoredAny>::deserialize(deserializer)?;
Ok(())
}
fn deserialize_entities<'de, D: Deserializer<'de>>(
&self,
deserializer: D,
entity_allocator: &GuidEntityAllocator,
entities: &mut Vec<Entity>,
) -> Result<(), <D as Deserializer<'de>>::Error> {
let entity_indices = <Vec<EntityIndex> 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(())
}
}

View file

@ -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::<Test>()
.register_component::<Foo>()
// .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<A>,
}
#[derive(Serialize)]
struct A {
pub x: f32,
}
fn load_scene(world: &mut World, resources: &mut Resources) {
let asset_server = resources.get::<AssetServer>().unwrap();
let mut scenes = resources.get_mut::<Assets<Scene>>().unwrap();
let component_registry = resources.get::<ComponentRegistryContext>().unwrap();
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();
// 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::<ComponentRegistryContext>().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);
}

View file

@ -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::<usize>("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::<f32>("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::<usize>("a", 3);
patch.set::<usize>("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::<DynamicProperties>(&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);
}