mirror of
https://github.com/bevyengine/bevy
synced 2024-12-30 06:53:13 +00:00
06d9384447
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>
116 lines
2.8 KiB
Rust
116 lines
2.8 KiB
Rust
use smallvec::{Array, SmallVec};
|
|
use std::any::Any;
|
|
|
|
use crate::{serde::Serializable, FromReflect, List, ListIter, Reflect, ReflectMut, ReflectRef};
|
|
|
|
impl<T: Array + Send + Sync + 'static> List for SmallVec<T>
|
|
where
|
|
T::Item: FromReflect + Clone,
|
|
{
|
|
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
|
if index < SmallVec::len(self) {
|
|
Some(&self[index] as &dyn Reflect)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
|
if index < SmallVec::len(self) {
|
|
Some(&mut self[index] as &mut dyn Reflect)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn len(&self) -> usize {
|
|
<SmallVec<T>>::len(self)
|
|
}
|
|
|
|
fn push(&mut self, value: Box<dyn Reflect>) {
|
|
let value = value.take::<T::Item>().unwrap_or_else(|value| {
|
|
<T as Array>::Item::from_reflect(&*value).unwrap_or_else(|| {
|
|
panic!(
|
|
"Attempted to push invalid value of type {}.",
|
|
value.type_name()
|
|
)
|
|
})
|
|
});
|
|
SmallVec::push(self, value);
|
|
}
|
|
|
|
fn iter(&self) -> ListIter {
|
|
ListIter {
|
|
list: self,
|
|
index: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
// SAFE: any and any_mut both return self
|
|
unsafe impl<T: Array + Send + Sync + 'static> Reflect for SmallVec<T>
|
|
where
|
|
T::Item: FromReflect + Clone,
|
|
{
|
|
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())
|
|
}
|
|
|
|
fn reflect_hash(&self) -> Option<u64> {
|
|
None
|
|
}
|
|
|
|
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
|
crate::list_partial_eq(self, value)
|
|
}
|
|
|
|
fn serializable(&self) -> Option<Serializable> {
|
|
None
|
|
}
|
|
}
|
|
|
|
impl<T: Array + Send + Sync + 'static> FromReflect for SmallVec<T>
|
|
where
|
|
T::Item: FromReflect + Clone,
|
|
{
|
|
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 as Array>::Item::from_reflect(field)?);
|
|
}
|
|
Some(new_list)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|