props: dynamic casting. reorganize
This commit is contained in:
parent
da8daa051b
commit
e514bd14fe
108
crates/bevy_props/src/dynamic_properties.rs
Normal file
108
crates/bevy_props/src/dynamic_properties.rs
Normal file
@ -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<dyn Prop>)>,
|
||||||
|
pub prop_indices: HashMap<Cow<'static, str>, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl DynamicProperties {
|
||||||
|
fn push(&mut self, name: &str, prop: Box<dyn Prop>) {
|
||||||
|
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<T: Prop>(&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<dyn Prop>) {
|
||||||
|
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
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<D>(_deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'a>,
|
||||||
|
{
|
||||||
|
Ok(DynamicProperties::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,255 +1,9 @@
|
|||||||
use serde::{ser::SerializeMap, Deserialize, Serialize};
|
#![feature(min_specialization)]
|
||||||
use std::{any::Any, collections::HashMap, borrow::Cow};
|
|
||||||
|
|
||||||
pub struct DynamicScene {
|
mod prop;
|
||||||
pub entities: Vec<SceneEntity>,
|
mod props;
|
||||||
}
|
mod dynamic_properties;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
pub use prop::*;
|
||||||
pub struct SceneEntity {
|
pub use props::*;
|
||||||
pub entity: u32,
|
pub use dynamic_properties::*;
|
||||||
pub components: Vec<DynamicProperties>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct DynamicProperties {
|
|
||||||
pub type_name: &'static str,
|
|
||||||
pub props: Vec<(Cow<'static, str>, Box<dyn Prop>)>,
|
|
||||||
pub prop_indices: HashMap<Cow<'static, str>, usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SerializableProps<'a> {
|
|
||||||
pub props: &'a dyn Props,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DynamicProperties {
|
|
||||||
fn push(&mut self, name: &str, prop: Box<dyn Prop>) {
|
|
||||||
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<T: Prop>(&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<dyn Prop>) {
|
|
||||||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
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::<Self>();
|
|
||||||
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<Self::Item> {
|
|
||||||
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<dyn Prop>;
|
|
||||||
fn set_val_dyn(&mut self, value: &dyn Prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
erased_serde::serialize_trait_object!(Prop);
|
|
||||||
|
|
||||||
pub trait PropVal {
|
|
||||||
fn val<T: 'static>(&self) -> Option<&T>;
|
|
||||||
fn set_val<T: 'static>(&mut self, value: T);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PropsVal {
|
|
||||||
fn prop_val<T: 'static>(&self, name: &str) -> Option<&T>;
|
|
||||||
fn set_prop_val<T: 'static>(&mut self, name: &str, value: T);
|
|
||||||
fn set_prop_val_dyn<T: 'static>(&mut self, name: &str, value: &dyn Prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl PropVal for dyn Prop {
|
|
||||||
fn val<T: 'static>(&self) -> Option<&T> {
|
|
||||||
self.any().downcast_ref::<T>()
|
|
||||||
}
|
|
||||||
fn set_val<T: 'static>(&mut self, value: T) {
|
|
||||||
if let Some(prop) = self.any_mut().downcast_mut::<T>() {
|
|
||||||
*prop = value;
|
|
||||||
} else {
|
|
||||||
panic!("prop value is not {}", std::any::type_name::<T>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<P> PropsVal for P where P: Props {
|
|
||||||
fn prop_val<T: 'static>(&self, name: &str) -> Option<&T> {
|
|
||||||
self.prop(name).and_then(|p| p.any().downcast_ref::<T>())
|
|
||||||
}
|
|
||||||
fn set_prop_val<T: 'static>(&mut self, name: &str, value: T) {
|
|
||||||
if let Some(prop) = self.prop_mut(name).and_then(|p| p.any_mut().downcast_mut::<T>()) {
|
|
||||||
*prop = value;
|
|
||||||
} else {
|
|
||||||
panic!("prop does not exist or is incorrect type: {}", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn set_prop_val_dyn<T: 'static>(&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<D>(_deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'a>,
|
|
||||||
{
|
|
||||||
Ok(DynamicProperties::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> 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<dyn Prop> {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
fn set_val_dyn(&mut self, value: &dyn Prop) {
|
|
||||||
if let Some(prop) = value.any().downcast_ref::<T>() {
|
|
||||||
*self = prop.clone();
|
|
||||||
} else {
|
|
||||||
panic!("prop value is not {}", std::any::type_name::<T>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
375
crates/bevy_props/src/prop.rs
Normal file
375
crates/bevy_props/src/prop.rs
Normal file
@ -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<dyn Prop>;
|
||||||
|
fn set(&mut self, value: &dyn Prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
erased_serde::serialize_trait_object!(Prop);
|
||||||
|
|
||||||
|
pub trait PropVal {
|
||||||
|
fn val<T: 'static>(&self) -> Option<&T>;
|
||||||
|
fn set_val<T: 'static>(&mut self, value: T);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropVal for dyn Prop {
|
||||||
|
// #[inline]
|
||||||
|
default fn val<T: 'static>(&self) -> Option<&T> {
|
||||||
|
self.any().downcast_ref::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[inline]
|
||||||
|
default fn set_val<T: 'static>(&mut self, value: T) {
|
||||||
|
if let Some(prop) = self.any_mut().downcast_mut::<T>() {
|
||||||
|
*prop = value;
|
||||||
|
} else {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<T>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> 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<dyn Prop> {
|
||||||
|
Box::new(self.clone())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
default fn set(&mut self, value: &dyn Prop) {
|
||||||
|
if let Some(prop) = value.any().downcast_ref::<T>() {
|
||||||
|
*self = prop.clone();
|
||||||
|
} else {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<T>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prop for usize {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
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 Prop for u64 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<usize>() {
|
||||||
|
*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 Prop for u32 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
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::<usize>() {
|
||||||
|
*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 Prop for u16 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
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::<usize>() {
|
||||||
|
*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 Prop for u8 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
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::<usize>() {
|
||||||
|
*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 Prop for isize {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} 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 if let Some(prop) = value.downcast_ref::<usize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} 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 {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prop for i64 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<isize>() {
|
||||||
|
*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 if let Some(prop) = value.downcast_ref::<usize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} 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 {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prop for i32 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<i64>() {
|
||||||
|
*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::<i16>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<i8>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<usize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} 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 {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prop for i16 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} 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::<isize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<i8>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<usize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} 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 {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prop for i8 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} 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::<isize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<usize>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} 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 {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Prop for f32 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<f64>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Prop for f64 {
|
||||||
|
fn set(&mut self, value: &dyn Prop) {
|
||||||
|
let value = value.any();
|
||||||
|
if let Some(prop) = value.downcast_ref::<Self>() {
|
||||||
|
*self = *prop;
|
||||||
|
} else if let Some(prop) = value.downcast_ref::<f32>() {
|
||||||
|
*self = *prop as Self;
|
||||||
|
} else {
|
||||||
|
panic!("prop value is not {}", std::any::type_name::<Self>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
103
crates/bevy_props/src/props.rs
Normal file
103
crates/bevy_props/src/props.rs
Normal file
@ -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::<Self>();
|
||||||
|
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<Self::Item> {
|
||||||
|
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<T: 'static>(&self, name: &str) -> Option<&T>;
|
||||||
|
fn set_prop_val<T: 'static>(&mut self, name: &str, value: T);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P> PropsVal for P
|
||||||
|
where
|
||||||
|
P: Props,
|
||||||
|
{
|
||||||
|
// #[inline]
|
||||||
|
fn prop_val<T: 'static>(&self, name: &str) -> Option<&T> {
|
||||||
|
self.prop(name).and_then(|p| p.any().downcast_ref::<T>())
|
||||||
|
}
|
||||||
|
// #[inline]
|
||||||
|
fn set_prop_val<T: 'static>(&mut self, name: &str, value: T) {
|
||||||
|
if let Some(prop) = self.prop_mut(name) {
|
||||||
|
prop.set_val(value);
|
||||||
|
} 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bevy_app = { path = "../bevy_app" }
|
bevy_app = { path = "../bevy_app" }
|
||||||
bevy_asset = { path = "../bevy_asset" }
|
bevy_asset = { path = "../bevy_asset" }
|
||||||
|
bevy_props = { path = "../bevy_props" }
|
||||||
legion = { path = "../bevy_legion", features = ["serialize"] }
|
legion = { path = "../bevy_legion", features = ["serialize"] }
|
||||||
serde = { version = "1.0", features = ["derive"]}
|
serde = { version = "1.0", features = ["derive"]}
|
||||||
erased-serde = "0.3"
|
erased-serde = "0.3"
|
||||||
|
|||||||
@ -2,13 +2,26 @@ use crate::{ComponentRegistry, ComponentRegistryContext, SceneDeserializer};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bevy_app::FromResources;
|
use bevy_app::FromResources;
|
||||||
use bevy_asset::AssetLoader;
|
use bevy_asset::AssetLoader;
|
||||||
|
use bevy_props::DynamicProperties;
|
||||||
use legion::prelude::{Resources, World};
|
use legion::prelude::{Resources, World};
|
||||||
use serde::de::DeserializeSeed;
|
use serde::de::DeserializeSeed;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct DynamicScene {
|
||||||
|
pub entities: Vec<SceneEntity>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct SceneEntity {
|
||||||
|
pub entity: u32,
|
||||||
|
pub components: Vec<DynamicProperties>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub world: World,
|
pub world: World,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_props::{DynamicScene, SerializableProps, SceneEntity};
|
use bevy_props::SerializableProps;
|
||||||
|
use bevy_scene::{DynamicScene, SceneEntity};
|
||||||
use serde::ser::Serialize;
|
use serde::ser::Serialize;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -13,16 +14,26 @@ fn main() {
|
|||||||
pub struct Test {
|
pub struct Test {
|
||||||
a: usize,
|
a: usize,
|
||||||
b: String,
|
b: String,
|
||||||
|
c: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup() {
|
fn setup() {
|
||||||
let mut test = Test {
|
let mut test = Test {
|
||||||
a: 1,
|
a: 1,
|
||||||
b: "hi".to_string(),
|
b: "hi".to_string(),
|
||||||
|
c: 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
test.set_prop_val::<usize>("a", 2);
|
test.set_prop_val::<usize>("a", 2);
|
||||||
assert_eq!(test.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::<f32>("c", 2.0);
|
||||||
|
let x: f64 = 3.0;
|
||||||
|
test.set_prop("c", &x);
|
||||||
|
assert_eq!(test.c, 3.0);
|
||||||
|
|
||||||
let mut patch = DynamicProperties::default();
|
let mut patch = DynamicProperties::default();
|
||||||
patch.set::<usize>("a", 3);
|
patch.set::<usize>("a", 3);
|
||||||
@ -30,26 +41,19 @@ fn setup() {
|
|||||||
|
|
||||||
assert_eq!(test.a, 3);
|
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);
|
let mut serializer = ron::ser::Serializer::new(Some(ron::ser::PrettyConfig::default()), false);
|
||||||
ser.serialize(&mut serializer).unwrap();
|
ser.serialize(&mut serializer).unwrap();
|
||||||
println!("{}", serializer.into_output_string());
|
println!("{}", serializer.into_output_string());
|
||||||
|
|
||||||
let dynamic_scene = DynamicScene {
|
let dynamic_scene = DynamicScene {
|
||||||
entities: vec![
|
entities: vec![SceneEntity {
|
||||||
SceneEntity {
|
entity: 12345,
|
||||||
entity: 12345,
|
components: vec![patch],
|
||||||
components: vec![
|
}],
|
||||||
patch
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut serializer = ron::ser::Serializer::new(Some(ron::ser::PrettyConfig::default()), false);
|
let mut serializer = ron::ser::Serializer::new(Some(ron::ser::PrettyConfig::default()), false);
|
||||||
dynamic_scene.entities.serialize(&mut serializer).unwrap();
|
dynamic_scene.entities.serialize(&mut serializer).unwrap();
|
||||||
println!("{}", serializer.into_output_string());
|
println!("{}", serializer.into_output_string());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user