Skip to content

Commit ef85d54

Browse files
add EntityRef::get_unchecked_mut_by_id
1 parent f5bdeb9 commit ef85d54

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,31 @@ impl<'w> EntityRef<'w> {
189189
)
190190
}
191191
}
192+
193+
/// Gets the component of the given [`ComponentId`] from the entity.
194+
///
195+
/// **You should prefer to use the typed API where possible and only
196+
/// use this in cases where the actual component types are not known at
197+
/// compile time.**
198+
///
199+
/// Unlike [`EntityRef::get`], this returns a raw pointer to the component,
200+
/// which is only valid while the `'w` borrow of the lifetime is active.
201+
///
202+
/// # Safety
203+
///
204+
/// - The returned reference must never alias a mutable borrow of this component.
205+
/// - The returned reference must not be used after this component is moved which
206+
/// may happen from **any** `insert_component`, `remove_component` or `despawn`
207+
/// operation on this world (non-exhaustive list).
208+
#[inline]
209+
pub unsafe fn get_unchecked_mut_by_id(
210+
&self,
211+
component_id: ComponentId,
212+
) -> Option<MutUntyped<'w>> {
213+
self.world.components().get_info(component_id)?;
214+
// SAFETY: entity_location is valid, component_id is valid as checked by the line above, world access is promised by the caller
215+
get_mut_by_id(self.world, self.entity, self.location, component_id)
216+
}
192217
}
193218

194219
impl<'w> From<EntityMut<'w>> for EntityRef<'w> {
@@ -692,7 +717,7 @@ impl<'w> EntityMut<'w> {
692717
#[inline]
693718
pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
694719
self.world.components().get_info(component_id)?;
695-
// SAFETY: entity_location is valid, component_id is valid as checked by the line above
720+
// SAFETY: entity_location is valid, component_id is valid as checked by the line above, world access is unique
696721
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
697722
}
698723
}
@@ -1064,21 +1089,26 @@ pub(crate) unsafe fn get_mut<T: Component>(
10641089
})
10651090
}
10661091

1067-
// SAFETY: EntityLocation must be valid, component_id must be valid
1092+
// SAFETY:
1093+
// - EntityLocation must be valid, component_id must be valid
1094+
// - world access to the component must be valid, either because the caller has a `&mut` world or it synchronizes access like systems do
10681095
#[inline]
10691096
pub(crate) unsafe fn get_mut_by_id(
1070-
world: &mut World,
1097+
world: &World,
10711098
entity: Entity,
10721099
location: EntityLocation,
10731100
component_id: ComponentId,
10741101
) -> Option<MutUntyped> {
1075-
let change_tick = world.change_tick();
10761102
let info = world.components.get_info_unchecked(component_id);
1077-
// SAFETY: world access is unique, entity location and component_id required to be valid
1103+
// SAFETY: world access promised by the caller, entity location and component_id required to be valid
10781104
get_component_and_ticks(world, component_id, info.storage_type(), entity, location).map(
10791105
|(value, ticks)| MutUntyped {
10801106
value: value.assert_unique(),
1081-
ticks: Ticks::from_tick_cells(ticks, world.last_change_tick(), change_tick),
1107+
ticks: Ticks::from_tick_cells(
1108+
ticks,
1109+
world.last_change_tick(),
1110+
world.read_change_tick(),
1111+
),
10821112
},
10831113
)
10841114
}

0 commit comments

Comments
 (0)