Skip to content

Commit e1d741a

Browse files
committed
bevy_ecs: ReflectComponentFns without World (#7206)
# Objective Ability to use `ReflectComponent` methods in dynamic type contexts with no access to `&World`. This problem occurred to me when wanting to apply reflected types to an entity where the `&World` reference was already consumed by query iterator leaving only `EntityMut`. ## Solution - Remove redundant `EntityMut` or `EntityRef` lookup from `World` and `Entity` in favor of taking `EntityMut` directly in `ReflectComponentFns`. - Added `RefectComponent::contains` to determine without panic whether `apply` can be used. ## Changelog - Changed function signatures of `ReflectComponent` methods, `apply`, `remove`, `contains`, and `reflect`. ## Migration Guide - Call `World::entity` before calling into the changed `ReflectComponent` methods, most likely user already has a `EntityRef` or `EntityMut` which was being queried redundantly.
1 parent 4f3ed19 commit e1d741a

File tree

3 files changed

+67
-67
lines changed

3 files changed

+67
-67
lines changed

crates/bevy_ecs/src/reflect.rs

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use crate::{
55
component::Component,
66
entity::{Entity, EntityMap, MapEntities, MapEntitiesError},
77
system::Resource,
8-
world::{unsafe_world_cell::UnsafeWorldCell, FromWorld, World},
8+
world::{
9+
unsafe_world_cell::{UnsafeWorldCell, UnsafeWorldCellEntityRef},
10+
EntityMut, EntityRef, FromWorld, World,
11+
},
912
};
1013
use bevy_reflect::{
1114
impl_from_reflect_value, impl_reflect_value, FromType, Reflect, ReflectDeserialize,
@@ -42,20 +45,25 @@ pub struct ReflectComponent(ReflectComponentFns);
4245
#[derive(Clone)]
4346
pub struct ReflectComponentFns {
4447
/// Function pointer implementing [`ReflectComponent::insert()`].
45-
pub insert: fn(&mut World, Entity, &dyn Reflect),
48+
pub insert: fn(&mut EntityMut, &dyn Reflect),
4649
/// Function pointer implementing [`ReflectComponent::apply()`].
47-
pub apply: fn(&mut World, Entity, &dyn Reflect),
50+
pub apply: fn(&mut EntityMut, &dyn Reflect),
4851
/// Function pointer implementing [`ReflectComponent::apply_or_insert()`].
49-
pub apply_or_insert: fn(&mut World, Entity, &dyn Reflect),
52+
pub apply_or_insert: fn(&mut EntityMut, &dyn Reflect),
5053
/// Function pointer implementing [`ReflectComponent::remove()`].
51-
pub remove: fn(&mut World, Entity),
54+
pub remove: fn(&mut EntityMut),
55+
/// Function pointer implementing [`ReflectComponent::contains()`].
56+
pub contains: fn(EntityRef) -> bool,
5257
/// Function pointer implementing [`ReflectComponent::reflect()`].
53-
pub reflect: fn(&World, Entity) -> Option<&dyn Reflect>,
58+
pub reflect: fn(EntityRef) -> Option<&dyn Reflect>,
5459
/// Function pointer implementing [`ReflectComponent::reflect_mut()`].
60+
pub reflect_mut: for<'a> fn(&'a mut EntityMut<'_>) -> Option<Mut<'a, dyn Reflect>>,
61+
/// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`].
5562
///
5663
/// # Safety
57-
/// The function may only be called with an [`UnsafeWorldCell`] that can be used to mutably access the relevant component on the given entity.
58-
pub reflect_mut: unsafe fn(UnsafeWorldCell<'_>, Entity) -> Option<Mut<'_, dyn Reflect>>,
64+
/// The function may only be called with an [`UnsafeWorldCellEntityRef`] that can be used to mutably access the relevant component on the given entity.
65+
pub reflect_unchecked_mut:
66+
unsafe fn(UnsafeWorldCellEntityRef<'_>) -> Option<Mut<'_, dyn Reflect>>,
5967
/// Function pointer implementing [`ReflectComponent::copy()`].
6068
pub copy: fn(&World, &mut World, Entity, Entity),
6169
}
@@ -73,68 +81,59 @@ impl ReflectComponentFns {
7381

7482
impl ReflectComponent {
7583
/// Insert a reflected [`Component`] into the entity like [`insert()`](crate::world::EntityMut::insert).
76-
///
77-
/// # Panics
78-
///
79-
/// Panics if there is no such entity.
80-
pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
81-
(self.0.insert)(world, entity, component);
84+
pub fn insert(&self, entity: &mut EntityMut, component: &dyn Reflect) {
85+
(self.0.insert)(entity, component);
8286
}
8387

8488
/// Uses reflection to set the value of this [`Component`] type in the entity to the given value.
8589
///
8690
/// # Panics
8791
///
88-
/// Panics if there is no [`Component`] of the given type or the `entity` does not exist.
89-
pub fn apply(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
90-
(self.0.apply)(world, entity, component);
92+
/// Panics if there is no [`Component`] of the given type.
93+
pub fn apply(&self, entity: &mut EntityMut, component: &dyn Reflect) {
94+
(self.0.apply)(entity, component);
9195
}
9296

9397
/// 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.
94-
///
95-
/// # Panics
96-
///
97-
/// Panics if the `entity` does not exist.
98-
pub fn apply_or_insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) {
99-
(self.0.apply_or_insert)(world, entity, component);
98+
pub fn apply_or_insert(&self, entity: &mut EntityMut, component: &dyn Reflect) {
99+
(self.0.apply_or_insert)(entity, component);
100100
}
101101

102102
/// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist.
103103
///
104104
/// # Panics
105105
///
106-
/// Panics if there is no [`Component`] of the given type or the `entity` does not exist.
107-
pub fn remove(&self, world: &mut World, entity: Entity) {
108-
(self.0.remove)(world, entity);
106+
/// Panics if there is no [`Component`] of the given type.
107+
pub fn remove(&self, entity: &mut EntityMut) {
108+
(self.0.remove)(entity);
109+
}
110+
111+
/// Returns whether entity contains this [`Component`]
112+
pub fn contains(&self, entity: EntityRef) -> bool {
113+
(self.0.contains)(entity)
109114
}
110115

111116
/// Gets the value of this [`Component`] type from the entity as a reflected reference.
112-
pub fn reflect<'a>(&self, world: &'a World, entity: Entity) -> Option<&'a dyn Reflect> {
113-
(self.0.reflect)(world, entity)
117+
pub fn reflect<'a>(&self, entity: EntityRef<'a>) -> Option<&'a dyn Reflect> {
118+
(self.0.reflect)(entity)
114119
}
115120

116121
/// Gets the value of this [`Component`] type from the entity as a mutable reflected reference.
117-
pub fn reflect_mut<'a>(
118-
&self,
119-
world: &'a mut World,
120-
entity: Entity,
121-
) -> Option<Mut<'a, dyn Reflect>> {
122-
// SAFETY: unique world access
123-
unsafe { (self.0.reflect_mut)(world.as_unsafe_world_cell(), entity) }
122+
pub fn reflect_mut<'a>(&self, entity: &'a mut EntityMut<'_>) -> Option<Mut<'a, dyn Reflect>> {
123+
(self.0.reflect_mut)(entity)
124124
}
125125

126126
/// # Safety
127127
/// This method does not prevent you from having two mutable pointers to the same data,
128128
/// violating Rust's aliasing rules. To avoid this:
129-
/// * Only call this method with a [`UnsafeWorldCell`] that may be used to mutably access the component on the entity `entity`
129+
/// * Only call this method with a [`UnsafeWorldCellEntityRef`] that may be used to mutably access the component on the entity `entity`
130130
/// * Don't call this method more than once in the same scope for a given [`Component`].
131131
pub unsafe fn reflect_unchecked_mut<'a>(
132132
&self,
133-
world: UnsafeWorldCell<'a>,
134-
entity: Entity,
133+
entity: UnsafeWorldCellEntityRef<'a>,
135134
) -> Option<Mut<'a, dyn Reflect>> {
136135
// SAFETY: safety requirements deferred to caller
137-
(self.0.reflect_mut)(world, entity)
136+
(self.0.reflect_unchecked_mut)(entity)
138137
}
139138

140139
/// 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`.
@@ -176,27 +175,28 @@ impl ReflectComponent {
176175
impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
177176
fn from_type() -> Self {
178177
ReflectComponent(ReflectComponentFns {
179-
insert: |world, entity, reflected_component| {
180-
let mut component = C::from_world(world);
178+
insert: |entity, reflected_component| {
179+
let mut component = entity.world_scope(|world| C::from_world(world));
181180
component.apply(reflected_component);
182-
world.entity_mut(entity).insert(component);
181+
entity.insert(component);
183182
},
184-
apply: |world, entity, reflected_component| {
185-
let mut component = world.get_mut::<C>(entity).unwrap();
183+
apply: |entity, reflected_component| {
184+
let mut component = entity.get_mut::<C>().unwrap();
186185
component.apply(reflected_component);
187186
},
188-
apply_or_insert: |world, entity, reflected_component| {
189-
if let Some(mut component) = world.get_mut::<C>(entity) {
187+
apply_or_insert: |entity, reflected_component| {
188+
if let Some(mut component) = entity.get_mut::<C>() {
190189
component.apply(reflected_component);
191190
} else {
192-
let mut component = C::from_world(world);
191+
let mut component = entity.world_scope(|world| C::from_world(world));
193192
component.apply(reflected_component);
194-
world.entity_mut(entity).insert(component);
193+
entity.insert(component);
195194
}
196195
},
197-
remove: |world, entity| {
198-
world.entity_mut(entity).remove::<C>();
196+
remove: |entity| {
197+
entity.remove::<C>();
199198
},
199+
contains: |entity| entity.contains::<C>(),
200200
copy: |source_world, destination_world, source_entity, destination_entity| {
201201
let source_component = source_world.get::<C>(source_entity).unwrap();
202202
let mut destination_component = C::from_world(destination_world);
@@ -205,18 +205,18 @@ impl<C: Component + Reflect + FromWorld> FromType<C> for ReflectComponent {
205205
.entity_mut(destination_entity)
206206
.insert(destination_component);
207207
},
208-
reflect: |world, entity| {
209-
world
210-
.get_entity(entity)?
211-
.get::<C>()
212-
.map(|c| c as &dyn Reflect)
208+
reflect: |entity| entity.get::<C>().map(|c| c as &dyn Reflect),
209+
reflect_mut: |entity| {
210+
entity.get_mut::<C>().map(|c| Mut {
211+
value: c.value as &mut dyn Reflect,
212+
ticks: c.ticks,
213+
})
213214
},
214-
reflect_mut: |world, entity| {
215-
// SAFETY: reflect_mut is an unsafe function pointer used by
216-
// 1. `reflect_unchecked_mut` which must be called with an UnsafeWorldCell with access to the the component `C` on the `entity`, and
217-
// 2. `reflect_mut`, which has mutable world access
215+
reflect_unchecked_mut: |entity| {
216+
// SAFETY: reflect_unchecked_mut is an unsafe function pointer used by
217+
// `reflect_unchecked_mut` which must be called with an UnsafeWorldCellEntityRef with access to the the component `C` on the `entity`
218218
unsafe {
219-
world.get_entity(entity)?.get_mut::<C>().map(|c| Mut {
219+
entity.get_mut::<C>().map(|c| Mut {
220220
value: c.value as &mut dyn Reflect,
221221
ticks: c.ticks,
222222
})

crates/bevy_scene/src/dynamic_scene.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl DynamicScene {
7171
let entity = *entity_map
7272
.entry(bevy_ecs::entity::Entity::from_raw(scene_entity.entity))
7373
.or_insert_with(|| world.spawn_empty().id());
74+
let entity_mut = &mut world.entity_mut(entity);
7475

7576
// Apply/ add each component to the given entity.
7677
for component in &scene_entity.components {
@@ -89,7 +90,7 @@ impl DynamicScene {
8990
// If the entity already has the given component attached,
9091
// just apply the (possibly) new value, otherwise add the
9192
// component to the entity.
92-
reflect_component.apply_or_insert(world, entity, &**component);
93+
reflect_component.apply_or_insert(entity_mut, &**component);
9394
}
9495
}
9596

crates/bevy_scene/src/dynamic_scene_builder.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,18 @@ impl<'w> DynamicSceneBuilder<'w> {
124124
components: Vec::new(),
125125
};
126126

127-
for component_id in self.original_world.entity(entity).archetype().components() {
127+
let entity = self.original_world.entity(entity);
128+
for component_id in entity.archetype().components() {
128129
let reflect_component = self
129130
.original_world
130131
.components()
131132
.get_info(component_id)
132133
.and_then(|info| type_registry.get(info.type_id().unwrap()))
133-
.and_then(|registration| registration.data::<ReflectComponent>());
134+
.and_then(|registration| registration.data::<ReflectComponent>())
135+
.and_then(|reflect_component| reflect_component.reflect(entity));
134136

135137
if let Some(reflect_component) = reflect_component {
136-
if let Some(component) = reflect_component.reflect(self.original_world, entity)
137-
{
138-
entry.components.push(component.clone_value());
139-
}
138+
entry.components.push(reflect_component.clone_value());
140139
}
141140
}
142141
self.extracted_scene.insert(index, entry);

0 commit comments

Comments
 (0)