From 74f52076a383d0636d3d5f4cf5b448aed19ddd3e Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Mon, 8 Apr 2024 03:46:07 +0200 Subject: [PATCH] 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>`; - 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` --- crates/bevy_ecs/src/reflect/bundle.rs | 46 ++++++++++-------------- crates/bevy_ecs/src/reflect/component.rs | 18 +++++----- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/bundle.rs b/crates/bevy_ecs/src/reflect/bundle.rs index 22905f53b8212..f89302a61d9e0 100644 --- a/crates/bevy_ecs/src/reflect/bundle.rs +++ b/crates/bevy_ecs/src/reflect/bundle.rs @@ -6,7 +6,10 @@ //! Same as [`super::component`], but for bundles. 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 super::ReflectComponent; @@ -26,7 +29,7 @@ pub struct ReflectBundleFns { /// Function pointer implementing [`ReflectBundle::insert()`]. pub insert: fn(&mut EntityWorldMut, &dyn Reflect), /// 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()`]. pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), /// Function pointer implementing [`ReflectBundle::remove()`]. @@ -55,13 +58,13 @@ impl ReflectBundle { /// # Panics /// /// Panics if there is no [`Bundle`] of the given type. - pub fn apply( + pub fn apply<'a>( &self, - entity: &mut EntityWorldMut, + entity: impl Into>, bundle: &dyn Reflect, 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. @@ -121,7 +124,7 @@ impl FromType for ReflectBundle { let bundle = B::from_reflect(reflected_bundle).unwrap(); entity.insert(bundle); }, - apply: |entity, reflected_bundle, registry| { + apply: |mut entity, reflected_bundle, registry| { if let Some(reflect_component) = registry.get_type_data::(TypeId::of::()) { @@ -130,10 +133,10 @@ impl FromType for ReflectBundle { match reflected_bundle.reflect_ref() { ReflectRef::Struct(bundle) => bundle .iter_fields() - .for_each(|field| insert_field(entity, field, registry)), + .for_each(|field| apply_field(&mut entity, field, registry)), ReflectRef::Tuple(bundle) => bundle .iter_fields() - .for_each(|field| insert_field(entity, field, registry)), + .for_each(|field| apply_field(&mut entity, field, registry)), _ => panic!( "expected bundle `{}` to be named struct or tuple", // FIXME: once we have unique reflect, use `TypePath`. @@ -170,29 +173,16 @@ impl FromType 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::(field.type_id()) { - reflect_component.apply(entity, field); + reflect_component.apply(entity.reborrow(), field); } else if let Some(reflect_bundle) = registry.get_type_data::(field.type_id()) { - reflect_bundle.apply(entity, field, registry); + reflect_bundle.apply(entity.reborrow(), field, registry); } else { - let is_component = entity - .world() - .components() - .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(), - ) - } + panic!( + "no `ReflectComponent` nor `ReflectBundle` registration found for `{}`", + field.reflect_type_path() + ); } } diff --git a/crates/bevy_ecs/src/reflect/component.rs b/crates/bevy_ecs/src/reflect/component.rs index de5a933131ca9..fdc42141c5c5e 100644 --- a/crates/bevy_ecs/src/reflect/component.rs +++ b/crates/bevy_ecs/src/reflect/component.rs @@ -62,7 +62,7 @@ use crate::{ change_detection::Mut, component::Component, 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}; @@ -98,7 +98,7 @@ pub struct ReflectComponentFns { /// Function pointer implementing [`ReflectComponent::insert()`]. pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), /// 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()`]. pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), /// Function pointer implementing [`ReflectComponent::remove()`]. @@ -108,7 +108,7 @@ pub struct ReflectComponentFns { /// Function pointer implementing [`ReflectComponent::reflect()`]. pub reflect: fn(EntityRef) -> Option<&dyn Reflect>, /// Function pointer implementing [`ReflectComponent::reflect_mut()`]. - pub reflect_mut: for<'a> fn(&'a mut EntityWorldMut<'_>) -> Option>, + pub reflect_mut: fn(EntityMut) -> Option>, /// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`]. /// /// # Safety @@ -145,8 +145,8 @@ impl ReflectComponent { /// # Panics /// /// Panics if there is no [`Component`] of the given type. - pub fn apply(&self, entity: &mut EntityWorldMut, component: &dyn Reflect) { - (self.0.apply)(entity, component); + pub fn apply<'a>(&self, entity: impl Into>, component: &dyn Reflect) { + (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. @@ -177,9 +177,9 @@ impl ReflectComponent { /// Gets the value of this [`Component`] type from the entity as a mutable reflected reference. pub fn reflect_mut<'a>( &self, - entity: &'a mut EntityWorldMut<'_>, + entity: impl Into>, ) -> Option> { - (self.0.reflect_mut)(entity) + (self.0.reflect_mut)(entity.into()) } /// # Safety @@ -262,7 +262,7 @@ impl FromType for ReflectComponent { }); entity.insert(component); }, - apply: |entity, reflected_component| { + apply: |mut entity, reflected_component| { let mut component = entity.get_mut::().unwrap(); component.apply(reflected_component); }, @@ -290,7 +290,7 @@ impl FromType for ReflectComponent { }, reflect: |entity| entity.get::().map(|c| c as &dyn Reflect), reflect_mut: |entity| { - entity.get_mut::().map(|c| Mut { + entity.into_mut::().map(|c| Mut { value: c.value as &mut dyn Reflect, ticks: c.ticks, })