Skip to content

Commit 41f59f1

Browse files
authored
TypeData dependencies (#22016)
# Objective The proposed ["Resources as entities"](#20934 ) PR makes Resource implement Component. This creates a situation where we need to do: ```rust #[derive(Resource, Reflect)] #[reflect(Resource, Component)] struct Thing; ``` I'm of the mind that we should add the ability for TypeData to have "dependencies". Ex `reflect(Resource)` implies `reflect(Component)`. For "subtrait" types, I think supporting this is logical / users would appreciate it. ## Solution 1. Add a new `FromType<T>::insert_dependencies` function with a default impl (which makes this a non-breaking change). This does kind of overload the `FromType` trait (ex: a name like `GetTypeData` might be better with this new context), but this is a pretty niche trait / piece of functionality, and I like the idea of not breaking people. 2. Add a new `TypeRegistration::register_type_data<T, V>` function, which initializes the TypeData `T` for a given type `V` , inserts that type data, and also inserts any dependent type data using `insert_dependencies`. 3. Adjust the `Reflect` macro to use `register_type_data` instead of `insert(FromType::<Self>::from_type())` This makes it possible to do the following: ```rust impl<R: Resource + FromReflect + TypePath> FromType<R> for ReflectResource { fn from_type() -> Self { ReflectResource } fn insert_dependencies(type_registration: &mut TypeRegistration) { type_registration.register_type_data::<ReflectComponent, R>(); } } ``` Which then allows dropping `reflect(Component)`: ```rust #[derive(Resource, Reflect)] #[reflect(Resource)] struct Thing; ``` ## Testing I added a unit test 😜
1 parent aa14ada commit 41f59f1

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

crates/bevy_reflect/derive/src/registration.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(crate) fn impl_get_type_registration<'a>(
4949
registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::<Self>::from_type());
5050
#from_reflect_data
5151
#serialization_data
52-
#(registration.insert::<#registration_data>(#bevy_reflect_path::FromType::<Self>::from_type());)*
52+
#(registration.register_type_data::<#registration_data, Self>();)*
5353
registration
5454
}
5555

crates/bevy_reflect/src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,6 +3606,36 @@ bevy_reflect::tests::Test {
36063606
assert!(registry.contains(TypeId::of::<OpaqueStructReflect>()));
36073607
assert!(registry.contains(TypeId::of::<ZSTOpaqueStructReflect>()));
36083608
}
3609+
3610+
#[test]
3611+
fn type_data_dependency() {
3612+
#[derive(Reflect)]
3613+
#[reflect(A)]
3614+
struct X;
3615+
3616+
#[derive(Clone)]
3617+
struct ReflectA;
3618+
3619+
impl<T> FromType<T> for ReflectA {
3620+
fn from_type() -> Self {
3621+
ReflectA
3622+
}
3623+
3624+
fn insert_dependencies(type_registration: &mut TypeRegistration) {
3625+
type_registration.insert(ReflectB);
3626+
}
3627+
}
3628+
3629+
#[derive(Clone)]
3630+
struct ReflectB;
3631+
3632+
let mut registry = TypeRegistry::new();
3633+
registry.register::<X>();
3634+
3635+
let registration = registry.get(TypeId::of::<X>()).unwrap();
3636+
assert!(registration.data::<ReflectA>().is_some());
3637+
assert!(registration.data::<ReflectB>().is_some());
3638+
}
36093639
}
36103640

36113641
#[cfg(feature = "glam")]

crates/bevy_reflect/src/type_registry.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,13 @@ impl TypeRegistration {
588588
self.data.insert(TypeId::of::<T>(), Box::new(data));
589589
}
590590

591+
/// Inserts the [`TypeData`] instance of `T` created for `V`, and inserts any
592+
/// [`TypeData`] dependencies for that combination of `T` and `V`.
593+
pub fn register_type_data<T: TypeData + FromType<V>, V>(&mut self) {
594+
self.insert(T::from_type());
595+
T::insert_dependencies(self);
596+
}
597+
591598
/// Returns a reference to the value of type `T` in this registration's
592599
/// [type data].
593600
///
@@ -747,6 +754,10 @@ where
747754
pub trait FromType<T> {
748755
/// Creates an instance of `Self` for type `T`.
749756
fn from_type() -> Self;
757+
/// Inserts [`TypeData`] dependencies of this [`TypeData`].
758+
/// This is especially useful for trait [`TypeData`] that has a supertrait (ex: `A: B`).
759+
/// When the [`TypeData`] for `A` is inserted, the `B` [`TypeData`] will also be inserted.
760+
fn insert_dependencies(_type_registration: &mut TypeRegistration) {}
750761
}
751762

752763
/// A struct used to serialize reflected instances of a type.

0 commit comments

Comments
 (0)