Make some ReflectComponent/ReflectBundle methods work with EntityMut too (#12895)

# Objective

- Make `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` work with `EntityMut` too (currently they only
work with the more restricting `EntityWorldMut`);
- Note: support for the `Filtered*` variants has been left out since the
conversion in that case is more expensive. Let me know if I should add
support for them too.

## Solution

- Make `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` take an `impl Into<EntityMut<'a>>`;
- Make the corresponding `*Fns` function pointers take a `EntityMut`.

---

## Changelog

- `ReflectComponent::apply`, `ReflectComponent::reflect_mut` and
`ReflectBundle::apply` now accept `EntityMut` as well

## Migration Guide

- `ReflectComponentFns`'s `apply` and `reflect_mut` fields now take
`EntityMut` instead of `&mut EntityWorldMut`
- `ReflectBundleFns`'s `apply` field now takes `EntityMut` instead of
`&mut EntityWorldMut`
This commit is contained in:
Giacomo Stevanato 2024-04-08 03:46:07 +02:00 committed by GitHub
parent 31b5943ad4
commit 74f52076a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 37 deletions

View File

@ -6,7 +6,10 @@
//! Same as [`super::component`], but for bundles. //! Same as [`super::component`], but for bundles.
use std::any::TypeId; use std::any::TypeId;
use crate::{prelude::Bundle, world::EntityWorldMut}; use crate::{
prelude::Bundle,
world::{EntityMut, EntityWorldMut},
};
use bevy_reflect::{FromReflect, FromType, Reflect, ReflectRef, TypeRegistry}; use bevy_reflect::{FromReflect, FromType, Reflect, ReflectRef, TypeRegistry};
use super::ReflectComponent; use super::ReflectComponent;
@ -26,7 +29,7 @@ pub struct ReflectBundleFns {
/// Function pointer implementing [`ReflectBundle::insert()`]. /// Function pointer implementing [`ReflectBundle::insert()`].
pub insert: fn(&mut EntityWorldMut, &dyn Reflect), pub insert: fn(&mut EntityWorldMut, &dyn Reflect),
/// Function pointer implementing [`ReflectBundle::apply()`]. /// Function pointer implementing [`ReflectBundle::apply()`].
pub apply: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), pub apply: fn(EntityMut, &dyn Reflect, &TypeRegistry),
/// Function pointer implementing [`ReflectBundle::apply_or_insert()`]. /// Function pointer implementing [`ReflectBundle::apply_or_insert()`].
pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
/// Function pointer implementing [`ReflectBundle::remove()`]. /// Function pointer implementing [`ReflectBundle::remove()`].
@ -55,13 +58,13 @@ impl ReflectBundle {
/// # Panics /// # Panics
/// ///
/// Panics if there is no [`Bundle`] of the given type. /// Panics if there is no [`Bundle`] of the given type.
pub fn apply( pub fn apply<'a>(
&self, &self,
entity: &mut EntityWorldMut, entity: impl Into<EntityMut<'a>>,
bundle: &dyn Reflect, bundle: &dyn Reflect,
registry: &TypeRegistry, registry: &TypeRegistry,
) { ) {
(self.0.apply)(entity, bundle, registry); (self.0.apply)(entity.into(), bundle, registry);
} }
/// Uses reflection to set the value of this [`Bundle`] type in the entity to the given value or insert a new one if it does not exist. /// Uses reflection to set the value of this [`Bundle`] type in the entity to the given value or insert a new one if it does not exist.
@ -121,7 +124,7 @@ impl<B: Bundle + Reflect + FromReflect> FromType<B> for ReflectBundle {
let bundle = B::from_reflect(reflected_bundle).unwrap(); let bundle = B::from_reflect(reflected_bundle).unwrap();
entity.insert(bundle); entity.insert(bundle);
}, },
apply: |entity, reflected_bundle, registry| { apply: |mut entity, reflected_bundle, registry| {
if let Some(reflect_component) = if let Some(reflect_component) =
registry.get_type_data::<ReflectComponent>(TypeId::of::<B>()) registry.get_type_data::<ReflectComponent>(TypeId::of::<B>())
{ {
@ -130,10 +133,10 @@ impl<B: Bundle + Reflect + FromReflect> FromType<B> for ReflectBundle {
match reflected_bundle.reflect_ref() { match reflected_bundle.reflect_ref() {
ReflectRef::Struct(bundle) => bundle ReflectRef::Struct(bundle) => bundle
.iter_fields() .iter_fields()
.for_each(|field| insert_field(entity, field, registry)), .for_each(|field| apply_field(&mut entity, field, registry)),
ReflectRef::Tuple(bundle) => bundle ReflectRef::Tuple(bundle) => bundle
.iter_fields() .iter_fields()
.for_each(|field| insert_field(entity, field, registry)), .for_each(|field| apply_field(&mut entity, field, registry)),
_ => panic!( _ => panic!(
"expected bundle `{}` to be named struct or tuple", "expected bundle `{}` to be named struct or tuple",
// FIXME: once we have unique reflect, use `TypePath`. // FIXME: once we have unique reflect, use `TypePath`.
@ -170,29 +173,16 @@ impl<B: Bundle + Reflect + FromReflect> FromType<B> for ReflectBundle {
} }
} }
fn insert_field(entity: &mut EntityWorldMut, field: &dyn Reflect, registry: &TypeRegistry) { fn apply_field(entity: &mut EntityMut, field: &dyn Reflect, registry: &TypeRegistry) {
if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(field.type_id()) { if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(field.type_id()) {
reflect_component.apply(entity, field); reflect_component.apply(entity.reborrow(), field);
} else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(field.type_id()) { } else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(field.type_id()) {
reflect_bundle.apply(entity, field, registry); reflect_bundle.apply(entity.reborrow(), field, registry);
} else { } else {
let is_component = entity panic!(
.world() "no `ReflectComponent` nor `ReflectBundle` registration found for `{}`",
.components() field.reflect_type_path()
.get_id(field.type_id()) );
.is_some();
if is_component {
panic!(
"no `ReflectComponent` registration found for `{}`",
field.reflect_type_path(),
);
} else {
panic!(
"no `ReflectBundle` registration found for `{}`",
field.reflect_type_path(),
)
}
} }
} }

View File

@ -62,7 +62,7 @@ use crate::{
change_detection::Mut, change_detection::Mut,
component::Component, component::Component,
entity::Entity, entity::Entity,
world::{unsafe_world_cell::UnsafeEntityCell, EntityRef, EntityWorldMut, World}, world::{unsafe_world_cell::UnsafeEntityCell, EntityMut, EntityRef, EntityWorldMut, World},
}; };
use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry}; use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry};
@ -98,7 +98,7 @@ pub struct ReflectComponentFns {
/// Function pointer implementing [`ReflectComponent::insert()`]. /// Function pointer implementing [`ReflectComponent::insert()`].
pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
/// Function pointer implementing [`ReflectComponent::apply()`]. /// Function pointer implementing [`ReflectComponent::apply()`].
pub apply: fn(&mut EntityWorldMut, &dyn Reflect), pub apply: fn(EntityMut, &dyn Reflect),
/// Function pointer implementing [`ReflectComponent::apply_or_insert()`]. /// Function pointer implementing [`ReflectComponent::apply_or_insert()`].
pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
/// Function pointer implementing [`ReflectComponent::remove()`]. /// Function pointer implementing [`ReflectComponent::remove()`].
@ -108,7 +108,7 @@ pub struct ReflectComponentFns {
/// Function pointer implementing [`ReflectComponent::reflect()`]. /// Function pointer implementing [`ReflectComponent::reflect()`].
pub reflect: fn(EntityRef) -> Option<&dyn Reflect>, pub reflect: fn(EntityRef) -> Option<&dyn Reflect>,
/// Function pointer implementing [`ReflectComponent::reflect_mut()`]. /// Function pointer implementing [`ReflectComponent::reflect_mut()`].
pub reflect_mut: for<'a> fn(&'a mut EntityWorldMut<'_>) -> Option<Mut<'a, dyn Reflect>>, pub reflect_mut: fn(EntityMut) -> Option<Mut<dyn Reflect>>,
/// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`]. /// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`].
/// ///
/// # Safety /// # Safety
@ -145,8 +145,8 @@ impl ReflectComponent {
/// # Panics /// # Panics
/// ///
/// Panics if there is no [`Component`] of the given type. /// Panics if there is no [`Component`] of the given type.
pub fn apply(&self, entity: &mut EntityWorldMut, component: &dyn Reflect) { pub fn apply<'a>(&self, entity: impl Into<EntityMut<'a>>, component: &dyn Reflect) {
(self.0.apply)(entity, component); (self.0.apply)(entity.into(), 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. /// 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.
@ -177,9 +177,9 @@ impl ReflectComponent {
/// Gets the value of this [`Component`] type from the entity as a mutable reflected reference. /// Gets the value of this [`Component`] type from the entity as a mutable reflected reference.
pub fn reflect_mut<'a>( pub fn reflect_mut<'a>(
&self, &self,
entity: &'a mut EntityWorldMut<'_>, entity: impl Into<EntityMut<'a>>,
) -> Option<Mut<'a, dyn Reflect>> { ) -> Option<Mut<'a, dyn Reflect>> {
(self.0.reflect_mut)(entity) (self.0.reflect_mut)(entity.into())
} }
/// # Safety /// # Safety
@ -262,7 +262,7 @@ impl<C: Component + Reflect + FromReflect> FromType<C> for ReflectComponent {
}); });
entity.insert(component); entity.insert(component);
}, },
apply: |entity, reflected_component| { apply: |mut entity, reflected_component| {
let mut component = entity.get_mut::<C>().unwrap(); let mut component = entity.get_mut::<C>().unwrap();
component.apply(reflected_component); component.apply(reflected_component);
}, },
@ -290,7 +290,7 @@ impl<C: Component + Reflect + FromReflect> FromType<C> for ReflectComponent {
}, },
reflect: |entity| entity.get::<C>().map(|c| c as &dyn Reflect), reflect: |entity| entity.get::<C>().map(|c| c as &dyn Reflect),
reflect_mut: |entity| { reflect_mut: |entity| {
entity.get_mut::<C>().map(|c| Mut { entity.into_mut::<C>().map(|c| Mut {
value: c.value as &mut dyn Reflect, value: c.value as &mut dyn Reflect,
ticks: c.ticks, ticks: c.ticks,
}) })