props: remove specialization, ignore fields, impl for Handle, fix world round tripping

This commit is contained in:
Carter Anderson 2020-05-25 12:03:50 -07:00
parent 1cd3b4c987
commit 0826d74163
16 changed files with 768 additions and 330 deletions

View file

@ -1,26 +1,30 @@
[
(
entity: 1279729879,
Entity(
id: 1401014920,
components: [
{
"type": "load_scene::Test",
"x": 3.0,
"y": 4.0,
},
],
}, ],
),
(
entity: 1639302665,
Entity(
id: 99763910,
components: [
{
"type": "load_scene::Test",
"x": 1.0,
"y": 2.0,
},
{
"type": "bevy_asset::handle::Handle<bevy_render::mesh::Mesh>",
"id": HandleId("edcdd23f-5be5-4dbf-9a6e-9f46b2185570"),
},
{
"type": "load_scene::Foo",
"value": "hello",
},
],
),
]
}, ],
),]

View file

@ -11,9 +11,11 @@ filesystem_watcher = ["notify"]
[dependencies]
bevy_app = { path = "../bevy_app" }
bevy_core = { path = "../bevy_core" }
bevy_property = { path = "../bevy_property" }
legion = { path = "../bevy_legion" }
uuid = { version = "0.8", features = ["v4", "serde"] }
serde = { version = "1", features = ["derive"] }
crossbeam-channel = "0.4.2"
anyhow = "1.0"
thiserror = "1.0"

View file

