Skip to content
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

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

Merged
merged 2 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 18 additions & 28 deletions crates/bevy_ecs/src/reflect/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()`].
Expand Down Expand Up @@ -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<EntityMut<'a>>,
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.
Expand Down Expand Up @@ -121,7 +124,7 @@ impl<B: Bundle + Reflect + FromReflect> FromType<B> 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::<ReflectComponent>(TypeId::of::<B>())
{
Expand All @@ -130,10 +133,10 @@ impl<B: Bundle + Reflect + FromReflect> FromType<B> 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`.
Expand Down Expand Up @@ -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()) {
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()) {
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()
);
}
}

Expand Down
18 changes: 9 additions & 9 deletions crates/bevy_ecs/src/reflect/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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()`].
Expand All @@ -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<Mut<'a, dyn Reflect>>,
pub reflect_mut: fn(EntityMut) -> Option<Mut<dyn Reflect>>,
/// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`].
///
/// # Safety
Expand Down Expand Up @@ -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<EntityMut<'a>>, 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.
Expand Down Expand Up @@ -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<EntityMut<'a>>,
) -> Option<Mut<'a, dyn Reflect>> {
(self.0.reflect_mut)(entity)
(self.0.reflect_mut)(entity.into())
}

/// # Safety
Expand Down Expand Up @@ -262,7 +262,7 @@ impl<C: Component + Reflect + FromReflect> FromType<C> for ReflectComponent {
});
entity.insert(component);
},
apply: |entity, reflected_component| {
apply: |mut entity, reflected_component| {
let mut component = entity.get_mut::<C>().unwrap();
component.apply(reflected_component);
},
Expand Down Expand Up @@ -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_mut: |entity| {
entity.get_mut::<C>().map(|c| Mut {
entity.into_mut::<C>().map(|c| Mut {
value: c.value as &mut dyn Reflect,
ticks: c.ticks,
})
Expand Down