2021-05-19 19:03:36 +00:00
|
|
|
use crate as bevy_reflect;
|
2020-11-28 00:39:59 +00:00
|
|
|
use crate::{
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
map_partial_eq, serde::Serializable, DynamicMap, FromReflect, FromType, GetTypeRegistration,
|
|
|
|
List, ListIter, Map, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef,
|
|
|
|
TypeRegistration,
|
2020-11-28 00:39:59 +00:00
|
|
|
};
|
|
|
|
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value};
|
|
|
|
use bevy_utils::{AHashExt, Duration, HashMap, HashSet};
|
2020-11-28 00:39:59 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-02-01 00:35:23 +00:00
|
|
|
use std::{
|
|
|
|
any::Any,
|
|
|
|
borrow::Cow,
|
|
|
|
hash::{Hash, Hasher},
|
|
|
|
ops::Range,
|
|
|
|
};
|
2020-11-28 00:39:59 +00:00
|
|
|
|
|
|
|
impl_reflect_value!(bool(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(u8(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(u16(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(u32(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(u64(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(u128(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(usize(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(i8(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(i16(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(i32(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(i64(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(i128(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(isize(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(f32(Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(f64(Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(String(Hash, PartialEq, Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(Option<T: Serialize + Clone + for<'de> Deserialize<'de> + Reflect + 'static>(Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(HashSet<T: Serialize + Hash + Eq + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize));
|
|
|
|
impl_reflect_value!(Range<T: Serialize + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize));
|
2021-12-29 21:04:26 +00:00
|
|
|
impl_reflect_value!(Duration(Hash, PartialEq, Serialize, Deserialize));
|
2020-11-28 00:39:59 +00:00
|
|
|
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
impl_from_reflect_value!(bool);
|
|
|
|
impl_from_reflect_value!(u8);
|
|
|
|
impl_from_reflect_value!(u16);
|
|
|
|
impl_from_reflect_value!(u32);
|
|
|
|
impl_from_reflect_value!(u64);
|
|
|
|
impl_from_reflect_value!(u128);
|
|
|
|
impl_from_reflect_value!(usize);
|
|
|
|
impl_from_reflect_value!(i8);
|
|
|
|
impl_from_reflect_value!(i16);
|
|
|
|
impl_from_reflect_value!(i32);
|
|
|
|
impl_from_reflect_value!(i64);
|
|
|
|
impl_from_reflect_value!(i128);
|
|
|
|
impl_from_reflect_value!(isize);
|
|
|
|
impl_from_reflect_value!(f32);
|
|
|
|
impl_from_reflect_value!(f64);
|
|
|
|
impl_from_reflect_value!(String);
|
|
|
|
impl_from_reflect_value!(
|
|
|
|
Option<T: Serialize + Clone + for<'de> Deserialize<'de> + Reflect + 'static>
|
|
|
|
);
|
|
|
|
impl_from_reflect_value!(
|
|
|
|
HashSet<T: Serialize + Hash + Eq + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>
|
|
|
|
);
|
|
|
|
impl_from_reflect_value!(
|
|
|
|
Range<T: Serialize + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>
|
|
|
|
);
|
|
|
|
impl_from_reflect_value!(Duration);
|
|
|
|
|
|
|
|
impl<T: FromReflect> List for Vec<T> {
|
2020-11-28 00:39:59 +00:00
|
|
|
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
|
|
|
<[T]>::get(self, index).map(|value| value as &dyn Reflect)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
|
|
|
<[T]>::get_mut(self, index).map(|value| value as &mut dyn Reflect)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
<[T]>::len(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn iter(&self) -> ListIter {
|
|
|
|
ListIter {
|
|
|
|
list: self,
|
|
|
|
index: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn push(&mut self, value: Box<dyn Reflect>) {
|
|
|
|
let value = value.take::<T>().unwrap_or_else(|value| {
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
T::from_reflect(&*value).unwrap_or_else(|| {
|
|
|
|
panic!(
|
|
|
|
"Attempted to push invalid value of type {}.",
|
|
|
|
value.type_name()
|
|
|
|
)
|
|
|
|
})
|
2020-11-28 00:39:59 +00:00
|
|
|
});
|
|
|
|
Vec::push(self, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:46:46 +00:00
|
|
|
// SAFE: any and any_mut both return self
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
unsafe impl<T: FromReflect> Reflect for Vec<T> {
|
2020-11-28 00:39:59 +00:00
|
|
|
fn type_name(&self) -> &str {
|
|
|
|
std::any::type_name::<Self>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn any(&self) -> &dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn any_mut(&mut self) -> &mut dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn apply(&mut self, value: &dyn Reflect) {
|
|
|
|
crate::list_apply(self, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
|
|
|
*self = value.take()?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_ref(&self) -> ReflectRef {
|
|
|
|
ReflectRef::List(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_mut(&mut self) -> ReflectMut {
|
|
|
|
ReflectMut::List(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clone_value(&self) -> Box<dyn Reflect> {
|
|
|
|
Box::new(self.clone_dynamic())
|
|
|
|
}
|
|
|
|
|
2020-12-01 19:15:07 +00:00
|
|
|
fn reflect_hash(&self) -> Option<u64> {
|
2020-11-28 00:39:59 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2020-12-01 19:15:07 +00:00
|
|
|
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
2020-11-28 00:39:59 +00:00
|
|
|
crate::list_partial_eq(self, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn serializable(&self) -> Option<Serializable> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
impl<T: FromReflect + for<'de> Deserialize<'de>> GetTypeRegistration for Vec<T> {
|
Reflection cleanup (#1536)
This is an effort to provide the correct `#[reflect_value(...)]` attributes where they are needed.
Supersedes #1533 and resolves #1528.
---
I am working under the following assumptions (thanks to @bjorn3 and @Davier for advice here):
- Any `enum` that derives `Reflect` and one or more of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } needs a `#[reflect_value(...)]` attribute containing the same subset of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } that is present on the derive.
- Same as above for `struct` and `#[reflect(...)]`, respectively.
- If a `struct` is used as a component, it should also have `#[reflect(Component)]`
- All reflected types should be registered in their plugins
I treated the following as components (added `#[reflect(Component)]` if necessary):
- `bevy_render`
- `struct RenderLayers`
- `bevy_transform`
- `struct GlobalTransform`
- `struct Parent`
- `struct Transform`
- `bevy_ui`
- `struct Style`
Not treated as components:
- `bevy_math`
- `struct Size<T>`
- `struct Rect<T>`
- Note: The updates for `Size<T>` and `Rect<T>` in `bevy::math::geometry` required using @Davier's suggestion to add `+ PartialEq` to the trait bound. I then registered the specific types used over in `bevy_ui` such as `Size<Val>`, etc. in `bevy_ui`'s plugin, since `bevy::math` does not contain a plugin.
- `bevy_render`
- `struct Color`
- `struct PipelineSpecialization`
- `struct ShaderSpecialization`
- `enum PrimitiveTopology`
- `enum IndexFormat`
Not Addressed:
- I am not searching for components in Bevy that are _not_ reflected. So if there are components that are not reflected that should be reflected, that will need to be figured out in another PR.
- I only added `#[reflect(...)]` or `#[reflect_value(...)]` entries for the set of four traits { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } _if they were derived via `#[derive(...)]`_. I did not look for manual trait implementations of the same set of four, nor did I consider any traits outside the four. Are those other possibilities something that needs to be looked into?
2021-03-09 23:39:41 +00:00
|
|
|
fn get_type_registration() -> TypeRegistration {
|
|
|
|
let mut registration = TypeRegistration::of::<Vec<T>>();
|
|
|
|
registration.insert::<ReflectDeserialize>(FromType::<Vec<T>>::from_type());
|
|
|
|
registration
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
impl<T: FromReflect> FromReflect for Vec<T> {
|
|
|
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
|
|
|
if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
|
|
|
|
let mut new_list = Self::with_capacity(ref_list.len());
|
|
|
|
for field in ref_list.iter() {
|
|
|
|
new_list.push(T::from_reflect(field)?);
|
|
|
|
}
|
|
|
|
Some(new_list)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<K: Reflect + Eq + Hash, V: Reflect> Map for HashMap<K, V> {
|
2020-11-28 00:39:59 +00:00
|
|
|
fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> {
|
|
|
|
key.downcast_ref::<K>()
|
|
|
|
.and_then(|key| HashMap::get(self, key))
|
|
|
|
.map(|value| value as &dyn Reflect)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> {
|
|
|
|
key.downcast_ref::<K>()
|
|
|
|
.and_then(move |key| HashMap::get_mut(self, key))
|
|
|
|
.map(|value| value as &mut dyn Reflect)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> {
|
|
|
|
self.iter()
|
|
|
|
.nth(index)
|
|
|
|
.map(|(key, value)| (key as &dyn Reflect, value as &dyn Reflect))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn len(&self) -> usize {
|
2022-02-13 22:33:55 +00:00
|
|
|
Self::len(self)
|
2020-11-28 00:39:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn iter(&self) -> MapIter {
|
|
|
|
MapIter {
|
|
|
|
map: self,
|
|
|
|
index: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clone_dynamic(&self) -> DynamicMap {
|
|
|
|
let mut dynamic_map = DynamicMap::default();
|
2021-02-02 21:57:26 +00:00
|
|
|
dynamic_map.set_name(self.type_name().to_string());
|
2022-02-13 22:33:55 +00:00
|
|
|
for (k, v) in self {
|
2020-11-28 00:39:59 +00:00
|
|
|
dynamic_map.insert_boxed(k.clone_value(), v.clone_value());
|
|
|
|
}
|
|
|
|
dynamic_map
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:46:46 +00:00
|
|
|
// SAFE: any and any_mut both return self
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
unsafe impl<K: Reflect + Eq + Hash, V: Reflect> Reflect for HashMap<K, V> {
|
2020-11-28 00:39:59 +00:00
|
|
|
fn type_name(&self) -> &str {
|
|
|
|
std::any::type_name::<Self>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn any(&self) -> &dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn any_mut(&mut self) -> &mut dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn apply(&mut self, value: &dyn Reflect) {
|
|
|
|
if let ReflectRef::Map(map_value) = value.reflect_ref() {
|
|
|
|
for (key, value) in map_value.iter() {
|
|
|
|
if let Some(v) = Map::get_mut(self, key) {
|
|
|
|
v.apply(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2020-12-02 19:31:16 +00:00
|
|
|
panic!("Attempted to apply a non-map type to a map type.");
|
2020-11-28 00:39:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
|
|
|
*self = value.take()?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_ref(&self) -> ReflectRef {
|
|
|
|
ReflectRef::Map(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_mut(&mut self) -> ReflectMut {
|
|
|
|
ReflectMut::Map(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clone_value(&self) -> Box<dyn Reflect> {
|
|
|
|
Box::new(self.clone_dynamic())
|
|
|
|
}
|
|
|
|
|
2020-12-01 19:15:07 +00:00
|
|
|
fn reflect_hash(&self) -> Option<u64> {
|
2020-11-28 00:39:59 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2020-12-01 19:15:07 +00:00
|
|
|
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
2020-11-28 00:39:59 +00:00
|
|
|
map_partial_eq(self, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn serializable(&self) -> Option<Serializable> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2021-02-01 00:35:23 +00:00
|
|
|
|
Reflection cleanup (#1536)
This is an effort to provide the correct `#[reflect_value(...)]` attributes where they are needed.
Supersedes #1533 and resolves #1528.
---
I am working under the following assumptions (thanks to @bjorn3 and @Davier for advice here):
- Any `enum` that derives `Reflect` and one or more of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } needs a `#[reflect_value(...)]` attribute containing the same subset of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } that is present on the derive.
- Same as above for `struct` and `#[reflect(...)]`, respectively.
- If a `struct` is used as a component, it should also have `#[reflect(Component)]`
- All reflected types should be registered in their plugins
I treated the following as components (added `#[reflect(Component)]` if necessary):
- `bevy_render`
- `struct RenderLayers`
- `bevy_transform`
- `struct GlobalTransform`
- `struct Parent`
- `struct Transform`
- `bevy_ui`
- `struct Style`
Not treated as components:
- `bevy_math`
- `struct Size<T>`
- `struct Rect<T>`
- Note: The updates for `Size<T>` and `Rect<T>` in `bevy::math::geometry` required using @Davier's suggestion to add `+ PartialEq` to the trait bound. I then registered the specific types used over in `bevy_ui` such as `Size<Val>`, etc. in `bevy_ui`'s plugin, since `bevy::math` does not contain a plugin.
- `bevy_render`
- `struct Color`
- `struct PipelineSpecialization`
- `struct ShaderSpecialization`
- `enum PrimitiveTopology`
- `enum IndexFormat`
Not Addressed:
- I am not searching for components in Bevy that are _not_ reflected. So if there are components that are not reflected that should be reflected, that will need to be figured out in another PR.
- I only added `#[reflect(...)]` or `#[reflect_value(...)]` entries for the set of four traits { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } _if they were derived via `#[derive(...)]`_. I did not look for manual trait implementations of the same set of four, nor did I consider any traits outside the four. Are those other possibilities something that needs to be looked into?
2021-03-09 23:39:41 +00:00
|
|
|
impl<K, V> GetTypeRegistration for HashMap<K, V>
|
|
|
|
where
|
|
|
|
K: Reflect + Clone + Eq + Hash + for<'de> Deserialize<'de>,
|
|
|
|
V: Reflect + Clone + for<'de> Deserialize<'de>,
|
|
|
|
{
|
|
|
|
fn get_type_registration() -> TypeRegistration {
|
2022-02-13 22:33:55 +00:00
|
|
|
let mut registration = TypeRegistration::of::<Self>();
|
|
|
|
registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
|
Reflection cleanup (#1536)
This is an effort to provide the correct `#[reflect_value(...)]` attributes where they are needed.
Supersedes #1533 and resolves #1528.
---
I am working under the following assumptions (thanks to @bjorn3 and @Davier for advice here):
- Any `enum` that derives `Reflect` and one or more of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } needs a `#[reflect_value(...)]` attribute containing the same subset of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } that is present on the derive.
- Same as above for `struct` and `#[reflect(...)]`, respectively.
- If a `struct` is used as a component, it should also have `#[reflect(Component)]`
- All reflected types should be registered in their plugins
I treated the following as components (added `#[reflect(Component)]` if necessary):
- `bevy_render`
- `struct RenderLayers`
- `bevy_transform`
- `struct GlobalTransform`
- `struct Parent`
- `struct Transform`
- `bevy_ui`
- `struct Style`
Not treated as components:
- `bevy_math`
- `struct Size<T>`
- `struct Rect<T>`
- Note: The updates for `Size<T>` and `Rect<T>` in `bevy::math::geometry` required using @Davier's suggestion to add `+ PartialEq` to the trait bound. I then registered the specific types used over in `bevy_ui` such as `Size<Val>`, etc. in `bevy_ui`'s plugin, since `bevy::math` does not contain a plugin.
- `bevy_render`
- `struct Color`
- `struct PipelineSpecialization`
- `struct ShaderSpecialization`
- `enum PrimitiveTopology`
- `enum IndexFormat`
Not Addressed:
- I am not searching for components in Bevy that are _not_ reflected. So if there are components that are not reflected that should be reflected, that will need to be figured out in another PR.
- I only added `#[reflect(...)]` or `#[reflect_value(...)]` entries for the set of four traits { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } _if they were derived via `#[derive(...)]`_. I did not look for manual trait implementations of the same set of four, nor did I consider any traits outside the four. Are those other possibilities something that needs to be looked into?
2021-03-09 23:39:41 +00:00
|
|
|
registration
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
impl<K: FromReflect + Eq + Hash, V: FromReflect> FromReflect for HashMap<K, V> {
|
|
|
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
|
|
|
if let ReflectRef::Map(ref_map) = reflect.reflect_ref() {
|
|
|
|
let mut new_map = Self::with_capacity(ref_map.len());
|
|
|
|
for (key, value) in ref_map.iter() {
|
|
|
|
let new_key = K::from_reflect(key)?;
|
|
|
|
let new_value = V::from_reflect(value)?;
|
|
|
|
new_map.insert(new_key, new_value);
|
|
|
|
}
|
|
|
|
Some(new_map)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-17 22:46:46 +00:00
|
|
|
// SAFE: any and any_mut both return self
|
|
|
|
unsafe impl Reflect for Cow<'static, str> {
|
2021-02-01 00:35:23 +00:00
|
|
|
fn type_name(&self) -> &str {
|
|
|
|
std::any::type_name::<Self>()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn any(&self) -> &dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn any_mut(&mut self) -> &mut dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn apply(&mut self, value: &dyn Reflect) {
|
|
|
|
let value = value.any();
|
|
|
|
if let Some(value) = value.downcast_ref::<Self>() {
|
|
|
|
*self = value.clone();
|
|
|
|
} else {
|
|
|
|
panic!("Value is not a {}.", std::any::type_name::<Self>());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
|
|
|
*self = value.take()?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_ref(&self) -> ReflectRef {
|
|
|
|
ReflectRef::Value(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_mut(&mut self) -> ReflectMut {
|
|
|
|
ReflectMut::Value(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clone_value(&self) -> Box<dyn Reflect> {
|
|
|
|
Box::new(self.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_hash(&self) -> Option<u64> {
|
|
|
|
let mut hasher = crate::ReflectHasher::default();
|
|
|
|
Hash::hash(&std::any::Any::type_id(self), &mut hasher);
|
|
|
|
Hash::hash(self, &mut hasher);
|
|
|
|
Some(hasher.finish())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
|
|
|
let value = value.any();
|
|
|
|
if let Some(value) = value.downcast_ref::<Self>() {
|
|
|
|
Some(std::cmp::PartialEq::eq(self, value))
|
|
|
|
} else {
|
|
|
|
Some(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn serializable(&self) -> Option<Serializable> {
|
|
|
|
Some(Serializable::Borrowed(self))
|
|
|
|
}
|
|
|
|
}
|
Reflection cleanup (#1536)
This is an effort to provide the correct `#[reflect_value(...)]` attributes where they are needed.
Supersedes #1533 and resolves #1528.
---
I am working under the following assumptions (thanks to @bjorn3 and @Davier for advice here):
- Any `enum` that derives `Reflect` and one or more of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } needs a `#[reflect_value(...)]` attribute containing the same subset of { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } that is present on the derive.
- Same as above for `struct` and `#[reflect(...)]`, respectively.
- If a `struct` is used as a component, it should also have `#[reflect(Component)]`
- All reflected types should be registered in their plugins
I treated the following as components (added `#[reflect(Component)]` if necessary):
- `bevy_render`
- `struct RenderLayers`
- `bevy_transform`
- `struct GlobalTransform`
- `struct Parent`
- `struct Transform`
- `bevy_ui`
- `struct Style`
Not treated as components:
- `bevy_math`
- `struct Size<T>`
- `struct Rect<T>`
- Note: The updates for `Size<T>` and `Rect<T>` in `bevy::math::geometry` required using @Davier's suggestion to add `+ PartialEq` to the trait bound. I then registered the specific types used over in `bevy_ui` such as `Size<Val>`, etc. in `bevy_ui`'s plugin, since `bevy::math` does not contain a plugin.
- `bevy_render`
- `struct Color`
- `struct PipelineSpecialization`
- `struct ShaderSpecialization`
- `enum PrimitiveTopology`
- `enum IndexFormat`
Not Addressed:
- I am not searching for components in Bevy that are _not_ reflected. So if there are components that are not reflected that should be reflected, that will need to be figured out in another PR.
- I only added `#[reflect(...)]` or `#[reflect_value(...)]` entries for the set of four traits { `Serialize`, `Deserialize`, `PartialEq`, `Hash` } _if they were derived via `#[derive(...)]`_. I did not look for manual trait implementations of the same set of four, nor did I consider any traits outside the four. Are those other possibilities something that needs to be looked into?
2021-03-09 23:39:41 +00:00
|
|
|
|
|
|
|
impl GetTypeRegistration for Cow<'static, str> {
|
|
|
|
fn get_type_registration() -> TypeRegistration {
|
|
|
|
let mut registration = TypeRegistration::of::<Cow<'static, str>>();
|
|
|
|
registration.insert::<ReflectDeserialize>(FromType::<Cow<'static, str>>::from_type());
|
|
|
|
registration
|
|
|
|
}
|
|
|
|
}
|
Add FromReflect trait to convert dynamic types to concrete types (#1395)
Dynamic types (`DynamicStruct`, `DynamicTupleStruct`, `DynamicTuple`, `DynamicList` and `DynamicMap`) are used when deserializing scenes, but currently they can only be applied to existing concrete types. This leads to issues when trying to spawn non trivial deserialized scene.
For components, the issue is avoided by requiring that reflected components implement ~~`FromResources`~~ `FromWorld` (or `Default`). When spawning, a new concrete type is created that way, and the dynamic type is applied to it. Unfortunately, some components don't have any valid implementation of these traits.
In addition, any `Vec` or `HashMap` inside a component will panic when a dynamic type is pushed into it (for instance, `Text` panics when adding a text section).
To solve this issue, this PR adds the `FromReflect` trait that creates a concrete type from a dynamic type that represent it, derives the trait alongside the `Reflect` trait, drops the ~~`FromResources`~~ `FromWorld` requirement on reflected components, ~~and enables reflection for UI and Text bundles~~. It also adds the requirement that fields ignored with `#[reflect(ignore)]` implement `Default`, since we need to initialize them somehow.
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-26 18:49:01 +00:00
|
|
|
|
|
|
|
impl FromReflect for Cow<'static, str> {
|
|
|
|
fn from_reflect(reflect: &dyn crate::Reflect) -> Option<Self> {
|
|
|
|
Some(reflect.any().downcast_ref::<Cow<'static, str>>()?.clone())
|
|
|
|
}
|
|
|
|
}
|
2021-12-29 21:04:26 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::Reflect;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_serialize_duration() {
|
2022-02-13 22:33:55 +00:00
|
|
|
assert!(std::time::Duration::ZERO.serializable().is_some());
|
2021-12-29 21:04:26 +00:00
|
|
|
}
|
|
|
|
}
|