@ -10,13 +10,13 @@ use std::{
path::{Path, PathBuf},
};
pub enum AssetEvent<T> {
pub enum AssetEvent<T: 'static> {
Created { handle: Handle<T> },
Modified { handle: Handle<T> },
Removed { handle: Handle<T> },
}
pub struct Assets<T> {
pub struct Assets<T: 'static> {
assets: HashMap<Handle<T>, T>,
paths: HashMap<PathBuf, Handle<T>>,
events: Events<AssetEvent<T>>,

View file

@ -4,9 +4,11 @@ use std::{
};
use std::{any::TypeId, marker::PhantomData};
use serde::{Serialize, Deserialize};
use uuid::Uuid;
use bevy_property::{Properties, Property, AsProperties};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct HandleId(pub Uuid);
pub const DEFAULT_HANDLE_ID: HandleId =
HandleId(Uuid::from_u128(240940089166493627844978703213080810552));
@ -17,8 +19,40 @@ impl HandleId {
}
}
pub struct Handle<T> {
impl Property for HandleId {
fn any(&self) -> &dyn std::any::Any {
self
}
fn any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = *prop;
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
}
impl AsProperties for HandleId {
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
#[derive(Properties)]
pub struct Handle<T> where T: 'static {
pub id: HandleId,
#[prop(ignore)]
marker: PhantomData<T>,
}
@ -137,6 +171,10 @@ impl<T> Clone for Handle<T> {
}
impl<T> Copy for Handle<T> {}
// SAFE: T is phantom data and Handle::id is an integer
unsafe impl<T> Send for Handle<T> {}
unsafe impl<T> Sync for Handle<T> {}
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
pub struct HandleUntyped {
pub id: HandleId,

View file

@ -20,6 +20,7 @@ pub trait AssetLoadRequestHandler: Send + Sync + 'static {
pub struct ChannelAssetHandler<TLoader, TAsset>
where
TLoader: AssetLoader<TAsset>,
TAsset: 'static,
{
sender: Sender<AssetResult<TAsset>>,
loader: TLoader,

View file

@ -30,13 +30,13 @@ pub trait AssetLoader<T>: Send + Sync + 'static {
}
}
pub struct AssetResult<T> {
pub struct AssetResult<T: 'static> {
pub result: Result<T, AssetLoadError>,
pub handle: Handle<T>,
pub path: PathBuf,
}
pub struct AssetChannel<T> {
pub struct AssetChannel<T: 'static> {
pub sender: Sender<AssetResult<T>>,
pub receiver: Receiver<AssetResult<T>>,
}

View file

@ -1,11 +1,11 @@
use crate::entity::Entity;
use parking_lot::RwLock;
use std::{collections::HashSet, num::Wrapping, sync::Arc};
use std::{collections::{VecDeque, HashSet}, num::Wrapping, sync::Arc};
#[derive(Default, Debug, Clone)]
pub struct GuidEntityAllocator {
entities: Arc<RwLock<HashSet<Entity>>>,
next_ids: Arc<RwLock<Vec<Entity>>>,
next_ids: Arc<RwLock<VecDeque<Entity>>>,
}
impl GuidEntityAllocator {
@ -18,7 +18,7 @@ impl GuidEntityAllocator {
/// Allocates a new unused `Entity` ID.
pub fn create_entity(&self) -> Entity {
let entity = if !self.next_ids.read().is_empty() {
self.next_ids.write().pop().unwrap()
self.next_ids.write().pop_front().unwrap()
} else {
Entity::new(rand::random::<u32>(), Wrapping(1))
};

View file

@ -2,10 +2,19 @@ extern crate proc_macro;
mod modules;
use darling::FromMeta;
use modules::{get_modules, get_path};
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields};
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields};
#[derive(FromMeta, Debug, Default)]
struct PropAttributeArgs {
#[darling(default)]
pub ignore: Option<bool>,
}
static PROP_ATTRIBUTE_NAME: &str = "prop";
#[proc_macro_derive(Properties, attributes(prop, module))]
pub fn derive_properties(input: TokenStream) -> TokenStream {
@ -17,19 +26,47 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
}) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
let fields_and_args = fields
.iter()
.map(|f| {
(
f,
f.attrs
.iter()
.find(|a| {
a.path.get_ident().as_ref().unwrap().to_string() == PROP_ATTRIBUTE_NAME
})
.map(|a| {
PropAttributeArgs::from_meta(&a.parse_meta().unwrap())
.unwrap_or_else(|_err| PropAttributeArgs::default())
}),
)
})
.collect::<Vec<(&Field, Option<PropAttributeArgs>)>>();
let active_fields = fields_and_args
.iter()
.filter(|(_field, attrs)| {
attrs.is_none()
|| match attrs.as_ref().unwrap().ignore {
Some(ignore) => !ignore,
None => true,
}
})
.map(|(f, _attr)| *f)
.collect::<Vec<&Field>>();
let modules = get_modules(&ast);
let bevy_property_path = get_path(&modules.bevy_property);
let field_names = fields
let field_names = active_fields
.iter()
.map(|field| field.ident.as_ref().unwrap().to_string())
.collect::<Vec<String>>();
let field_idents = fields
let field_idents = active_fields
.iter()
.map(|field| field.ident.as_ref().unwrap())
.collect::<Vec<_>>();
let field_count = fields.len();
let field_count = active_fields.len();
let field_indices = (0..field_count).collect::<Vec<usize>>();
let generics = ast.generics;

View file

@ -1,5 +1,3 @@
#![feature(min_specialization)]
mod property;
mod properties;
mod dynamic_properties;

View file

@ -1,5 +1,4 @@
use crate::Properties;
use serde::Serialize;
use std::any::Any;
pub trait Property: erased_serde::Serialize + Send + Sync + Any + AsProperties + 'static {
@ -23,12 +22,12 @@ pub trait PropertyVal {
impl PropertyVal for dyn Property {
#[inline]
default fn val<T: 'static>(&self) -> Option<&T> {
fn val<T: 'static>(&self) -> Option<&T> {
self.any().downcast_ref::<T>()
}
#[inline]
default fn set_val<T: 'static>(&mut self, value: T) {
fn set_val<T: 'static>(&mut self, value: T) {
if let Some(prop) = self.any_mut().downcast_mut::<T>() {
*prop = value;
} else {
@ -37,81 +36,83 @@ impl PropertyVal for dyn Property {
}
}
// TODO: remove specialization
impl<T> AsProperties for T
where
T: Clone + Serialize + Send + Sync + Any + 'static,
impl Property for usize {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = *prop;
} else if let Some(prop) = value.downcast_ref::<u64>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<u32>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<u16>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<u8>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<isize>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i64>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i32>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i16>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i8>() {
*self = *prop as Self;
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
}
impl AsProperties for usize
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl<T> Property for T
where
T: Clone + Serialize + Send + Sync + Any + 'static,
{
impl Property for u64 {
#[inline]
default fn any(&self) -> &dyn Any {
fn any(&self) -> &dyn Any {
self
}
#[inline]
default fn any_mut(&mut self) -> &mut dyn Any {
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
default fn clone_prop(&self) -> Box<dyn Property> {
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
default fn set(&mut self, value: &dyn Property) {
if let Some(prop) = value.any().downcast_ref::<T>() {
*self = prop.clone();
} else {
panic!("prop value is not {}", std::any::type_name::<T>());
}
}
#[inline]
default fn apply(&mut self, value: &dyn Property) {
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
}
impl Property for usize {
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = *prop;
} else if let Some(prop) = value.downcast_ref::<u64>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<u32>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<u16>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<u8>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<isize>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i64>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i32>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i16>() {
*self = *prop as Self;
} else if let Some(prop) = value.downcast_ref::<i8>() {
*self = *prop as Self;
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
}
impl Property for u64 {
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -140,7 +141,34 @@ impl Property for u64 {
}
}
impl AsProperties for u64
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for u32 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -169,7 +197,34 @@ impl Property for u32 {
}
}
impl AsProperties for u32
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for u16 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -198,7 +253,34 @@ impl Property for u16 {
}
}
impl AsProperties for u16
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for u8 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -227,7 +309,34 @@ impl Property for u8 {
}
}
impl AsProperties for u8
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for isize {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -256,7 +365,34 @@ impl Property for isize {
}
}
impl AsProperties for isize
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for i64 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -285,7 +421,34 @@ impl Property for i64 {
}
}
impl AsProperties for i64
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for i32 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -314,7 +477,34 @@ impl Property for i32 {
}
}
impl AsProperties for i32
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for i16 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -343,7 +533,34 @@ impl Property for i16 {
}
}
impl AsProperties for i16
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for i8 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -372,7 +589,34 @@ impl Property for i8 {
}
}
impl AsProperties for i8
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for f32 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -385,7 +629,34 @@ impl Property for f32 {
}
}
impl AsProperties for f32
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for f64 {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
@ -397,3 +668,46 @@ impl Property for f64 {
}
}
}
impl AsProperties for f64
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
impl Property for String {
#[inline]
fn any(&self) -> &dyn Any {
self
}
#[inline]
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
#[inline]
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = prop.clone();
}
}
}
impl AsProperties for String
{
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}

