mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
props: remove specialization, ignore fields, impl for Handle, fix world round tripping
This commit is contained in:
parent
1cd3b4c987
commit
0826d74163
16 changed files with 768 additions and 330 deletions
|
@ -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",
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
}, ],
|
||||
),]
|
|
@ -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"
|
||||
|
|
|
@ -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>>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>>,
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(min_specialization)]
|
||||
|
||||
mod property;
|
||||
mod properties;
|
||||
mod dynamic_properties;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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: ®istry,
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
45
crates/bevy_scene/src/scene_loader.rs
Normal file
45
crates/bevy_scene/src/scene_loader.rs
Normal 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: ®istry,
|
||||
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
|
||||
}
|
||||
}
|
194
crates/bevy_scene/src/serde.rs
Normal file
194
crates/bevy_scene/src/serde.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue