props: migrate scenes to props. loading / saving worlds from / to props.
This commit is contained in:
parent
f36a67ee96
commit
4c306e6d48
@ -1,32 +1,26 @@
|
|||||||
[
|
[
|
||||||
(
|
(
|
||||||
entity: 2309003120,
|
entity: 3072676124,
|
||||||
components: [
|
components: [
|
||||||
(
|
{
|
||||||
type: "Test",
|
"type": "load_scene::Test",
|
||||||
data: (
|
"x": 3.0,
|
||||||
x: 3,
|
"y": 4.0,
|
||||||
y: 4,
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
type: "Foo",
|
|
||||||
data: (
|
|
||||||
value: "hi",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
entity: 4238063392,
|
entity: 3949176536,
|
||||||
components: [
|
components: [
|
||||||
(
|
{
|
||||||
type: "Test",
|
"type": "load_scene::Test",
|
||||||
data: (
|
"x": 1.0,
|
||||||
x: 3,
|
"y": 2.0,
|
||||||
y: 4,
|
},
|
||||||
),
|
{
|
||||||
),
|
"type": "load_scene::Foo",
|
||||||
|
"value": "hello",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{DynamicProperties, Property, PropertyVal};
|
use crate::{DynamicProperties, Property, PropertyVal};
|
||||||
use serde::{ser::SerializeMap, Serialize};
|
use serde::{ser::SerializeMap, Serialize};
|
||||||
|
|
||||||
pub trait Properties {
|
pub trait Properties: Property {
|
||||||
fn type_name(&self) -> &str;
|
fn type_name(&self) -> &str;
|
||||||
fn prop(&self, name: &str) -> Option<&dyn Property>;
|
fn prop(&self, name: &str) -> Option<&dyn Property>;
|
||||||
fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Property>;
|
fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Property>;
|
||||||
@ -63,11 +63,11 @@ impl<P> PropertiesVal for P
|
|||||||
where
|
where
|
||||||
P: Properties,
|
P: Properties,
|
||||||
{
|
{
|
||||||
// #[inline]
|
#[inline]
|
||||||
fn prop_val<T: 'static>(&self, name: &str) -> Option<&T> {
|
fn prop_val<T: 'static>(&self, name: &str) -> Option<&T> {
|
||||||
self.prop(name).and_then(|p| p.any().downcast_ref::<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) {
|
fn set_prop_val<T: 'static>(&mut self, name: &str, value: T) {
|
||||||
if let Some(prop) = self.prop_mut(name) {
|
if let Some(prop) = self.prop_mut(name) {
|
||||||
prop.set_val(value);
|
prop.set_val(value);
|
||||||
|
@ -12,5 +12,5 @@ legion = { path = "../bevy_legion", features = ["serialize"] }
|
|||||||
serde = { version = "1.0", features = ["derive"]}
|
serde = { version = "1.0", features = ["derive"]}
|
||||||
erased-serde = "0.3"
|
erased-serde = "0.3"
|
||||||
ron = { path = "../ron" }
|
ron = { path = "../ron" }
|
||||||
uuid = { version = "0.8", features = ["v4", "serde"] }
|
anyhow = "1.0"
|
||||||
anyhow = "1.0"
|
thiserror = "1.0"
|
@ -1,15 +1,17 @@
|
|||||||
use bevy_app::AppBuilder;
|
use bevy_app::AppBuilder;
|
||||||
|
use bevy_property::{Properties, Property};
|
||||||
use legion::{
|
use legion::{
|
||||||
prelude::{Entity, World},
|
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)]
|
#[derive(Default)]
|
||||||
pub struct ComponentRegistryContext {
|
pub struct ComponentRegistryContext {
|
||||||
pub value: Arc<RwLock<ComponentRegistry>>,
|
pub value: Arc<RwLock<ComponentRegistry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -22,7 +24,7 @@ pub struct ComponentRegistry {
|
|||||||
impl ComponentRegistry {
|
impl ComponentRegistry {
|
||||||
pub fn register<T>(&mut self)
|
pub fn register<T>(&mut self)
|
||||||
where
|
where
|
||||||
T: Clone + Send + Sync + 'static + Serialize + for<'de> Deserialize<'de>,
|
T: Properties + Component + Default,
|
||||||
{
|
{
|
||||||
let registration = ComponentRegistration::of::<T>();
|
let registration = ComponentRegistration::of::<T>();
|
||||||
self.short_names
|
self.short_names
|
||||||
@ -52,52 +54,24 @@ impl ComponentRegistry {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ComponentRegistration {
|
pub struct ComponentRegistration {
|
||||||
pub ty: ComponentTypeId,
|
pub ty: ComponentTypeId,
|
||||||
pub comp_serialize_fn: fn(&ComponentResourceSet, &mut dyn FnMut(&dyn erased_serde::Serialize)),
|
pub component_add_fn: fn(&mut World, Entity, &dyn Property),
|
||||||
pub individual_comp_serialize_fn:
|
pub component_properties_fn: fn(&ComponentResourceSet, usize) -> &dyn Properties,
|
||||||
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 short_name: &'static str,
|
pub short_name: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComponentRegistration {
|
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>();
|
let ty = ComponentTypeId::of::<T>();
|
||||||
Self {
|
Self {
|
||||||
ty,
|
ty,
|
||||||
comp_serialize_fn: |comp_storage, serialize_fn| {
|
component_add_fn: |world: &mut World, entity: Entity, property: &dyn Property| {
|
||||||
// it's safe because we know this is the correct type due to lookup
|
let mut component = T::default();
|
||||||
let slice = unsafe { comp_storage.data_slice::<T>() };
|
component.apply(property);
|
||||||
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)?;
|
|
||||||
world.add_component(entity, component).unwrap();
|
world.add_component(entity, component).unwrap();
|
||||||
Ok(())
|
|
||||||
},
|
},
|
||||||
register_comp_fn: |desc| {
|
component_properties_fn: |component_resource_set: &ComponentResourceSet, index: usize| {
|
||||||
desc.register_component::<T>();
|
// 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(),
|
short_name: ty.0.split("::").last().unwrap(),
|
||||||
}
|
}
|
||||||
@ -107,16 +81,19 @@ impl ComponentRegistration {
|
|||||||
pub trait RegisterComponent {
|
pub trait RegisterComponent {
|
||||||
fn register_component<T>(&mut self) -> &mut Self
|
fn register_component<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Clone + Send + Sync + 'static + Serialize + for<'de> Deserialize<'de>;
|
T: Properties + Component + Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegisterComponent for AppBuilder {
|
impl RegisterComponent for AppBuilder {
|
||||||
fn register_component<T>(&mut self) -> &mut Self
|
fn register_component<T>(&mut self) -> &mut Self
|
||||||
where
|
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>();
|
registry_context.value.write().unwrap().register::<T>();
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
mod component_registry;
|
mod component_registry;
|
||||||
mod scene;
|
mod scene;
|
||||||
mod serde;
|
|
||||||
pub use crate::serde::*;
|
|
||||||
pub use component_registry::*;
|
pub use component_registry::*;
|
||||||
pub use scene::*;
|
pub use scene::*;
|
||||||
|
|
||||||
|
@ -1,59 +1,104 @@
|
|||||||
use crate::{ComponentRegistry, ComponentRegistryContext, SceneDeserializer};
|
use crate::ComponentRegistry;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bevy_app::FromResources;
|
|
||||||
use bevy_asset::AssetLoader;
|
use bevy_asset::AssetLoader;
|
||||||
use bevy_property::DynamicProperties;
|
use bevy_property::DynamicProperties;
|
||||||
use legion::prelude::{Resources, World};
|
use legion::prelude::{Entity, World};
|
||||||
use serde::de::DeserializeSeed;
|
use serde::{Deserialize, Serialize};
|
||||||
use serde::{Serialize, Deserialize};
|
use std::{num::Wrapping, path::Path};
|
||||||
use std::{
|
use thiserror::Error;
|
||||||
path::Path,
|
|
||||||
sync::{Arc, RwLock},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct DynamicScene {
|
#[derive(Serialize, Deserialize, Default)]
|
||||||
|
pub struct Scene {
|
||||||
pub entities: Vec<SceneEntity>,
|
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)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct SceneEntity {
|
pub struct SceneEntity {
|
||||||
pub entity: u32,
|
pub entity: u32,
|
||||||
pub components: Vec<DynamicProperties>,
|
pub components: Vec<DynamicProperties>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Scene {
|
pub struct SceneLoader;
|
||||||
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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AssetLoader<Scene> for SceneLoader {
|
impl AssetLoader<Scene> for SceneLoader {
|
||||||
fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
|
fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
|
||||||
let mut deserializer = ron::de::Deserializer::from_bytes(&bytes).unwrap();
|
let mut deserializer = ron::de::Deserializer::from_bytes(&bytes).unwrap();
|
||||||
let mut scene = Scene::default();
|
let entities = Vec::<SceneEntity>::deserialize(&mut deserializer).unwrap();
|
||||||
let scene_deserializer = SceneDeserializer {
|
Ok(Scene { entities })
|
||||||
component_registry: &self.component_registry.read().unwrap(),
|
|
||||||
scene: &mut scene,
|
|
||||||
};
|
|
||||||
|
|
||||||
scene_deserializer.deserialize(&mut deserializer).unwrap();
|
|
||||||
|
|
||||||
Ok(scene)
|
|
||||||
}
|
}
|
||||||
fn extensions(&self) -> &[&str] {
|
fn extensions(&self) -> &[&str] {
|
||||||
static EXTENSIONS: &[&str] = &["scn"];
|
static EXTENSIONS: &[&str] = &["scn"];
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
mod scene_de;
|
|
||||||
mod scene_ser;
|
|
||||||
pub mod world;
|
|
||||||
|
|
||||||
pub use scene_de::*;
|
|
||||||
pub use scene_ser::*;
|
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +1,73 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use bevy_scene::ComponentRegistryContext;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::build()
|
App::build()
|
||||||
.add_default_plugins()
|
.add_default_plugins()
|
||||||
// Registering components informs Bevy that they exist. This allows them to be used when loading/saving scenes
|
// 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/save your components.
|
// This step is only required if you want to load your components from scene files.
|
||||||
.register_component::<Test>()
|
.register_component::<Test>()
|
||||||
.register_component::<Foo>()
|
.register_component::<Foo>()
|
||||||
// .add_startup_system(setup)
|
|
||||||
.add_startup_system(load_scene)
|
.add_startup_system(load_scene)
|
||||||
|
// .add_startup_system(serialize_scene)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Properties, Default)]
|
||||||
struct Test {
|
struct Test {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Properties, Default)]
|
||||||
struct Foo {
|
struct Foo {
|
||||||
pub value: String,
|
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 asset_server = resources.get::<AssetServer>().unwrap();
|
||||||
let mut scenes = resources.get_mut::<Assets<Scene>>().unwrap();
|
let mut scenes = resources.get_mut::<Assets<Scene>>().unwrap();
|
||||||
|
let component_registry = resources.get::<ComponentRegistryContext>().unwrap();
|
||||||
|
|
||||||
let scene_handle: Handle<Scene> = asset_server
|
let scene_handle: Handle<Scene> = asset_server
|
||||||
.load_sync(&mut scenes, "assets/scene/load_scene_example.scn")
|
.load_sync(&mut scenes, "assets/scene/load_scene_example.scn")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let _scene= scenes.get(&scene_handle).unwrap();
|
let scene= scenes.get(&scene_handle).unwrap();
|
||||||
// world.merge(scene)
|
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);
|
||||||
|
|
||||||
}
|
}
|
@ -1,9 +1,7 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
property::SerializableProperties,
|
property::SerializableProperties,
|
||||||
scene::{DynamicScene, SceneEntity},
|
|
||||||
};
|
};
|
||||||
use serde::{de::Deserialize, ser::Serialize};
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::build()
|
App::build()
|
||||||
@ -15,71 +13,53 @@ fn main() {
|
|||||||
#[derive(Properties, Default)]
|
#[derive(Properties, Default)]
|
||||||
pub struct Test {
|
pub struct Test {
|
||||||
a: usize,
|
a: usize,
|
||||||
b: String,
|
nested: Nested,
|
||||||
c: f32,
|
|
||||||
nest: Nested,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Properties, Default)]
|
#[derive(Properties, Default)]
|
||||||
pub struct Nested {
|
pub struct Nested {
|
||||||
d: usize,
|
b: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup() {
|
fn setup() {
|
||||||
let mut test = Test {
|
let mut test = Test {
|
||||||
a: 1,
|
a: 1,
|
||||||
b: "hi".to_string(),
|
nested: Nested {
|
||||||
c: 1.0,
|
b: 8,
|
||||||
nest: Nested {
|
|
||||||
d: 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);
|
test.set_prop_val::<usize>("a", 2);
|
||||||
assert_eq!(test.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;
|
let x: u32 = 3;
|
||||||
test.set_prop("a", &x);
|
test.set_prop("a", &x);
|
||||||
assert_eq!(test.a, 3);
|
assert_eq!(test.a, 3);
|
||||||
|
|
||||||
test.set_prop_val::<f32>("c", 2.0);
|
// DynamicProperties also implements the Properties trait.
|
||||||
let x: f64 = 3.0;
|
|
||||||
test.set_prop("c", &x);
|
|
||||||
assert_eq!(test.c, 3.0);
|
|
||||||
|
|
||||||
let mut patch = DynamicProperties::default();
|
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);
|
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 ser = SerializableProperties { props: &test };
|
||||||
let pretty_config = ron::ser::PrettyConfig::default().with_decimal_floats(true);
|
let pretty_config = ron::ser::PrettyConfig::default().with_decimal_floats(true);
|
||||||
|
|
||||||
let mut buf = Vec::new();
|
let ron_string = ron::ser::to_string_pretty(&ser, pretty_config.clone()).unwrap();
|
||||||
let mut serializer =
|
println!("{}\n", ron_string);
|
||||||
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 dynamic_scene = DynamicScene {
|
// Dynamic properties can be deserialized
|
||||||
// entities: vec![SceneEntity {
|
let dynamic_properties = ron::from_str::<DynamicProperties>(&ron_string).unwrap();
|
||||||
// entity: 12345,
|
let round_tripped = ron::ser::to_string_pretty(&dynamic_properties, pretty_config).unwrap();
|
||||||
// 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!();
|
|
||||||
println!("{}", round_tripped);
|
println!("{}", round_tripped);
|
||||||
assert_eq!(ron_string, 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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user