diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 231ab7d0e0c58..39dca6fcb888f 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1868,6 +1868,21 @@ bevy_reflect::tests::Test { assert_eq!("123", format!("{:?}", foo)); } + #[test] + fn box_dyn_reflect() { + #[derive(Reflect)] + struct Foo { + a: u32, + } + + let boxed: Box = Box::new(Foo { a: 1 }); + + assert_eq!( + boxed.reflect_type_path(), + "std::boxed::Box(dyn bevy_reflect::Reflect)" + ); + } + #[test] fn recursive_typed_storage_does_not_hang() { #[derive(Reflect)] diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 458022566baa5..c788cb2136060 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -6,6 +6,7 @@ use crate::{ use std::{ any::{Any, TypeId}, fmt::Debug, + ops::{Deref, DerefMut}, }; use crate::utility::NonGenericTypeInfoCell; @@ -326,3 +327,91 @@ impl dyn Reflect { self.as_any_mut().downcast_mut::() } } + +impl TypePath for Box { + fn type_path() -> &'static str { + "std::boxed::Box(dyn bevy_reflect::Reflect)" + } + + fn short_type_path() -> &'static str { + "Box(dyn Reflect)" + } + + fn type_ident() -> Option<&'static str> { + Some("Box") + } + + fn crate_name() -> Option<&'static str> { + Some("std") + } + + fn module_path() -> Option<&'static str> { + Some("std::boxed") + } +} + +impl Reflect for Box { + fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { + self.deref().get_represented_type_info() + } + + fn into_any(self: Box) -> Box { + Box::new((*self).into_any()) + } + + fn as_any(&self) -> &dyn Any { + self.deref().as_any() + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self.deref_mut().as_any_mut() + } + + fn apply(&mut self, value: &dyn Reflect) { + self.deref_mut().apply(value); + } + + fn set(&mut self, value: Box) -> Result<(), Box> { + self.deref_mut().set(value) + } + + fn into_reflect(self: Box) -> Box { + Box::new((*self).into_reflect()) + } + + fn as_reflect(&self) -> &dyn Reflect { + self.deref().as_reflect() + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self.deref_mut().as_reflect_mut() + } + + fn reflect_ref(&self) -> ReflectRef { + self.deref().reflect_ref() + } + + fn reflect_mut(&mut self) -> ReflectMut { + self.deref_mut().reflect_mut() + } + + fn reflect_owned(self: Box) -> ReflectOwned { + (*self).reflect_owned() + } + + fn clone_value(&self) -> Box { + self.deref().clone_value() + } + + fn reflect_hash(&self) -> Option { + self.deref().reflect_hash() + } + + fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + self.deref().reflect_partial_eq(value) + } + + fn serializable(&self) -> Option { + self.deref().serializable() + } +} diff --git a/examples/reflection/reflection.rs b/examples/reflection/reflection.rs index 8f874633f8af6..085b4224e5d47 100644 --- a/examples/reflection/reflection.rs +++ b/examples/reflection/reflection.rs @@ -32,17 +32,20 @@ fn main() { /// how to handle the field. /// To do this, you can either define a `#[reflect(default = "...")]` attribute on the ignored field, or /// opt-out of `FromReflect`'s auto-derive using the `#[reflect(from_reflect = false)]` attribute. +/// +/// `Box` will forward all reflect methods to its inner value #[derive(Reflect)] #[reflect(from_reflect = false)] pub struct Foo { a: usize, nested: Bar, + boxed: Box, #[reflect(ignore)] _ignored: NonReflectedValue, } -/// This `Bar` type is used in the `nested` field on the `Test` type. We must derive `Reflect` here -/// too (or ignore it) +/// This `Bar` type is used in the `nested` and `boxed` fields on the `Test` type. +/// We must derive `Reflect` here too (or ignore it) #[derive(Reflect)] pub struct Bar { b: usize, @@ -58,6 +61,7 @@ fn setup(type_registry: Res) { a: 1, _ignored: NonReflectedValue { _a: 10 }, nested: Bar { b: 8 }, + boxed: Box::new(Bar { b: 4 }), }; // You can set field values like this. The type must match exactly or this will fail.