diff --git a/crates/bevy_props/src/dynamic_properties.rs b/crates/bevy_props/src/dynamic_properties.rs new file mode 100644 index 0000000000..88b9febd6a --- /dev/null +++ b/crates/bevy_props/src/dynamic_properties.rs @@ -0,0 +1,108 @@ +use std::{collections::HashMap, borrow::Cow}; +use crate::{Props, Prop, PropIter}; +use serde::{Deserialize, Serialize, ser::SerializeMap}; + +#[derive(Default)] +pub struct DynamicProperties { + pub type_name: &'static str, + pub props: Vec<(Cow<'static, str>, Box)>, + pub prop_indices: HashMap, usize>, +} + + +impl DynamicProperties { + fn push(&mut self, name: &str, prop: Box) { + let name: Cow<'static, str> = Cow::Owned(name.to_string()); + self.props.push((name.clone(), prop)); + self.prop_indices.insert(name, self.props.len()); + } + pub fn set(&mut self, name: &str, prop: T) { + if let Some(index) = self.prop_indices.get(name) { + self.props[*index].1 = Box::new(prop); + } else { + self.push(name, Box::new(prop)); + } + } + pub fn set_box(&mut self, name: &str, prop: Box) { + if let Some(index) = self.prop_indices.get(name) { + self.props[*index].1 = prop; + } else { + self.push(name, prop); + } + } +} + + +impl Props for DynamicProperties { + #[inline] + fn type_name(&self) -> &str { + self.type_name + } + #[inline] + fn prop(&self, name: &str) -> Option<&dyn Prop> { + if let Some(index) = self.prop_indices.get(name) { + Some(&*self.props[*index].1) + } else { + None + } + } + + #[inline] + fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Prop> { + if let Some(index) = self.prop_indices.get(name) { + Some(&mut *self.props[*index].1) + } else { + None + } + } + + #[inline] + fn prop_with_index(&self, index: usize) -> Option<&dyn Prop> { + self.props.get(index).map(|(_i, prop)| &**prop) + } + + #[inline] + fn prop_with_index_mut(&mut self, index: usize) -> Option<&mut dyn Prop> { + self.props.get_mut(index).map(|(_i, prop)| &mut **prop) + } + + #[inline] + fn prop_name(&self, index: usize) -> Option<&str> { + self.props.get(index).map(|(name, _)| name.as_ref()) + } + + #[inline] + fn prop_len(&self) -> usize { + self.props.len() + } + + fn iter_props(&self) -> PropIter { + PropIter { + props: self, + index: 0, + } + } +} + +impl Serialize for DynamicProperties { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_map(Some(self.props.len()))?; + state.serialize_entry("type", self.type_name())?; + for (name, prop) in self.iter_props() { + state.serialize_entry(name, prop)?; + } + state.end() + } +} + +impl<'a> Deserialize<'a> for DynamicProperties { + fn deserialize(_deserializer: D) -> Result + where + D: serde::Deserializer<'a>, + { + Ok(DynamicProperties::default()) + } +} \ No newline at end of file diff --git a/crates/bevy_props/src/lib.rs b/crates/bevy_props/src/lib.rs index 0c8a292ea6..918aa5427a 100644 --- a/crates/bevy_props/src/lib.rs +++ b/crates/bevy_props/src/lib.rs @@ -1,255 +1,9 @@ -use serde::{ser::SerializeMap, Deserialize, Serialize}; -use std::{any::Any, collections::HashMap, borrow::Cow}; +#![feature(min_specialization)] -pub struct DynamicScene { - pub entities: Vec, -} +mod prop; +mod props; +mod dynamic_properties; -#[derive(Serialize, Deserialize)] -pub struct SceneEntity { - pub entity: u32, - pub components: Vec, -} - -#[derive(Default)] -pub struct DynamicProperties { - pub type_name: &'static str, - pub props: Vec<(Cow<'static, str>, Box)>, - pub prop_indices: HashMap, usize>, -} - -pub struct SerializableProps<'a> { - pub props: &'a dyn Props, -} - -impl DynamicProperties { - fn push(&mut self, name: &str, prop: Box) { - let name: Cow<'static, str> = Cow::Owned(name.to_string()); - self.props.push((name.clone(), prop)); - self.prop_indices.insert(name, self.props.len()); - } - pub fn set(&mut self, name: &str, prop: T) { - if let Some(index) = self.prop_indices.get(name) { - self.props[*index].1 = Box::new(prop); - } else { - self.push(name, Box::new(prop)); - } - } - pub fn set_box(&mut self, name: &str, prop: Box) { - if let Some(index) = self.prop_indices.get(name) { - self.props[*index].1 = prop; - } else { - self.push(name, prop); - } - } -} - -impl Props for DynamicProperties { - fn type_name(&self) -> &str { - self.type_name - } - fn prop(&self, name: &str) -> Option<&dyn Prop> { - if let Some(index) = self.prop_indices.get(name) { - Some(&*self.props[*index].1) - } else { - None - } - } - - fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Prop> { - if let Some(index) = self.prop_indices.get(name) { - Some(&mut *self.props[*index].1) - } else { - None - } - } - - fn prop_with_index(&self, index: usize) -> Option<&dyn Prop> { - self.props.get(index).map(|(_i, prop)| &**prop) - } - - fn prop_with_index_mut(&mut self, index: usize) -> Option<&mut dyn Prop> { - self.props.get_mut(index).map(|(_i, prop)| &mut **prop) - } - - fn prop_name(&self, index: usize) -> Option<&str> { - self.props.get(index).map(|(name, _)| name.as_ref()) - } - - fn prop_len(&self) -> usize { - self.props.len() - } - - fn iter_props(&self) -> PropIter { - PropIter { - props: self, - index: 0, - } - } -} - -impl Serialize for DynamicProperties { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(self.props.len()))?; - state.serialize_entry("type", self.type_name())?; - for (name, prop) in self.iter_props() { - state.serialize_entry(name, prop)?; - } - state.end() - } -} - -impl<'a> Serialize for SerializableProps<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut state = serializer.serialize_map(Some(self.props.prop_len()))?; - state.serialize_entry("type", self.props.type_name())?; - for (name, prop) in self.props.iter_props() { - state.serialize_entry(name, prop)?; - } - state.end() - } -} - -pub trait Props { - fn type_name(&self) -> &str; - fn prop(&self, name: &str) -> Option<&dyn Prop>; - fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Prop>; - fn prop_with_index(&self, index: usize) -> Option<&dyn Prop>; - fn prop_with_index_mut(&mut self, index: usize) -> Option<&mut dyn Prop>; - fn prop_name(&self, index: usize) -> Option<&str>; - fn prop_len(&self) -> usize; - fn iter_props(&self) -> PropIter; - fn apply(&mut self, props: &dyn Props) { - for (name, prop) in props.iter_props() { - self.prop_mut(name).unwrap().set_val_dyn(prop); - } - } - fn to_dynamic(&self) -> DynamicProperties where Self: 'static { - let mut dynamic_props = DynamicProperties::default(); - for (name, prop) in self.iter_props() { - dynamic_props.set_box(name, prop.clone_prop()); - } - - dynamic_props.type_name = std::any::type_name::(); - dynamic_props - } -} - -pub struct PropIter<'a> { - props: &'a dyn Props, - index: usize, -} - -impl<'a> PropIter<'a> { - pub fn new(props: &'a dyn Props) -> Self { - PropIter { - props, - index: 0, - } - } -} - -impl<'a> Iterator for PropIter<'a> { - type Item = (&'a str, &'a dyn Prop); - fn next(&mut self) -> Option { - if self.index < self.props.prop_len() { - let prop = self.props.prop_with_index(self.index).unwrap(); - let name = self.props.prop_name(self.index).unwrap(); - self.index += 1; - Some((name, prop)) - } else { - None - } - } -} - -pub trait Prop: erased_serde::Serialize + Send + Sync + Any + 'static { - fn any(&self) -> &dyn Any; - fn any_mut(&mut self) -> &mut dyn Any; - fn clone_prop(&self) -> Box; - fn set_val_dyn(&mut self, value: &dyn Prop); -} - -erased_serde::serialize_trait_object!(Prop); - -pub trait PropVal { - fn val(&self) -> Option<&T>; - fn set_val(&mut self, value: T); -} - -pub trait PropsVal { - fn prop_val(&self, name: &str) -> Option<&T>; - fn set_prop_val(&mut self, name: &str, value: T); - fn set_prop_val_dyn(&mut self, name: &str, value: &dyn Prop); -} - - -impl PropVal for dyn Prop { - fn val(&self) -> Option<&T> { - self.any().downcast_ref::() - } - fn set_val(&mut self, value: T) { - if let Some(prop) = self.any_mut().downcast_mut::() { - *prop = value; - } else { - panic!("prop value is not {}", std::any::type_name::()); - } - } -} - -impl