View file

@ -1,7 +1,11 @@
mod component_registry;
mod scene;
mod scene_loader;
pub mod serde;
pub use component_registry::*;
pub use scene::*;
pub use scene_loader::*;
use bevy_app::{AppBuilder, AppPlugin};
use bevy_asset::AddAsset;

View file

@ -1,25 +1,19 @@
use crate::{ComponentRegistry, PropertyTypeRegistryContext};
use crate::ComponentRegistry;
use anyhow::Result;
use bevy_app::FromResources;
use bevy_asset::AssetLoader;
use bevy_property::{DynamicProperties, PropertyTypeRegistry, DynamicPropertiesDeserializer};
use legion::prelude::{Entity, Resources, World};
use serde::{
de::{DeserializeSeed, SeqAccess, Visitor, MapAccess, Error},
Serialize,
Deserialize
};
use std::{cell::RefCell, num::Wrapping, path::Path, rc::Rc};
use bevy_property::DynamicProperties;
use legion::prelude::World;
use serde::Serialize;
use std::num::Wrapping;
use thiserror::Error;
#[derive(Default)]
pub struct Scene {
pub entities: Vec<SceneEntity>,
pub entities: Vec<Entity>,
}
#[derive(Serialize)]
pub struct SceneEntity {
pub entity: u32,
pub struct Entity {
pub id: u32,
pub components: Vec<DynamicProperties>,
}
@ -45,8 +39,8 @@ impl Scene {
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(),
entities.push(Entity {
id: entity.index(),
components: Vec::new(),
})
}
@ -77,7 +71,7 @@ impl Scene {
world.entity_allocator.push_next_ids(
self.entities
.iter()
.map(|e| Entity::new(e.entity, Wrapping(1))),
.map(|e| legion::prelude::Entity::new(e.id, Wrapping(1))),
);
for scene_entity in self.entities.iter() {
// TODO: use EntityEntry when legion refactor is finished
@ -95,223 +89,3 @@ impl Scene {
Ok(())
}
}
impl Serialize for Scene {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.entities.serialize(serializer)
}
}
pub struct SceneDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> DeserializeSeed<'de> for SceneDeserializer<'a> {
type Value = Scene;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut scene = Scene::default();
scene.entities = deserializer.deserialize_seq(SceneEntitySeqVisiter {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name,
})?;
Ok(scene)
}
}
struct SceneEntitySeqVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> Visitor<'de> for SceneEntitySeqVisiter<'a> {
type Value = Vec<SceneEntity>;
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>,
{
let mut entities = Vec::new();
while let Some(entity) = seq.next_element_seed(SceneEntityDeserializer {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name.clone(),
})? {
entities.push(entity);
}
Ok(entities)
}
}
pub struct SceneEntityDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> {
type Value = SceneEntity;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_struct("", &["entity", "components"], SceneEntityVisiter {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name,
})
}
}
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum EntityField {
Entity,
Components,
}
pub const ENTITY_FIELD_ENTITY: &str = "entity";
pub const ENTITY_FIELD_COMPONENTS: &str = "components";
struct SceneEntityVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> {
type Value = SceneEntity;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("entities")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where A: MapAccess<'de> {
let mut entity = None;
let mut components = None;
while let Some(key) = map.next_key()? {
match key {
EntityField::Entity => {
if entity.is_some() {
return Err(Error::duplicate_field(ENTITY_FIELD_ENTITY));
}
entity = Some(map.next_value::<u32>()?);
}
EntityField::Components => {
if components.is_some() {
return Err(Error::duplicate_field(ENTITY_FIELD_COMPONENTS));
}
components = Some(map.next_value_seed(ComponentVecDeserializer {
current_type_name: self.current_type_name.clone(),
property_type_registry: self.property_type_registry
})?);
}
}
}
let entity = entity
.as_ref()
.ok_or_else(|| Error::missing_field(ENTITY_FIELD_ENTITY))?;
let components = components
.take()
.ok_or_else(|| Error::missing_field(ENTITY_FIELD_COMPONENTS))?;
Ok(SceneEntity {
entity: *entity,
components,
})
}
}
pub struct ComponentVecDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> DeserializeSeed<'de> for ComponentVecDeserializer<'a> {
type Value = Vec<DynamicProperties>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(ComponentSeqVisiter {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name,
})
}
}
struct ComponentSeqVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> Visitor<'de> for ComponentSeqVisiter<'a> {
type Value = Vec<DynamicProperties>;
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>,
{
let mut dynamic_properties = Vec::new();
while let Some(entity) = seq.next_element_seed(DynamicPropertiesDeserializer {
current_type_name: self.current_type_name.clone(),
property_type_registry: self.property_type_registry
})? {
dynamic_properties.push(entity);
}
Ok(dynamic_properties)
}
}
pub struct SceneLoader {
property_type_registry: PropertyTypeRegistryContext,
}
impl FromResources for SceneLoader {
fn from_resources(resources: &Resources) -> Self {
let property_type_registry = resources.get::<PropertyTypeRegistryContext>().unwrap();
SceneLoader {
property_type_registry: property_type_registry.clone(),
}
}
}
impl AssetLoader<Scene> for SceneLoader {
fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
let registry = self.property_type_registry.value.read().unwrap();
let mut deserializer = ron::de::Deserializer::from_bytes(&bytes).unwrap();
let current_type_name = Rc::new(RefCell::new(None));
let scene_deserializer = SceneDeserializer {
property_type_registry: &registry,
current_type_name: current_type_name.clone(),
};
let mut callback = |ident: &Option<&[u8]>| {
let mut last_type_name = current_type_name.borrow_mut();
*last_type_name = ident.map(|i| String::from_utf8(i.to_vec()).unwrap());
};
deserializer.set_callback(&mut callback);
let scene = scene_deserializer.deserialize(&mut deserializer).unwrap();
Ok(scene)
}
fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["scn"];
EXTENSIONS
}
}

