Skip to content

Implement Reflect for Box<dyn Reflect> #3400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn Reflect> = 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)]
Expand Down
89 changes: 89 additions & 0 deletions crates/bevy_reflect/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
use std::{
any::{Any, TypeId},
fmt::Debug,
ops::{Deref, DerefMut},
};

use crate::utility::NonGenericTypeInfoCell;
Expand Down Expand Up @@ -326,3 +327,91 @@ impl dyn Reflect {
self.as_any_mut().downcast_mut::<T>()
}
}

impl TypePath for Box<dyn Reflect> {
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<dyn Reflect> {
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
self.deref().get_represented_type_info()
}

fn into_any(self: Box<Self>) -> Box<dyn Any> {
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<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
self.deref_mut().set(value)
}

fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
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<Self>) -> ReflectOwned {
(*self).reflect_owned()
}

fn clone_value(&self) -> Box<dyn Reflect> {
self.deref().clone_value()
}

fn reflect_hash(&self) -> Option<u64> {
self.deref().reflect_hash()
}

fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
self.deref().reflect_partial_eq(value)
}

fn serializable(&self) -> Option<Serializable> {
self.deref().serializable()
}
}
8 changes: 6 additions & 2 deletions examples/reflection/reflection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn Reflect>,
#[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,
Expand All @@ -58,6 +61,7 @@ fn setup(type_registry: Res<AppTypeRegistry>) {
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.
Expand Down