reflect: remove manual Reflect impls which could be handled by macros (#12596)
# Objective * Adopted #12025 to fix merge conflicts * In some cases we used manual impls for certain types, though they are (at least, now) unnecessary. ## Solution * Use macros and reflecting-by-value to avoid this clutter. * Though there were linker issues with Reflect and the CowArc in AssetPath (see https://github.com/bevyengine/bevy/issues/9747), I checked these are resolved by using #[reflect_value]. --------- Co-authored-by: soqb <cb.setho@gmail.com> Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: James Liu <contact@jamessliu.com>
This commit is contained in:
		
							parent
							
								
									037f9d414b
								
							
						
					
					
						commit
						fdf2ea7cc5
					
				@ -1,15 +1,10 @@
 | 
				
			|||||||
use crate::io::AssetSourceId;
 | 
					use crate::io::AssetSourceId;
 | 
				
			||||||
use bevy_reflect::{
 | 
					use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
 | 
				
			||||||
    std_traits::ReflectDefault, utility::NonGenericTypeInfoCell, FromReflect, FromType,
 | 
					 | 
				
			||||||
    GetTypeRegistration, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect,
 | 
					 | 
				
			||||||
    ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, TypeInfo, TypePath,
 | 
					 | 
				
			||||||
    TypeRegistration, Typed, ValueInfo,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use bevy_utils::CowArc;
 | 
					use bevy_utils::CowArc;
 | 
				
			||||||
use serde::{de::Visitor, Deserialize, Serialize};
 | 
					use serde::{de::Visitor, Deserialize, Serialize};
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
    fmt::{Debug, Display},
 | 
					    fmt::{Debug, Display},
 | 
				
			||||||
    hash::{Hash, Hasher},
 | 
					    hash::Hash,
 | 
				
			||||||
    ops::Deref,
 | 
					    ops::Deref,
 | 
				
			||||||
    path::{Path, PathBuf},
 | 
					    path::{Path, PathBuf},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -52,7 +47,8 @@ use thiserror::Error;
 | 
				
			|||||||
/// This means that the common case of `asset_server.load("my_scene.scn")` when it creates and
 | 
					/// This means that the common case of `asset_server.load("my_scene.scn")` when it creates and
 | 
				
			||||||
/// clones internal owned [`AssetPaths`](AssetPath).
 | 
					/// clones internal owned [`AssetPaths`](AssetPath).
 | 
				
			||||||
/// This also means that you should use [`AssetPath::parse`] in cases where `&str` is the explicit type.
 | 
					/// This also means that you should use [`AssetPath::parse`] in cases where `&str` is the explicit type.
 | 
				
			||||||
#[derive(Eq, PartialEq, Hash, Clone, Default)]
 | 
					#[derive(Eq, PartialEq, Hash, Clone, Default, Reflect)]
 | 
				
			||||||
 | 
					#[reflect_value(Debug, PartialEq, Hash, Serialize, Deserialize)]
 | 
				
			||||||
pub struct AssetPath<'a> {
 | 
					pub struct AssetPath<'a> {
 | 
				
			||||||
    source: AssetSourceId<'a>,
 | 
					    source: AssetSourceId<'a>,
 | 
				
			||||||
    path: CowArc<'a, Path>,
 | 
					    path: CowArc<'a, Path>,
 | 
				
			||||||
@ -572,136 +568,6 @@ impl<'de> Visitor<'de> for AssetPathVisitor {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NOTE: We manually implement "reflect value" because deriving Reflect on `AssetPath` breaks dynamic linking
 | 
					 | 
				
			||||||
// See https://github.com/bevyengine/bevy/issues/9747
 | 
					 | 
				
			||||||
// NOTE: This could use `impl_reflect_value` if it supported static lifetimes.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl GetTypeRegistration for AssetPath<'static> {
 | 
					 | 
				
			||||||
    fn get_type_registration() -> TypeRegistration {
 | 
					 | 
				
			||||||
        let mut registration = TypeRegistration::of::<Self>();
 | 
					 | 
				
			||||||
        registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectFromReflect>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectDefault>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TypePath for AssetPath<'static> {
 | 
					 | 
				
			||||||
    fn type_path() -> &'static str {
 | 
					 | 
				
			||||||
        "bevy_asset::path::AssetPath<'static>"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn short_type_path() -> &'static str {
 | 
					 | 
				
			||||||
        "AssetPath<'static>"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn type_ident() -> Option<&'static str> {
 | 
					 | 
				
			||||||
        Some("AssetPath<'static>")
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn crate_name() -> Option<&'static str> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn module_path() -> Option<&'static str> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl Typed for AssetPath<'static> {
 | 
					 | 
				
			||||||
    fn type_info() -> &'static TypeInfo {
 | 
					 | 
				
			||||||
        static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
 | 
					 | 
				
			||||||
        CELL.get_or_set(|| {
 | 
					 | 
				
			||||||
            let info = ValueInfo::new::<Self>();
 | 
					 | 
				
			||||||
            TypeInfo::Value(info)
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl Reflect for AssetPath<'static> {
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
					 | 
				
			||||||
        Some(<Self as Typed>::type_info())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn into_any(self: Box<Self>) -> Box<dyn core::any::Any> {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn as_any(&self) -> &dyn core::any::Any {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn as_reflect(&self) -> &dyn Reflect {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn apply(&mut self, value: &dyn Reflect) {
 | 
					 | 
				
			||||||
        let value = Reflect::as_any(value);
 | 
					 | 
				
			||||||
        if let Some(value) = value.downcast_ref::<Self>() {
 | 
					 | 
				
			||||||
            *self = value.clone();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            panic!("Value is not {}.", std::any::type_name::<Self>());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn set(
 | 
					 | 
				
			||||||
        &mut self,
 | 
					 | 
				
			||||||
        value: Box<dyn bevy_reflect::Reflect>,
 | 
					 | 
				
			||||||
    ) -> Result<(), Box<dyn bevy_reflect::Reflect>> {
 | 
					 | 
				
			||||||
        *self = <dyn bevy_reflect::Reflect>::take(value)?;
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_kind(&self) -> ReflectKind {
 | 
					 | 
				
			||||||
        ReflectKind::Value
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_ref(&self) -> ReflectRef {
 | 
					 | 
				
			||||||
        ReflectRef::Value(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_mut(&mut self) -> ReflectMut {
 | 
					 | 
				
			||||||
        ReflectMut::Value(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
 | 
					 | 
				
			||||||
        ReflectOwned::Value(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn clone_value(&self) -> Box<dyn Reflect> {
 | 
					 | 
				
			||||||
        Box::new(self.clone())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_hash(&self) -> Option<u64> {
 | 
					 | 
				
			||||||
        let mut hasher = bevy_reflect::utility::reflect_hasher();
 | 
					 | 
				
			||||||
        Hash::hash(&::core::any::Any::type_id(self), &mut hasher);
 | 
					 | 
				
			||||||
        Hash::hash(self, &mut hasher);
 | 
					 | 
				
			||||||
        Some(Hasher::finish(&hasher))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
 | 
					 | 
				
			||||||
        let value = <dyn Reflect>::as_any(value);
 | 
					 | 
				
			||||||
        if let Some(value) = <dyn core::any::Any>::downcast_ref::<Self>(value) {
 | 
					 | 
				
			||||||
            Some(PartialEq::eq(self, value))
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Some(false)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
 | 
					 | 
				
			||||||
        ::core::fmt::Debug::fmt(self, f)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
impl FromReflect for AssetPath<'static> {
 | 
					 | 
				
			||||||
    fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
 | 
					 | 
				
			||||||
        Some(Clone::clone(<dyn core::any::Any>::downcast_ref::<
 | 
					 | 
				
			||||||
            AssetPath<'static>,
 | 
					 | 
				
			||||||
        >(<dyn Reflect>::as_any(reflect))?))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Normalizes the path by collapsing all occurrences of '.' and '..' dot-segments where possible
 | 
					/// Normalizes the path by collapsing all occurrences of '.' and '..' dot-segments where possible
 | 
				
			||||||
/// as per [RFC 1808](https://datatracker.ietf.org/doc/html/rfc1808)
 | 
					/// as per [RFC 1808](https://datatracker.ietf.org/doc/html/rfc1808)
 | 
				
			||||||
pub(crate) fn normalize_path(path: &Path) -> PathBuf {
 | 
					pub(crate) fn normalize_path(path: &Path) -> PathBuf {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,16 @@
 | 
				
			|||||||
use crate::std_traits::ReflectDefault;
 | 
					use crate::std_traits::ReflectDefault;
 | 
				
			||||||
use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned, TypeRegistry};
 | 
					use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned, TypeRegistry};
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum,
 | 
					    impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicMap,
 | 
				
			||||||
    DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo,
 | 
					    FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter,
 | 
				
			||||||
    ListIter, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectKind, ReflectMut,
 | 
					    Reflect, ReflectDeserialize, ReflectKind, ReflectMut, ReflectRef, ReflectSerialize, TypeInfo,
 | 
				
			||||||
    ReflectRef, ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed,
 | 
					    TypePath, TypeRegistration, Typed, ValueInfo,
 | 
				
			||||||
    UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, VariantInfo, VariantType,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::utility::{
 | 
					use crate::utility::{
 | 
				
			||||||
    reflect_hasher, GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell,
 | 
					    reflect_hasher, GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use bevy_reflect_derive::impl_reflect_value;
 | 
					use bevy_reflect_derive::{impl_reflect, impl_reflect_value};
 | 
				
			||||||
use std::fmt;
 | 
					use std::fmt;
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
    any::Any,
 | 
					    any::Any,
 | 
				
			||||||
@ -996,252 +995,14 @@ impl<T: Reflect + TypePath + GetTypeRegistration, const N: usize> GetTypeRegistr
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: FromReflect + TypePath + GetTypeRegistration> GetTypeRegistration for Option<T> {
 | 
					impl_reflect! {
 | 
				
			||||||
    fn get_type_registration() -> TypeRegistration {
 | 
					    #[type_path = "core::option"]
 | 
				
			||||||
        TypeRegistration::of::<Option<T>>()
 | 
					    enum Option<T> {
 | 
				
			||||||
    }
 | 
					        None,
 | 
				
			||||||
 | 
					        Some(T),
 | 
				
			||||||
    fn register_type_dependencies(registry: &mut TypeRegistry) {
 | 
					 | 
				
			||||||
        registry.register::<T>();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: FromReflect + TypePath + GetTypeRegistration> Enum for Option<T> {
 | 
					 | 
				
			||||||
    fn field(&self, _name: &str) -> Option<&dyn Reflect> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            Some(value) if index == 0 => Some(value),
 | 
					 | 
				
			||||||
            _ => None,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn field_mut(&mut self, _name: &str) -> Option<&mut dyn Reflect> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            Some(value) if index == 0 => Some(value),
 | 
					 | 
				
			||||||
            _ => None,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn index_of(&self, _name: &str) -> Option<usize> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn name_at(&self, _index: usize) -> Option<&str> {
 | 
					 | 
				
			||||||
        None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn iter_fields(&self) -> VariantFieldIter {
 | 
					 | 
				
			||||||
        VariantFieldIter::new(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn field_len(&self) -> usize {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            Some(..) => 1,
 | 
					 | 
				
			||||||
            None => 0,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn variant_name(&self) -> &str {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            Some(..) => "Some",
 | 
					 | 
				
			||||||
            None => "None",
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn variant_index(&self) -> usize {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            None => 0,
 | 
					 | 
				
			||||||
            Some(..) => 1,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn variant_type(&self) -> VariantType {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            Some(..) => VariantType::Tuple,
 | 
					 | 
				
			||||||
            None => VariantType::Unit,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn clone_dynamic(&self) -> DynamicEnum {
 | 
					 | 
				
			||||||
        DynamicEnum::from_ref::<Self>(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T: FromReflect + TypePath + GetTypeRegistration> Reflect for Option<T> {
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
 | 
					 | 
				
			||||||
        Some(<Self as Typed>::type_info())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn into_any(self: Box<Self>) -> Box<dyn Any> {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn as_any(&self) -> &dyn Any {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn as_any_mut(&mut self) -> &mut dyn Any {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn as_reflect(&self) -> &dyn Reflect {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn apply(&mut self, value: &dyn Reflect) {
 | 
					 | 
				
			||||||
        if let ReflectRef::Enum(value) = value.reflect_ref() {
 | 
					 | 
				
			||||||
            if self.variant_name() == value.variant_name() {
 | 
					 | 
				
			||||||
                // Same variant -> just update fields
 | 
					 | 
				
			||||||
                for (index, field) in value.iter_fields().enumerate() {
 | 
					 | 
				
			||||||
                    if let Some(v) = self.field_at_mut(index) {
 | 
					 | 
				
			||||||
                        v.apply(field.value());
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                // New variant -> perform a switch
 | 
					 | 
				
			||||||
                match value.variant_name() {
 | 
					 | 
				
			||||||
                    "Some" => {
 | 
					 | 
				
			||||||
                        let field = T::take_from_reflect(
 | 
					 | 
				
			||||||
                            value
 | 
					 | 
				
			||||||
                                .field_at(0)
 | 
					 | 
				
			||||||
                                .unwrap_or_else(|| {
 | 
					 | 
				
			||||||
                                    panic!(
 | 
					 | 
				
			||||||
                                        "Field in `Some` variant of {} should exist",
 | 
					 | 
				
			||||||
                                        Self::type_path()
 | 
					 | 
				
			||||||
                                    )
 | 
					 | 
				
			||||||
                                })
 | 
					 | 
				
			||||||
                                .clone_value(),
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                        .unwrap_or_else(|_| {
 | 
					 | 
				
			||||||
                            panic!(
 | 
					 | 
				
			||||||
                                "Field in `Some` variant of {} should be of type {}",
 | 
					 | 
				
			||||||
                                Self::type_path(),
 | 
					 | 
				
			||||||
                                T::type_path()
 | 
					 | 
				
			||||||
                            )
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                        *self = Some(field);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    "None" => {
 | 
					 | 
				
			||||||
                        *self = None;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    _ => panic!("Enum is not a {}.", Self::type_path()),
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
 | 
					 | 
				
			||||||
        *self = value.take()?;
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reflect_kind(&self) -> ReflectKind {
 | 
					 | 
				
			||||||
        ReflectKind::Enum
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reflect_ref(&self) -> ReflectRef {
 | 
					 | 
				
			||||||
        ReflectRef::Enum(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reflect_mut(&mut self) -> ReflectMut {
 | 
					 | 
				
			||||||
        ReflectMut::Enum(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
 | 
					 | 
				
			||||||
        ReflectOwned::Enum(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #[inline]
 | 
					 | 
				
			||||||
    fn clone_value(&self) -> Box<dyn Reflect> {
 | 
					 | 
				
			||||||
        Box::new(Enum::clone_dynamic(self))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reflect_hash(&self) -> Option<u64> {
 | 
					 | 
				
			||||||
        crate::enum_hash(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
 | 
					 | 
				
			||||||
        crate::enum_partial_eq(self, value)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T: FromReflect + TypePath + GetTypeRegistration> FromReflect for Option<T> {
 | 
					 | 
				
			||||||
    fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
 | 
					 | 
				
			||||||
        if let ReflectRef::Enum(dyn_enum) = reflect.reflect_ref() {
 | 
					 | 
				
			||||||
            match dyn_enum.variant_name() {
 | 
					 | 
				
			||||||
                "Some" => {
 | 
					 | 
				
			||||||
                    let field = T::take_from_reflect(
 | 
					 | 
				
			||||||
                        dyn_enum
 | 
					 | 
				
			||||||
                            .field_at(0)
 | 
					 | 
				
			||||||
                            .unwrap_or_else(|| {
 | 
					 | 
				
			||||||
                                panic!(
 | 
					 | 
				
			||||||
                                    "Field in `Some` variant of {} should exist",
 | 
					 | 
				
			||||||
                                    Option::<T>::type_path()
 | 
					 | 
				
			||||||
                                )
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                            .clone_value(),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    .unwrap_or_else(|_| {
 | 
					 | 
				
			||||||
                        panic!(
 | 
					 | 
				
			||||||
                            "Field in `Some` variant of {} should be of type {}",
 | 
					 | 
				
			||||||
                            Option::<T>::type_path(),
 | 
					 | 
				
			||||||
                            T::type_path()
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                    Some(Some(field))
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                "None" => Some(None),
 | 
					 | 
				
			||||||
                name => panic!(
 | 
					 | 
				
			||||||
                    "variant with name `{}` does not exist on enum `{}`",
 | 
					 | 
				
			||||||
                    name,
 | 
					 | 
				
			||||||
                    Self::type_path()
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            None
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T: FromReflect + TypePath + GetTypeRegistration> Typed for Option<T> {
 | 
					 | 
				
			||||||
    fn type_info() -> &'static TypeInfo {
 | 
					 | 
				
			||||||
        static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
 | 
					 | 
				
			||||||
        CELL.get_or_insert::<Self, _>(|| {
 | 
					 | 
				
			||||||
            let none_variant = VariantInfo::Unit(UnitVariantInfo::new("None"));
 | 
					 | 
				
			||||||
            let some_variant =
 | 
					 | 
				
			||||||
                VariantInfo::Tuple(TupleVariantInfo::new("Some", &[UnnamedField::new::<T>(0)]));
 | 
					 | 
				
			||||||
            TypeInfo::Enum(EnumInfo::new::<Self>(&[none_variant, some_variant]))
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl_type_path!(::core::option::Option<T>);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl<T: TypePath + ?Sized> TypePath for &'static T {
 | 
					impl<T: TypePath + ?Sized> TypePath for &'static T {
 | 
				
			||||||
    fn type_path() -> &'static str {
 | 
					    fn type_path() -> &'static str {
 | 
				
			||||||
        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
					        static CELL: GenericTypePathCell = GenericTypePathCell::new();
 | 
				
			||||||
 | 
				
			|||||||
@ -7,13 +7,7 @@ use bevy_ecs::{
 | 
				
			|||||||
    system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState},
 | 
					    system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState},
 | 
				
			||||||
    world::{FromWorld, Mut},
 | 
					    world::{FromWorld, Mut},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use bevy_reflect::std_traits::ReflectDefault;
 | 
					use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
 | 
				
			||||||
use bevy_reflect::{
 | 
					 | 
				
			||||||
    utility::{reflect_hasher, NonGenericTypeInfoCell},
 | 
					 | 
				
			||||||
    FromReflect, FromType, GetTypeRegistration, Reflect, ReflectDeserialize, ReflectFromPtr,
 | 
					 | 
				
			||||||
    ReflectFromReflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize,
 | 
					 | 
				
			||||||
    TypeInfo, TypePath, TypeRegistration, Typed, ValueInfo,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use bevy_utils::{HashMap, HashSet};
 | 
					use bevy_utils::{HashMap, HashSet};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use std::marker::PhantomData;
 | 
					use std::marker::PhantomData;
 | 
				
			||||||
@ -77,7 +71,8 @@ bitflags::bitflags! {
 | 
				
			|||||||
    /// [discussion about memory management](https://github.com/WebAssembly/design/issues/1397) for more
 | 
					    /// [discussion about memory management](https://github.com/WebAssembly/design/issues/1397) for more
 | 
				
			||||||
    /// details.
 | 
					    /// details.
 | 
				
			||||||
    #[repr(transparent)]
 | 
					    #[repr(transparent)]
 | 
				
			||||||
    #[derive(Serialize, TypePath, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug)]
 | 
					    #[derive(Serialize, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug, Reflect)]
 | 
				
			||||||
 | 
					    #[reflect_value(Serialize, Deserialize, Hash, PartialEq, Debug)]
 | 
				
			||||||
    pub struct RenderAssetUsages: u8 {
 | 
					    pub struct RenderAssetUsages: u8 {
 | 
				
			||||||
        const MAIN_WORLD = 1 << 0;
 | 
					        const MAIN_WORLD = 1 << 0;
 | 
				
			||||||
        const RENDER_WORLD = 1 << 1;
 | 
					        const RENDER_WORLD = 1 << 1;
 | 
				
			||||||
@ -98,99 +93,6 @@ impl Default for RenderAssetUsages {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Reflect for RenderAssetUsages {
 | 
					 | 
				
			||||||
    fn get_represented_type_info(&self) -> Option<&'static bevy_reflect::TypeInfo> {
 | 
					 | 
				
			||||||
        Some(<Self as Typed>::type_info())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn as_any(&self) -> &dyn std::any::Any {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn as_reflect(&self) -> &dyn Reflect {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
 | 
					 | 
				
			||||||
        self
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn apply(&mut self, value: &dyn Reflect) {
 | 
					 | 
				
			||||||
        let value = value.as_any();
 | 
					 | 
				
			||||||
        if let Some(&value) = value.downcast_ref::<Self>() {
 | 
					 | 
				
			||||||
            *self = value;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            panic!("Value is not a {}.", Self::type_path());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
 | 
					 | 
				
			||||||
        *self = value.take()?;
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
 | 
					 | 
				
			||||||
        ReflectKind::Value
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
 | 
					 | 
				
			||||||
        ReflectRef::Value(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
 | 
					 | 
				
			||||||
        ReflectMut::Value(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_owned(self: Box<Self>) -> bevy_reflect::ReflectOwned {
 | 
					 | 
				
			||||||
        ReflectOwned::Value(self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn clone_value(&self) -> Box<dyn Reflect> {
 | 
					 | 
				
			||||||
        Box::new(*self)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fn reflect_hash(&self) -> Option<u64> {
 | 
					 | 
				
			||||||
        use std::hash::Hash;
 | 
					 | 
				
			||||||
        use std::hash::Hasher;
 | 
					 | 
				
			||||||
        let mut hasher = reflect_hasher();
 | 
					 | 
				
			||||||
        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.as_any();
 | 
					 | 
				
			||||||
        if let Some(value) = value.downcast_ref::<Self>() {
 | 
					 | 
				
			||||||
            Some(std::cmp::PartialEq::eq(self, value))
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Some(false)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl GetTypeRegistration for RenderAssetUsages {
 | 
					 | 
				
			||||||
    fn get_type_registration() -> TypeRegistration {
 | 
					 | 
				
			||||||
        let mut registration = TypeRegistration::of::<Self>();
 | 
					 | 
				
			||||||
        registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectDeserialize>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectDefault>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectFromReflect>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
 | 
					 | 
				
			||||||
        registration
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl FromReflect for RenderAssetUsages {
 | 
					 | 
				
			||||||
    fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
 | 
					 | 
				
			||||||
        let raw_value = *reflect.as_any().downcast_ref::<u8>()?;
 | 
					 | 
				
			||||||
        Self::from_bits(raw_value)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Typed for RenderAssetUsages {
 | 
					 | 
				
			||||||
    fn type_info() -> &'static TypeInfo {
 | 
					 | 
				
			||||||
        static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
 | 
					 | 
				
			||||||
        CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::<Self>()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// This plugin extracts the changed assets from the "app world" into the "render world"
 | 
					/// This plugin extracts the changed assets from the "app world" into the "render world"
 | 
				
			||||||
/// and prepares them for the GPU. They can then be accessed from the [`RenderAssets`] resource.
 | 
					/// and prepares them for the GPU. They can then be accessed from the [`RenderAssets`] resource.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user