View file

@ -0,0 +1,45 @@
use crate::{serde::SceneDeserializer, PropertyTypeRegistryContext, Scene};
use anyhow::Result;
use bevy_app::FromResources;
use bevy_asset::AssetLoader;
use legion::prelude::Resources;
use serde::de::DeserializeSeed;
use std::{cell::RefCell, path::Path, rc::Rc};
pub struct SceneLoader {
property_type_registry: PropertyTypeRegistryContext,
}
impl FromResources for SceneLoader {
fn from_resources(resources: &Resources) -> Self {
let property_type_registry = resources.get::<PropertyTypeRegistryContext>().unwrap();
SceneLoader {
property_type_registry: property_type_registry.clone(),
}
}
}
impl AssetLoader<Scene> for SceneLoader {
fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
let registry = self.property_type_registry.value.read().unwrap();
let mut deserializer = ron::de::Deserializer::from_bytes(&bytes).unwrap();
let current_type_name = Rc::new(RefCell::new(None));
let scene_deserializer = SceneDeserializer {
property_type_registry: &registry,
current_type_name: current_type_name.clone(),
};
// this callback is executed whenever an explicit type name is encountered in a map
let mut callback = |ident: &Option<&[u8]>| {
let mut last_type_name = current_type_name.borrow_mut();
*last_type_name = ident.map(|i| String::from_utf8(i.to_vec()).unwrap());
};
deserializer.set_callback(&mut callback);
let scene = scene_deserializer.deserialize(&mut deserializer).unwrap();
Ok(scene)
}
fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["scn"];
EXTENSIONS
}
}