PropsVal for P where P: Props { - fn prop_val(&self, name: &str) -> Option<&T> { - self.prop(name).and_then(|p| p.any().downcast_ref::()) - } - fn set_prop_val(&mut self, name: &str, value: T) { - if let Some(prop) = self.prop_mut(name).and_then(|p| p.any_mut().downcast_mut::()) { - *prop = value; - } else { - panic!("prop does not exist or is incorrect type: {}", name); - } - } - fn set_prop_val_dyn(&mut self, name: &str, value: &dyn Prop) { - if let Some(prop) = self.prop_mut(name) { - prop.set_val_dyn(value); - } else { - panic!("prop does not exist: {}", name); - } - } -} - -impl<'a> Deserialize<'a> for DynamicProperties { - fn deserialize(_deserializer: D) -> Result - where - D: serde::Deserializer<'a>, - { - Ok(DynamicProperties::default()) - } -} - -impl Prop for T -where - T: Clone + Serialize + Send + Sync + Any + 'static, -{ - fn any(&self) -> &dyn Any { - self - } - fn any_mut(&mut self) -> &mut dyn Any { - self - } - fn clone_prop(&self) -> Box { - Box::new(self.clone()) - } - fn set_val_dyn(&mut self, value: &dyn Prop) { - if let Some(prop) = value.any().downcast_ref::() { - *self = prop.clone(); - } else { - panic!("prop value is not {}", std::any::type_name::()); - } - } -} +pub use prop::*; +pub use props::*; +pub use dynamic_properties::*; \ No newline at end of file diff --git a/crates/bevy_props/src/prop.rs b/crates/bevy_props/src/prop.rs new file mode 100644 index 0000000000..db0318007a --- /dev/null +++ b/crates/bevy_props/src/prop.rs @@ -0,0 +1,375 @@ +use serde::Serialize; +use std::any::Any; + +pub trait Prop: erased_serde::Serialize + Send + Sync + Any + 'static { + fn any(&self) -> &dyn Any; + fn any_mut(&mut self) -> &mut dyn Any; + fn clone_prop(&self) -> Box; + fn set(&mut self, value: &dyn Prop); +} + +erased_serde::serialize_trait_object!(Prop); + +pub trait PropVal { + fn val(&self) -> Option<&T>; + fn set_val(&mut self, value: T); +} + +impl PropVal for dyn Prop { + // #[inline] + default fn val(&self) -> Option<&T> { + self.any().downcast_ref::() + } + + // #[inline] + default fn set_val(&mut self, value: T) { + if let Some(prop) = self.any_mut().downcast_mut::() { + *prop = value; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for T +where + T: Clone + Serialize + Send + Sync + Any + 'static, +{ + #[inline] + default fn any(&self) -> &dyn Any { + self + } + #[inline] + default fn any_mut(&mut self) -> &mut dyn Any { + self + } + #[inline] + default fn clone_prop(&self) -> Box { + Box::new(self.clone()) + } + #[inline] + default fn set(&mut self, value: &dyn Prop) { + if let Some(prop) = value.any().downcast_ref::() { + *self = prop.clone(); + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for usize { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for u64 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for u32 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for u16 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for u8 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for isize { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for i64 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for i32 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for i16 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for i8 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + + +impl Prop for f32 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} + +impl Prop for f64 { + fn set(&mut self, value: &dyn Prop) { + let value = value.any(); + if let Some(prop) = value.downcast_ref::() { + *self = *prop; + } else if let Some(prop) = value.downcast_ref::() { + *self = *prop as Self; + } else { + panic!("prop value is not {}", std::any::type_name::()); + } + } +} \ No newline at end of file diff --git a/crates/bevy_props/src/props.rs b/crates/bevy_props/src/props.rs new file mode 100644 index 0000000000..f2ae2cf400 --- /dev/null +++ b/crates/bevy_props/src/props.rs @@ -0,0 +1,103 @@ +use crate::{DynamicProperties, Prop, PropVal}; +use serde::{ser::SerializeMap, Serialize}; + +pub trait Props { + fn type_name(&self) -> &str; + fn prop(&self, name: &str) -> Option<&dyn Prop>; + fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Prop>; + fn prop_with_index(&self, index: usize) -> Option<&dyn Prop>; + fn prop_with_index_mut(&mut self, index: usize) -> Option<&mut dyn Prop>; + fn prop_name(&self, index: usize) -> Option<&str>; + fn prop_len(&self) -> usize; + fn iter_props(&self) -> PropIter; + fn set_prop(&mut self, name: &str, value: &dyn Prop) { + if let Some(prop) = self.prop_mut(name) { + prop.set(value); + } else { + panic!("prop does not exist: {}", name); + } + } + fn apply(&mut self, props: &dyn Props) { + for (name, prop) in props.iter_props() { + self.set_prop(name, prop); + } + } + fn to_dynamic(&self) -> DynamicProperties + where + Self: 'static, + { + let mut dynamic_props = DynamicProperties::default(); + for (name, prop) in self.iter_props() { + dynamic_props.set_box(name, prop.clone_prop()); + } + + dynamic_props.type_name = std::any::type_name::(); + dynamic_props + } +} + +pub struct PropIter<'a> { + pub(crate) props: &'a dyn Props, + pub(crate) index: usize, +} + +impl<'a> PropIter<'a> { + pub fn new(props: &'a dyn Props) -> Self { + PropIter { props, index: 0 } + } +} + +impl<'a> Iterator for PropIter<'a> { + type Item = (&'a str, &'a dyn Prop); + fn next(&mut self) -> Option { + if self.index < self.props.prop_len() { + let prop = self.props.prop_with_index(self.index).unwrap(); + let name = self.props.prop_name(self.index).unwrap(); + self.index += 1; + Some((name, prop)) + } else { + None + } + } +} + +pub trait PropsVal { + fn prop_val(&self, name: &str) -> Option<&T>; + fn set_prop_val(&mut self, name: &str, value: T); +} + +impl

PropsVal for P +where + P: Props, +{ + // #[inline] + fn prop_val(&self, name: &str) -> Option<&T> { + self.prop(name).and_then(|p| p.any().downcast_ref::()) + } + // #[inline] + fn set_prop_val(&mut self, name: &str, value: T) { + if let Some(prop) = self.prop_mut(name) { + prop.set_val(value); + } else { + panic!("prop does not exist or is incorrect type: {}", name); + } + } +} + +pub struct SerializableProps<'a> { + pub props: &'a dyn Props, +} + +impl<'a> Serialize for SerializableProps<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut state = serializer.serialize_map(Some(self.props.prop_len()))?; + state.serialize_entry("type", self.props.type_name())?; + for (name, prop) in self.props.iter_props() { + state.serialize_entry(name, prop)?; + } + state.end() + } +} \ No newline at end of file diff --git a/crates/bevy_scene/Cargo.toml b/crates/bevy_scene/Cargo.toml index b477675814..4f3fb3df29 100644 --- a/crates/bevy_scene/Cargo.toml +++ b/crates/bevy_scene/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] bevy_app = { path = "../bevy_app" } bevy_asset = { path = "../bevy_asset" } +bevy_props = { path = "../bevy_props" } legion = { path = "../bevy_legion", features = ["serialize"] } serde = { version = "1.0", features = ["derive"]} erased-serde = "0.3" diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 48cb462809..828c8140d4 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -2,13 +2,26 @@ use crate::{ComponentRegistry, ComponentRegistryContext, SceneDeserializer}; use anyhow::Result; use bevy_app::FromResources; use bevy_asset::AssetLoader; +use bevy_props::DynamicProperties; use legion::prelude::{Resources, World}; use serde::de::DeserializeSeed; +use serde::{Serialize, Deserialize}; use std::{ path::Path, sync::{Arc, RwLock}, }; +pub struct DynamicScene { + pub entities: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct SceneEntity { + pub entity: u32, + pub components: Vec, +} + + #[derive(Default)] pub struct Scene { pub world: World, diff --git a/examples/scene/props.rs b/examples/scene/props.rs index 3e75f10e6a..be18e63ebd 100644 --- a/examples/scene/props.rs +++ b/examples/scene/props.rs @@ -1,5 +1,6 @@ use bevy::prelude::*; -use bevy_props::{DynamicScene, SerializableProps, SceneEntity}; +use bevy_props::SerializableProps; +use bevy_scene::{DynamicScene, SceneEntity}; use serde::ser::Serialize; fn main() { @@ -13,16 +14,26 @@ fn main() { pub struct Test { a: usize, b: String, + c: f32, } fn setup() { let mut test = Test { a: 1, b: "hi".to_string(), + c: 1.0, }; test.set_prop_val::("a", 2); assert_eq!(test.a, 2); + let x: u32 = 3; + test.set_prop("a", &x); + assert_eq!(test.a, 3); + + test.set_prop_val::("c", 2.0); + let x: f64 = 3.0; + test.set_prop("c", &x); + assert_eq!(test.c, 3.0); let mut patch = DynamicProperties::default(); patch.set::("a", 3); @@ -30,26 +41,19 @@ fn setup() { assert_eq!(test.a, 3); - - let ser = SerializableProps { - props: &test, - }; + let ser = SerializableProps { props: &test }; let mut serializer = ron::ser::Serializer::new(Some(ron::ser::PrettyConfig::default()), false); ser.serialize(&mut serializer).unwrap(); println!("{}", serializer.into_output_string()); let dynamic_scene = DynamicScene { - entities: vec![ - SceneEntity { - entity: 12345, - components: vec![ - patch - ] - } - ] + entities: vec![SceneEntity { + entity: 12345, + components: vec![patch], + }], }; - + let mut serializer = ron::ser::Serializer::new(Some(ron::ser::PrettyConfig::default()), false); dynamic_scene.entities.serialize(&mut serializer).unwrap(); println!("{}", serializer.into_output_string());