-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
[Merged by Bors] - Enable Constructing ReflectComponent/Resource #6257
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,14 +17,55 @@ use bevy_reflect::{ | |
/// A [`ReflectComponent`] for type `T` can be obtained via | ||
/// [`bevy_reflect::TypeRegistration::data`]. | ||
#[derive(Clone)] | ||
pub struct ReflectComponent { | ||
insert: fn(&mut World, Entity, &dyn Reflect), | ||
apply: fn(&mut World, Entity, &dyn Reflect), | ||
apply_or_insert: fn(&mut World, Entity, &dyn Reflect), | ||
remove: fn(&mut World, Entity), | ||
reflect: fn(&World, Entity) -> Option<&dyn Reflect>, | ||
reflect_mut: unsafe fn(&World, Entity) -> Option<Mut<dyn Reflect>>, | ||
copy: fn(&World, &mut World, Entity, Entity), | ||
pub struct ReflectComponent(ReflectComponentFns); | ||
|
||
/// The raw function pointers needed to make up a [`ReflectComponent`]. | ||
/// | ||
/// This is used when creating custom implementations of [`ReflectComponent`] with | ||
/// [`ReflectComponent::new()`]. | ||
/// | ||
/// > **Note:** | ||
/// > Creating custom implementations of [`ReflectComponent`] is an advanced feature that most users | ||
/// > will not need. | ||
/// > Usually a [`ReflectComponent`] is created for a type by deriving [`Reflect`] | ||
/// > and adding the `#[reflect(Component)]` attribute. | ||
/// > After adding the component to the [`TypeRegistry`][bevy_reflect::TypeRegistry], | ||
/// > its [`ReflectComponent`] can then be retrieved when needed. | ||
/// | ||
/// Creating a custom [`ReflectComponent`] may be useful if you need to create new component types | ||
/// at runtime, for example, for scripting implementations. | ||
/// | ||
/// By creating a custom [`ReflectComponent`] and inserting it into a type's | ||
/// [`TypeRegistration`][bevy_reflect::TypeRegistration], | ||
/// you can modify the way that reflected components of that type will be inserted into the Bevy | ||
/// world. | ||
#[derive(Clone)] | ||
pub struct ReflectComponentFns { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these structs have their own There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's actually a good idea. I'm not 100% sure that there will be a use for overriding only some options, but it seems like it could happen. |
||
/// Function pointer implementing [`ReflectComponent::insert()`]. | ||
pub insert: fn(&mut World, Entity, &dyn Reflect), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a doc comment for each of these (same for |
||
/// Function pointer implementing [`ReflectComponent::apply()`]. | ||
pub apply: fn(&mut World, Entity, &dyn Reflect), | ||
/// Function pointer implementing [`ReflectComponent::apply_or_insert()`]. | ||
pub apply_or_insert: fn(&mut World, Entity, &dyn Reflect), | ||
/// Function pointer implementing [`ReflectComponent::remove()`]. | ||
pub remove: fn(&mut World, Entity), | ||
/// Function pointer implementing [`ReflectComponent::reflect()`]. | ||
pub reflect: fn(&World, Entity) -> Option<&dyn Reflect>, | ||
/// Function pointer implementing [`ReflectComponent::reflect_mut()`]. | ||
pub reflect_mut: unsafe fn(&World, Entity) -> Option<Mut<dyn Reflect>>, | ||
/// Function pointer implementing [`ReflectComponent::copy()`]. | ||
pub copy: fn(&World, &mut World, Entity, Entity), | ||
} | ||
|
||
impl ReflectComponentFns { | ||
/// Get the default set of [`ReflectComponentFns`] for a specific component type using its | ||
/// [`FromType`] implementation. | ||
/// | ||
/// This is useful if you want to start with the default implementation before overriding some | ||
/// of the functions to create a custom implementation. | ||
pub fn new<T: Component + Reflect + FromWorld>() -> Self { | ||
<ReflectComponent as FromType<T>>::from_type().0 | ||
} | ||
} | ||
|
||
impl ReflectComponent { | ||
|
@@ -34,7 +75,7 @@ impl ReflectComponent { | |
/// | ||
/// Panics if there is no such entity. | ||
pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { | ||
(self.insert)(world, entity, component); | ||
(self.0.insert)(world, entity, component); | ||
} | ||
|
||
/// Uses reflection to set the value of this [`Component`] type in the entity to the given value. | ||
|
@@ -43,7 +84,7 @@ impl ReflectComponent { | |
/// | ||
/// Panics if there is no [`Component`] of the given type or the `entity` does not exist. | ||
pub fn apply(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { | ||
(self.apply)(world, entity, component); | ||
(self.0.apply)(world, entity, component); | ||
} | ||
|
||
/// Uses reflection to set the value of this [`Component`] type in the entity to the given value or insert a new one if it does not exist. | ||
|
@@ -52,7 +93,7 @@ impl ReflectComponent { | |
/// | ||
/// Panics if the `entity` does not exist. | ||
pub fn apply_or_insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { | ||
(self.apply_or_insert)(world, entity, component); | ||
(self.0.apply_or_insert)(world, entity, component); | ||
} | ||
|
||
/// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist. | ||
|
@@ -61,12 +102,12 @@ impl ReflectComponent { | |
/// | ||
/// Panics if there is no [`Component`] of the given type or the `entity` does not exist. | ||
pub fn remove(&self, world: &mut World, entity: Entity) { | ||
(self.remove)(world, entity); | ||
(self.0.remove)(world, entity); | ||
} | ||
|
||
/// Gets the value of this [`Component`] type from the entity as a reflected reference. | ||
pub fn reflect<'a>(&self, world: &'a World, entity: Entity) -> Option<&'a dyn Reflect> { | ||
(self.reflect)(world, entity) | ||
(self.0.reflect)(world, entity) | ||
} | ||
|
||
/// Gets the value of this [`Component`] type from the entity as a mutable reflected reference. | ||
|
@@ -76,7 +117,7 @@ impl ReflectComponent { | |
entity: Entity, | ||
) -> Option<Mut<'a, dyn Reflect>> { | ||
// SAFETY: unique world access | ||
unsafe { (self.reflect_mut)(world, entity) } | ||
unsafe { (self.0.reflect_mut)(world, entity) } | ||
} | ||
|
||
/// # Safety | ||
|
@@ -90,7 +131,7 @@ impl ReflectComponent { | |
world: &'a World, | ||
entity: Entity, | ||
) -> Option<Mut<'a, dyn Reflect>> { | ||
(self.reflect_mut)(world, entity) | ||
(self.0.reflect_mut)(world, entity) | ||
} | ||
|
||
/// Gets the value of this [`Component`] type from entity from `source_world` and [applies](Self::apply()) it to the value of this [`Component`] type in entity in `destination_world`. | ||
|
@@ -105,18 +146,33 @@ impl ReflectComponent { | |
source_entity: Entity, | ||
destination_entity: Entity, | ||
) { | ||
(self.copy)( | ||
(self.0.copy)( | ||
source_world, | ||
destination_world, | ||
source_entity, | ||
destination_entity, | ||
); | ||
} | ||
|
||
/// Create a custom implementation of [`ReflectComponent`]. | ||
/// | ||
/// This is an advanced feature, | ||
/// useful for scripting implementations, | ||
/// that should not be used by most users | ||
/// unless you know what you are doing. | ||
/// | ||
/// Usually you should derive [`Reflect`] and add the `#[reflect(Component)]` component | ||
/// to generate a [`ReflectComponent`] implementation automatically. | ||
/// | ||
/// See [`ReflectComponentFns`] for more information. | ||
pub fn new(fns: ReflectComponentFns) -> Self { | ||
Self(fns) | ||
} | ||
} | ||
|
||
impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent { | ||
fn from_type() -> Self { | ||
ReflectComponent { | ||
ReflectComponent(ReflectComponentFns { | ||
insert: |world, entity, reflected_component| { | ||
let mut component = C::from_world(world); | ||
component.apply(reflected_component); | ||
|
@@ -165,7 +221,7 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent { | |
}) | ||
} | ||
}, | ||
} | ||
}) | ||
} | ||
} | ||
|
||
|
@@ -174,20 +230,61 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent { | |
/// A [`ReflectResource`] for type `T` can be obtained via | ||
/// [`bevy_reflect::TypeRegistration::data`]. | ||
#[derive(Clone)] | ||
pub struct ReflectResource { | ||
insert: fn(&mut World, &dyn Reflect), | ||
apply: fn(&mut World, &dyn Reflect), | ||
apply_or_insert: fn(&mut World, &dyn Reflect), | ||
remove: fn(&mut World), | ||
reflect: fn(&World) -> Option<&dyn Reflect>, | ||
reflect_unchecked_mut: unsafe fn(&World) -> Option<Mut<dyn Reflect>>, | ||
copy: fn(&World, &mut World), | ||
pub struct ReflectResource(ReflectResourceFns); | ||
|
||
/// The raw function pointers needed to make up a [`ReflectResource`]. | ||
/// | ||
/// This is used when creating custom implementations of [`ReflectResource`] with | ||
/// [`ReflectResource::new()`]. | ||
/// | ||
/// > **Note:** | ||
/// > Creating custom implementations of [`ReflectResource`] is an advanced feature that most users | ||
/// > will not need. | ||
/// > Usually a [`ReflectResource`] is created for a type by deriving [`Reflect`] | ||
/// > and adding the `#[reflect(Resource)]` attribute. | ||
/// > After adding the component to the [`TypeRegistry`][bevy_reflect::TypeRegistry], | ||
/// > its [`ReflectResource`] can then be retrieved when needed. | ||
/// | ||
/// Creating a custom [`ReflectResource`] may be useful if you need to create new resource types at | ||
/// runtime, for example, for scripting implementations. | ||
/// | ||
/// By creating a custom [`ReflectResource`] and inserting it into a type's | ||
/// [`TypeRegistration`][bevy_reflect::TypeRegistration], | ||
/// you can modify the way that reflected resources of that type will be inserted into the bevy | ||
/// world. | ||
#[derive(Clone)] | ||
pub struct ReflectResourceFns { | ||
/// Function pointer implementing [`ReflectResource::insert()`]. | ||
pub insert: fn(&mut World, &dyn Reflect), | ||
/// Function pointer implementing [`ReflectResource::apply()`]. | ||
pub apply: fn(&mut World, &dyn Reflect), | ||
/// Function pointer implementing [`ReflectResource::apply_or_insert()`]. | ||
pub apply_or_insert: fn(&mut World, &dyn Reflect), | ||
/// Function pointer implementing [`ReflectResource::remove()`]. | ||
pub remove: fn(&mut World), | ||
/// Function pointer implementing [`ReflectResource::reflect()`]. | ||
pub reflect: fn(&World) -> Option<&dyn Reflect>, | ||
/// Function pointer implementing [`ReflectResource::reflect_unchecked_mut()`]. | ||
pub reflect_unchecked_mut: unsafe fn(&World) -> Option<Mut<dyn Reflect>>, | ||
/// Function pointer implementing [`ReflectResource::copy()`]. | ||
pub copy: fn(&World, &mut World), | ||
} | ||
|
||
impl ReflectResourceFns { | ||
/// Get the default set of [`ReflectResourceFns`] for a specific resource type using its | ||
/// [`FromType`] implementation. | ||
/// | ||
/// This is useful if you want to start with the default implementation before overriding some | ||
/// of the functions to create a custom implementation. | ||
pub fn new<T: Resource + Reflect + FromWorld>() -> Self { | ||
<ReflectResource as FromType<T>>::from_type().0 | ||
} | ||
} | ||
|
||
impl ReflectResource { | ||
/// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource). | ||
pub fn insert(&self, world: &mut World, resource: &dyn Reflect) { | ||
(self.insert)(world, resource); | ||
(self.0.insert)(world, resource); | ||
} | ||
|
||
/// Uses reflection to set the value of this [`Resource`] type in the world to the given value. | ||
|
@@ -196,28 +293,28 @@ impl ReflectResource { | |
/// | ||
/// Panics if there is no [`Resource`] of the given type. | ||
pub fn apply(&self, world: &mut World, resource: &dyn Reflect) { | ||
(self.apply)(world, resource); | ||
(self.0.apply)(world, resource); | ||
} | ||
|
||
/// Uses reflection to set the value of this [`Resource`] type in the world to the given value or insert a new one if it does not exist. | ||
pub fn apply_or_insert(&self, world: &mut World, resource: &dyn Reflect) { | ||
(self.apply_or_insert)(world, resource); | ||
(self.0.apply_or_insert)(world, resource); | ||
} | ||
|
||
/// Removes this [`Resource`] type from the world. Does nothing if it doesn't exist. | ||
pub fn remove(&self, world: &mut World) { | ||
(self.remove)(world); | ||
(self.0.remove)(world); | ||
} | ||
|
||
/// Gets the value of this [`Resource`] type from the world as a reflected reference. | ||
pub fn reflect<'a>(&self, world: &'a World) -> Option<&'a dyn Reflect> { | ||
(self.reflect)(world) | ||
(self.0.reflect)(world) | ||
} | ||
|
||
/// Gets the value of this [`Resource`] type from the world as a mutable reflected reference. | ||
pub fn reflect_mut<'a>(&self, world: &'a mut World) -> Option<Mut<'a, dyn Reflect>> { | ||
// SAFETY: unique world access | ||
unsafe { (self.reflect_unchecked_mut)(world) } | ||
unsafe { (self.0.reflect_unchecked_mut)(world) } | ||
} | ||
|
||
/// # Safety | ||
|
@@ -231,7 +328,7 @@ impl ReflectResource { | |
world: &'a World, | ||
) -> Option<Mut<'a, dyn Reflect>> { | ||
// SAFETY: caller promises to uphold uniqueness guarantees | ||
(self.reflect_unchecked_mut)(world) | ||
(self.0.reflect_unchecked_mut)(world) | ||
} | ||
|
||
/// Gets the value of this [`Resource`] type from `source_world` and [applies](Self::apply()) it to the value of this [`Resource`] type in `destination_world`. | ||
|
@@ -240,13 +337,28 @@ impl ReflectResource { | |
/// | ||
/// Panics if there is no [`Resource`] of the given type. | ||
pub fn copy(&self, source_world: &World, destination_world: &mut World) { | ||
(self.copy)(source_world, destination_world); | ||
(self.0.copy)(source_world, destination_world); | ||
} | ||
|
||
/// Create a custom implementation of [`ReflectResource`]. | ||
/// | ||
/// This is an advanced feature, | ||
/// useful for scripting implementations, | ||
/// that should not be used by most users | ||
/// unless you know what you are doing. | ||
/// | ||
/// Usually you should derive [`Reflect`] and add the `#[reflect(Resource)]` component | ||
/// to generate a [`ReflectResource`] implementation automatically. | ||
/// | ||
/// See [`ReflectResourceFns`] for more information. | ||
pub fn new(&self, fns: ReflectResourceFns) -> Self { | ||
Self(fns) | ||
} | ||
} | ||
|
||
impl<C: Resource + Reflect + FromWorld> FromType<C> for ReflectResource { | ||
fn from_type() -> Self { | ||
ReflectResource { | ||
ReflectResource(ReflectResourceFns { | ||
insert: |world, reflected_resource| { | ||
let mut resource = C::from_world(world); | ||
resource.apply(reflected_resource); | ||
|
@@ -285,7 +397,7 @@ impl<C: Resource + Reflect + FromWorld> FromType<C> for ReflectResource { | |
destination_resource.apply(source_resource); | ||
destination_world.insert_resource(destination_resource); | ||
}, | ||
} | ||
}) | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should link to / explain the simpler way here. Ditto for the resource equivalent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. We should probably also include it in the docs for the constructors (e.g.
ReflectComponent::new
) as well, and indicate that this is almost certainly not needed unless you know what you're doing.