View file

@ -0,0 +1,194 @@
use crate::{Entity, Scene};
use anyhow::Result;
use bevy_property::{DynamicProperties, DynamicPropertiesDeserializer, PropertyTypeRegistry};
use serde::{
de::{DeserializeSeed, Error, MapAccess, SeqAccess, Visitor},
Deserialize, Serialize,
};
use std::{cell::RefCell, rc::Rc};
impl Serialize for Scene {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.entities.serialize(serializer)
}
}
pub struct SceneDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> DeserializeSeed<'de> for SceneDeserializer<'a> {
type Value = Scene;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut scene = Scene::default();
scene.entities = deserializer.deserialize_seq(SceneEntitySeqVisiter {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name,
})?;
Ok(scene)
}
}
struct SceneEntitySeqVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> Visitor<'de> for SceneEntitySeqVisiter<'a> {
type Value = Vec<Entity>;
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>,
{
let mut entities = Vec::new();
while let Some(entity) = seq.next_element_seed(SceneEntityDeserializer {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name.clone(),
})? {
entities.push(entity);
}
Ok(entities)
}
}
pub struct SceneEntityDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> DeserializeSeed<'de> for SceneEntityDeserializer<'a> {
type Value = Entity;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_struct(
"Entity",
&["id", "components"],
SceneEntityVisiter {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name,
},
)
}
}
#[derive(Deserialize)]
#[serde(field_identifier, rename_all = "lowercase")]
enum EntityField {
Id,
Components,
}
pub const ENTITY_FIELD_ID: &str = "id";
pub const ENTITY_FIELD_COMPONENTS: &str = "components";
struct SceneEntityVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> Visitor<'de> for SceneEntityVisiter<'a> {
type Value = Entity;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("entities")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut id = None;
let mut components = None;
while let Some(key) = map.next_key()? {
match key {
EntityField::Id => {
if id.is_some() {
return Err(Error::duplicate_field(ENTITY_FIELD_ID));
}
id = Some(map.next_value::<u32>()?);
}
EntityField::Components => {
if components.is_some() {
return Err(Error::duplicate_field(ENTITY_FIELD_COMPONENTS));
}
components = Some(map.next_value_seed(ComponentVecDeserializer {
current_type_name: self.current_type_name.clone(),
property_type_registry: self.property_type_registry,
})?);
}
}
}
let entity = id
.as_ref()
.ok_or_else(|| Error::missing_field(ENTITY_FIELD_ID))?;
let components = components
.take()
.ok_or_else(|| Error::missing_field(ENTITY_FIELD_COMPONENTS))?;
Ok(Entity {
id: *entity,
components,
})
}
}
pub struct ComponentVecDeserializer<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> DeserializeSeed<'de> for ComponentVecDeserializer<'a> {
type Value = Vec<DynamicProperties>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(ComponentSeqVisiter {
property_type_registry: self.property_type_registry,
current_type_name: self.current_type_name,
})
}
}
struct ComponentSeqVisiter<'a> {
pub property_type_registry: &'a PropertyTypeRegistry,
pub current_type_name: Rc<RefCell<Option<String>>>,
}
impl<'a, 'de> Visitor<'de> for ComponentSeqVisiter<'a> {
type Value = Vec<DynamicProperties>;
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>,
{
let mut dynamic_properties = Vec::new();
while let Some(entity) = seq.next_element_seed(DynamicPropertiesDeserializer {
current_type_name: self.current_type_name.clone(),
property_type_registry: self.property_type_registry,
})? {
dynamic_properties.push(entity);
}
Ok(dynamic_properties)
}
}

