diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs index b865844731b66..1b3a2eaf0726b 100644 --- a/crates/bevy_ecs/src/reflect.rs +++ b/crates/bevy_ecs/src/reflect.rs @@ -5,7 +5,10 @@ use crate::{ component::Component, entity::{Entity, EntityMap, MapEntities, MapEntitiesError}, system::Resource, - world::{unsafe_world_cell::UnsafeWorldCell, FromWorld, World}, + world::{ + unsafe_world_cell::{UnsafeWorldCell, UnsafeWorldCellEntityRef}, + EntityMut, EntityRef, FromWorld, World, + }, }; use bevy_reflect::{ impl_from_reflect_value, impl_reflect_value, FromType, Reflect, ReflectDeserialize, @@ -42,20 +45,25 @@ pub struct ReflectComponent(ReflectComponentFns); #[derive(Clone)] pub struct ReflectComponentFns { /// Function pointer implementing [`ReflectComponent::insert()`]. - pub insert: fn(&mut World, Entity, &dyn Reflect), + pub insert: fn(&mut EntityMut, &dyn Reflect), /// Function pointer implementing [`ReflectComponent::apply()`]. - pub apply: fn(&mut World, Entity, &dyn Reflect), + pub apply: fn(&mut EntityMut, &dyn Reflect), /// Function pointer implementing [`ReflectComponent::apply_or_insert()`]. - pub apply_or_insert: fn(&mut World, Entity, &dyn Reflect), + pub apply_or_insert: fn(&mut EntityMut, &dyn Reflect), /// Function pointer implementing [`ReflectComponent::remove()`]. - pub remove: fn(&mut World, Entity), + pub remove: fn(&mut EntityMut), + /// Function pointer implementing [`ReflectComponent::contains()`]. + pub contains: fn(EntityRef) -> bool, /// Function pointer implementing [`ReflectComponent::reflect()`]. - pub reflect: fn(&World, Entity) -> Option<&dyn Reflect>, + pub reflect: fn(EntityRef) -> Option<&dyn Reflect>, /// Function pointer implementing [`ReflectComponent::reflect_mut()`]. + pub reflect_mut: for<'a> fn(&'a mut EntityMut<'_>) -> Option>, + /// Function pointer implementing [`ReflectComponent::reflect_unchecked_mut()`]. /// /// # Safety - /// The function may only be called with an [`UnsafeWorldCell`] that can be used to mutably access the relevant component on the given entity. - pub reflect_mut: unsafe fn(UnsafeWorldCell<'_>, Entity) -> Option>, + /// The function may only be called with an [`UnsafeWorldCellEntityRef`] that can be used to mutably access the relevant component on the given entity. + pub reflect_unchecked_mut: + unsafe fn(UnsafeWorldCellEntityRef<'_>) -> Option>, /// Function pointer implementing [`ReflectComponent::copy()`]. pub copy: fn(&World, &mut World, Entity, Entity), } @@ -73,68 +81,59 @@ impl ReflectComponentFns { impl ReflectComponent { /// Insert a reflected [`Component`] into the entity like [`insert()`](crate::world::EntityMut::insert). - /// - /// # Panics - /// - /// Panics if there is no such entity. - pub fn insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { - (self.0.insert)(world, entity, component); + pub fn insert(&self, entity: &mut EntityMut, component: &dyn Reflect) { + (self.0.insert)(entity, component); } /// Uses reflection to set the value of this [`Component`] type in the entity to the given value. /// /// # Panics /// - /// Panics if there is no [`Component`] of the given type or the `entity` does not exist. - pub fn apply(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { - (self.0.apply)(world, entity, component); + /// Panics if there is no [`Component`] of the given type. + pub fn apply(&self, entity: &mut EntityMut, component: &dyn Reflect) { + (self.0.apply)(entity, 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. - /// - /// # Panics - /// - /// Panics if the `entity` does not exist. - pub fn apply_or_insert(&self, world: &mut World, entity: Entity, component: &dyn Reflect) { - (self.0.apply_or_insert)(world, entity, component); + pub fn apply_or_insert(&self, entity: &mut EntityMut, component: &dyn Reflect) { + (self.0.apply_or_insert)(entity, component); } /// Removes this [`Component`] type from the entity. Does nothing if it doesn't exist. /// /// # Panics /// - /// Panics if there is no [`Component`] of the given type or the `entity` does not exist. - pub fn remove(&self, world: &mut World, entity: Entity) { - (self.0.remove)(world, entity); + /// Panics if there is no [`Component`] of the given type. + pub fn remove(&self, entity: &mut EntityMut) { + (self.0.remove)(entity); + } + + /// Returns whether entity contains this [`Component`] + pub fn contains(&self, entity: EntityRef) -> bool { + (self.0.contains)(entity) } /// Gets the value of this [`Component`] type from the entity as a reflected reference. - pub fn reflect<'a>(&self, world: &'a World, entity: Entity) -> Option<&'a dyn Reflect> { - (self.0.reflect)(world, entity) + pub fn reflect<'a>(&self, entity: EntityRef<'a>) -> Option<&'a dyn Reflect> { + (self.0.reflect)(entity) } /// Gets the value of this [`Component`] type from the entity as a mutable reflected reference. - pub fn reflect_mut<'a>( - &self, - world: &'a mut World, - entity: Entity, - ) -> Option> { - // SAFETY: unique world access - unsafe { (self.0.reflect_mut)(world.as_unsafe_world_cell(), entity) } + pub fn reflect_mut<'a>(&self, entity: &'a mut EntityMut<'_>) -> Option> { + (self.0.reflect_mut)(entity) } /// # Safety /// This method does not prevent you from having two mutable pointers to the same data, /// violating Rust's aliasing rules. To avoid this: - /// * Only call this method with a [`UnsafeWorldCell`] that may be used to mutably access the component on the entity `entity` + /// * Only call this method with a [`UnsafeWorldCellEntityRef`] that may be used to mutably access the component on the entity `entity` /// * Don't call this method more than once in the same scope for a given [`Component`]. pub unsafe fn reflect_unchecked_mut<'a>( &self, - world: UnsafeWorldCell<'a>, - entity: Entity, + entity: UnsafeWorldCellEntityRef<'a>, ) -> Option> { // SAFETY: safety requirements deferred to caller - (self.0.reflect_mut)(world, entity) + (self.0.reflect_unchecked_mut)(entity) } /// 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 { impl FromType for ReflectComponent { fn from_type() -> Self { ReflectComponent(ReflectComponentFns { - insert: |world, entity, reflected_component| { - let mut component = C::from_world(world); + insert: |entity, reflected_component| { + let mut component = entity.world_scope(|world| C::from_world(world)); component.apply(reflected_component); - world.entity_mut(entity).insert(component); + entity.insert(component); }, - apply: |world, entity, reflected_component| { - let mut component = world.get_mut::(entity).unwrap(); + apply: |entity, reflected_component| { + let mut component = entity.get_mut::().unwrap(); component.apply(reflected_component); }, - apply_or_insert: |world, entity, reflected_component| { - if let Some(mut component) = world.get_mut::(entity) { + apply_or_insert: |entity, reflected_component| { + if let Some(mut component) = entity.get_mut::() { component.apply(reflected_component); } else { - let mut component = C::from_world(world); + let mut component = entity.world_scope(|world| C::from_world(world)); component.apply(reflected_component); - world.entity_mut(entity).insert(component); + entity.insert(component); } }, - remove: |world, entity| { - world.entity_mut(entity).remove::(); + remove: |entity| { + entity.remove::(); }, + contains: |entity| entity.contains::(), copy: |source_world, destination_world, source_entity, destination_entity| { let source_component = source_world.get::(source_entity).unwrap(); let mut destination_component = C::from_world(destination_world); @@ -205,18 +205,18 @@ impl FromType for ReflectComponent { .entity_mut(destination_entity) .insert(destination_component); }, - reflect: |world, entity| { - world - .get_entity(entity)? - .get::() - .map(|c| c as &dyn Reflect) + reflect: |entity| entity.get::().map(|c| c as &dyn Reflect), + reflect_mut: |entity| { + entity.get_mut::().map(|c| Mut { + value: c.value as &mut dyn Reflect, + ticks: c.ticks, + }) }, - reflect_mut: |world, entity| { - // SAFETY: reflect_mut is an unsafe function pointer used by - // 1. `reflect_unchecked_mut` which must be called with an UnsafeWorldCell with access to the the component `C` on the `entity`, and - // 2. `reflect_mut`, which has mutable world access + reflect_unchecked_mut: |entity| { + // SAFETY: reflect_unchecked_mut is an unsafe function pointer used by + // `reflect_unchecked_mut` which must be called with an UnsafeWorldCellEntityRef with access to the the component `C` on the `entity` unsafe { - world.get_entity(entity)?.get_mut::().map(|c| Mut { + entity.get_mut::().map(|c| Mut { value: c.value as &mut dyn Reflect, ticks: c.ticks, }) diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index c0eb067b2ca8b..cb5bd1a387fce 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -71,6 +71,7 @@ impl DynamicScene { let entity = *entity_map .entry(bevy_ecs::entity::Entity::from_raw(scene_entity.entity)) .or_insert_with(|| world.spawn_empty().id()); + let entity_mut = &mut world.entity_mut(entity); // Apply/ add each component to the given entity. for component in &scene_entity.components { @@ -89,7 +90,7 @@ impl DynamicScene { // If the entity already has the given component attached, // just apply the (possibly) new value, otherwise add the // component to the entity. - reflect_component.apply_or_insert(world, entity, &**component); + reflect_component.apply_or_insert(entity_mut, &**component); } } diff --git a/crates/bevy_scene/src/dynamic_scene_builder.rs b/crates/bevy_scene/src/dynamic_scene_builder.rs index 98bf10e27f5b8..1187f087b6809 100644 --- a/crates/bevy_scene/src/dynamic_scene_builder.rs +++ b/crates/bevy_scene/src/dynamic_scene_builder.rs @@ -124,19 +124,18 @@ impl<'w> DynamicSceneBuilder<'w> { components: Vec::new(), }; - for component_id in self.original_world.entity(entity).archetype().components() { + let entity = self.original_world.entity(entity); + for component_id in entity.archetype().components() { let reflect_component = self .original_world .components() .get_info(component_id) .and_then(|info| type_registry.get(info.type_id().unwrap())) - .and_then(|registration| registration.data::()); + .and_then(|registration| registration.data::()) + .and_then(|reflect_component| reflect_component.reflect(entity)); if let Some(reflect_component) = reflect_component { - if let Some(component) = reflect_component.reflect(self.original_world, entity) - { - entry.components.push(component.clone_value()); - } + entry.components.push(reflect_component.clone_value()); } } self.extracted_scene.insert(index, entry);