diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index e49db629362f0..e61e27e5dced1 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -1,15 +1,10 @@ use crate::io::AssetSourceId; -use bevy_reflect::{ - std_traits::ReflectDefault, utility::NonGenericTypeInfoCell, FromReflect, FromType, - GetTypeRegistration, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect, - ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, TypeInfo, TypePath, - TypeRegistration, Typed, ValueInfo, -}; +use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use bevy_utils::CowArc; use serde::{de::Visitor, Deserialize, Serialize}; use std::{ fmt::{Debug, Display}, - hash::{Hash, Hasher}, + hash::Hash, ops::Deref, 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 /// clones internal owned [`AssetPaths`](AssetPath). /// 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> { source: AssetSourceId<'a>, 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::(); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::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::(); - TypeInfo::Value(info) - }) - } -} -impl Reflect for AssetPath<'static> { - #[inline] - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { - Some(::type_info()) - } - #[inline] - fn into_any(self: Box) -> Box { - 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) -> Box { - 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 = value.clone(); - } else { - panic!("Value is not {}.", std::any::type_name::()); - } - } - #[inline] - fn set( - &mut self, - value: Box, - ) -> Result<(), Box> { - *self = ::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) -> ReflectOwned { - ReflectOwned::Value(self) - } - #[inline] - fn clone_value(&self) -> Box { - Box::new(self.clone()) - } - fn reflect_hash(&self) -> Option { - 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 { - let value = ::as_any(value); - if let Some(value) = ::downcast_ref::(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 { - Some(Clone::clone(::downcast_ref::< - AssetPath<'static>, - >(::as_any(reflect))?)) - } -} - /// Normalizes the path by collapsing all occurrences of '.' and '..' dot-segments where possible /// as per [RFC 1808](https://datatracker.ietf.org/doc/html/rfc1808) pub(crate) fn normalize_path(path: &Path) -> PathBuf { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 3b50abb0d9fdf..f81db9d6c7506 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,17 +1,16 @@ use crate::std_traits::ReflectDefault; use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned, TypeRegistry}; use crate::{ - impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, - DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, - ListIter, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectKind, ReflectMut, - ReflectRef, ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, - UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, VariantInfo, VariantType, + impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicMap, + FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter, + Reflect, ReflectDeserialize, ReflectKind, ReflectMut, ReflectRef, ReflectSerialize, TypeInfo, + TypePath, TypeRegistration, Typed, ValueInfo, }; use crate::utility::{ 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::{ any::Any, @@ -996,252 +995,14 @@ impl GetTypeRegistr } } -impl GetTypeRegistration for Option { - fn get_type_registration() -> TypeRegistration { - TypeRegistration::of::>() - } - - fn register_type_dependencies(registry: &mut TypeRegistry) { - registry.register::(); +impl_reflect! { + #[type_path = "core::option"] + enum Option { + None, + Some(T), } } -impl Enum for Option { - 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 { - 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) - } -} - -impl Reflect for Option { - #[inline] - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { - Some(::type_info()) - } - - #[inline] - fn into_any(self: Box) -> Box { - 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) -> Box { - 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) -> Result<(), Box> { - *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) -> ReflectOwned { - ReflectOwned::Enum(self) - } - - #[inline] - fn clone_value(&self) -> Box { - Box::new(Enum::clone_dynamic(self)) - } - - fn reflect_hash(&self) -> Option { - crate::enum_hash(self) - } - - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - crate::enum_partial_eq(self, value) - } -} - -impl FromReflect for Option { - fn from_reflect(reflect: &dyn Reflect) -> Option { - 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::::type_path() - ) - }) - .clone_value(), - ) - .unwrap_or_else(|_| { - panic!( - "Field in `Some` variant of {} should be of type {}", - Option::::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 Typed for Option { - fn type_info() -> &'static TypeInfo { - static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); - CELL.get_or_insert::(|| { - let none_variant = VariantInfo::Unit(UnitVariantInfo::new("None")); - let some_variant = - VariantInfo::Tuple(TupleVariantInfo::new("Some", &[UnnamedField::new::(0)])); - TypeInfo::Enum(EnumInfo::new::(&[none_variant, some_variant])) - }) - } -} - -impl_type_path!(::core::option::Option); - impl TypePath for &'static T { fn type_path() -> &'static str { static CELL: GenericTypePathCell = GenericTypePathCell::new(); diff --git a/crates/bevy_render/src/render_asset.rs b/crates/bevy_render/src/render_asset.rs index 0af7b877854dc..6bf5ce9a6ea11 100644 --- a/crates/bevy_render/src/render_asset.rs +++ b/crates/bevy_render/src/render_asset.rs @@ -7,13 +7,7 @@ use bevy_ecs::{ system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState}, world::{FromWorld, Mut}, }; -use bevy_reflect::std_traits::ReflectDefault; -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_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use bevy_utils::{HashMap, HashSet}; use serde::{Deserialize, Serialize}; use std::marker::PhantomData; @@ -77,7 +71,8 @@ bitflags::bitflags! { /// [discussion about memory management](https://github.com/WebAssembly/design/issues/1397) for more /// details. #[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 { const MAIN_WORLD = 1 << 0; 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(::type_info()) - } - fn into_any(self: Box) -> Box { - 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) -> Box { - 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 = value; - } else { - panic!("Value is not a {}.", Self::type_path()); - } - } - fn set(&mut self, value: Box) -> Result<(), Box> { - *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) -> bevy_reflect::ReflectOwned { - ReflectOwned::Value(self) - } - fn clone_value(&self) -> Box { - Box::new(*self) - } - fn reflect_hash(&self) -> Option { - 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 { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { - Some(std::cmp::PartialEq::eq(self, value)) - } else { - Some(false) - } - } -} - -impl GetTypeRegistration for RenderAssetUsages { - fn get_type_registration() -> TypeRegistration { - let mut registration = TypeRegistration::of::(); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration - } -} - -impl FromReflect for RenderAssetUsages { - fn from_reflect(reflect: &dyn Reflect) -> Option { - let raw_value = *reflect.as_any().downcast_ref::()?; - 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::())) - } -} - /// 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. ///