View file

@ -1,14 +1,18 @@
use bevy::prelude::*;
use bevy_scene::ComponentRegistryContext;
use serde::Serialize;
use bevy_asset::HandleId;
fn main() {
App::build()
.add_default_plugins()
// 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.
// In the future registered components will also be usable from the Bevy editor.
.register_component::<Test>()
.register_component::<Foo>()
.register_component::<Handle<Mesh>>()
.register_property_type::<HandleId>()
.add_startup_system(load_scene)
// .add_startup_system(serialize_scene)
.run();
@ -25,16 +29,6 @@ struct Foo {
pub value: String,
}
#[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();
@ -56,6 +50,7 @@ fn serialize_scene(world: &mut World, resources: &mut Resources) {
x: 1.0,
y: 2.0,
})
.add(Handle::<Mesh>::new())
.add(Foo {
value: "hello".to_string()
})
@ -67,6 +62,9 @@ fn serialize_scene(world: &mut World, resources: &mut Resources) {
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();
let mut buf = Vec::new();
let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), true).unwrap();
scene.serialize(&mut serializer).unwrap();
let ron_string = String::from_utf8(buf).unwrap();
println!("{}", ron_string);
}

View file

@ -1,5 +1,5 @@
use bevy::prelude::*;
use bevy_property::ron::deserialize_dynamic_properties;
use bevy_property::{AsProperties, ron::deserialize_dynamic_properties};
use bevy_scene::PropertyTypeRegistryContext;
use serde::{Deserialize, Serialize};
@ -29,6 +29,35 @@ pub struct CustomProperty {
a: usize,
}
impl Property for CustomProperty {
fn any(&self) -> &dyn std::any::Any {
self
}
fn any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn clone_prop(&self) -> Box<dyn Property> {
Box::new(self.clone())
}
fn set(&mut self, value: &dyn Property) {
let value = value.any();
if let Some(prop) = value.downcast_ref::<Self>() {
*self = prop.clone();
} else {
panic!("prop value is not {}", std::any::type_name::<Self>());
}
}
fn apply(&mut self, value: &dyn Property) {
self.set(value);
}
}
impl AsProperties for CustomProperty {
fn as_properties(&self) -> Option<&dyn Properties> {
None
}
}
fn setup(property_type_registry: Res<PropertyTypeRegistryContext>) {
let mut test = Test {
a: 1,