diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 7750f972592c2..2d185853236d9 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -177,9 +177,10 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream { #[inline] fn get_components( self, - func: &mut impl FnMut(#ecs_path::component::StorageType, #ecs_path::ptr::OwningPtr<'_>) + insert_mode: #ecs_path::bundle::InsertMode, + func: &mut impl FnMut(#ecs_path::component::StorageType, #ecs_path::bundle::InsertMode, #ecs_path::ptr::OwningPtr<'_>) ) { - #(<#active_field_types as #ecs_path::bundle::DynamicBundle>::get_components(self.#active_field_tokens, &mut *func);)* + #(<#active_field_types as #ecs_path::bundle::DynamicBundle>::get_components(self.#active_field_tokens, insert_mode, &mut *func);)* } } }; diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 8efdc60ad9345..6c12deaaf02a9 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -255,7 +255,11 @@ pub trait DynamicBundle { /// Calls `func` on each value, in the order of this bundle's [`Component`]s. This passes /// ownership of the component values to `func`. #[doc(hidden)] - fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect; + fn get_components( + self, + insert_mode: InsertMode, + func: &mut impl FnMut(StorageType, InsertMode, OwningPtr<'_>), + ) -> Self::Effect; } /// An operation on an [`Entity`] that occurs _after_ inserting the [`Bundle`] that defined this bundle effect. @@ -316,8 +320,12 @@ unsafe impl BundleFromComponents for C { impl DynamicBundle for C { type Effect = (); #[inline] - fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect { - OwningPtr::make(self, |ptr| func(C::STORAGE_TYPE, ptr)); + fn get_components( + self, + insert_mode: InsertMode, + func: &mut impl FnMut(StorageType, InsertMode, OwningPtr<'_>), + ) -> Self::Effect { + OwningPtr::make(self, |ptr| func(C::STORAGE_TYPE, insert_mode, ptr)); } } @@ -408,14 +416,14 @@ macro_rules! tuple_impl { reason = "Zero-length tuples will generate a function body equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case." )] #[inline(always)] - fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) -> Self::Effect { + fn get_components(self, insert_mode: InsertMode, func: &mut impl FnMut(StorageType, InsertMode, OwningPtr<'_>)) -> Self::Effect { #[allow( non_snake_case, reason = "The names of these variables are provided by the caller, not by us." )] let ($(mut $name,)*) = self; ($( - $name.get_components(&mut *func), + $name.get_components(insert_mode, &mut *func), )*) } } @@ -498,6 +506,66 @@ pub enum InsertMode { Keep, } +pub struct ReplaceIfCollides(pub B); +// SAFETY: This internally relies on the wrapped Bundle implementation, which is sound. +unsafe impl Bundle for ReplaceIfCollides { + fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId)) { + B::component_ids(components, ids); + } + + fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option)) { + B::get_component_ids(components, ids); + } + + fn register_required_components( + components: &mut ComponentsRegistrator, + required_components: &mut RequiredComponents, + ) { + B::register_required_components(components, required_components); + } +} +impl DynamicBundle for ReplaceIfCollides { + type Effect = (); + + fn get_components( + self, + _insert_mode: InsertMode, + func: &mut impl FnMut(StorageType, InsertMode, OwningPtr<'_>), + ) { + self.0.get_components(InsertMode::Replace, func); + } +} + +pub struct IgnoreIfCollides(pub B); +// SAFETY: This internally relies on the wrapped Bundle implementation, which is sound. +unsafe impl Bundle for IgnoreIfCollides { + fn component_ids(components: &mut ComponentsRegistrator, ids: &mut impl FnMut(ComponentId)) { + B::component_ids(components, ids); + } + + fn get_component_ids(components: &Components, ids: &mut impl FnMut(Option)) { + B::get_component_ids(components, ids); + } + + fn register_required_components( + components: &mut ComponentsRegistrator, + required_components: &mut RequiredComponents, + ) { + B::register_required_components(components, required_components); + } +} +impl DynamicBundle for IgnoreIfCollides { + type Effect = (); + + fn get_components( + self, + _insert_mode: InsertMode, + func: &mut impl FnMut(StorageType, InsertMode, OwningPtr<'_>), + ) { + self.0.get_components(InsertMode::Keep, func); + } +} + /// Stores metadata associated with a specific type of [`Bundle`] for a given [`World`]. /// /// [`World`]: crate::world::World @@ -673,55 +741,57 @@ impl BundleInfo { table_row: TableRow, change_tick: Tick, bundle: T, - insert_mode: InsertMode, caller: MaybeLocation, ) -> T::Effect { // NOTE: get_components calls this closure on each component in "bundle order". // bundle_info.component_ids are also in "bundle order" let mut bundle_component = 0; - let after_effect = bundle.get_components(&mut |storage_type, component_ptr| { - let component_id = *self.component_ids.get_unchecked(bundle_component); - // SAFETY: bundle_component is a valid index for this bundle - let status = unsafe { bundle_component_status.get_status(bundle_component) }; - match storage_type { - StorageType::Table => { - let column = + let after_effect = bundle.get_components( + InsertMode::Replace, + &mut |storage_type, insert_mode, component_ptr| { + let component_id = *self.component_ids.get_unchecked(bundle_component); + // SAFETY: bundle_component is a valid index for this bundle + let status = unsafe { bundle_component_status.get_status(bundle_component) }; + match storage_type { + StorageType::Table => { + let column = // SAFETY: If component_id is in self.component_ids, BundleInfo::new ensures that // the target table contains the component. unsafe { table.get_column_mut(component_id).debug_checked_unwrap() }; - match (status, insert_mode) { - (ComponentStatus::Added, _) => { - column.initialize(table_row, component_ptr, change_tick, caller); - } - (ComponentStatus::Existing, InsertMode::Replace) => { - column.replace(table_row, component_ptr, change_tick, caller); - } - (ComponentStatus::Existing, InsertMode::Keep) => { - if let Some(drop_fn) = table.get_drop_for(component_id) { - drop_fn(component_ptr); + match (status, insert_mode) { + (ComponentStatus::Added, _) => { + column.initialize(table_row, component_ptr, change_tick, caller); + } + (ComponentStatus::Existing, InsertMode::Replace) => { + column.replace(table_row, component_ptr, change_tick, caller); + } + (ComponentStatus::Existing, InsertMode::Keep) => { + if let Some(drop_fn) = table.get_drop_for(component_id) { + drop_fn(component_ptr); + } } } } - } - StorageType::SparseSet => { - let sparse_set = + StorageType::SparseSet => { + let sparse_set = // SAFETY: If component_id is in self.component_ids, BundleInfo::new ensures that // a sparse set exists for the component. unsafe { sparse_sets.get_mut(component_id).debug_checked_unwrap() }; - match (status, insert_mode) { - (ComponentStatus::Added, _) | (_, InsertMode::Replace) => { - sparse_set.insert(entity, component_ptr, change_tick, caller); - } - (ComponentStatus::Existing, InsertMode::Keep) => { - if let Some(drop_fn) = sparse_set.get_drop() { - drop_fn(component_ptr); + match (status, insert_mode) { + (ComponentStatus::Added, _) | (_, InsertMode::Replace) => { + sparse_set.insert(entity, component_ptr, change_tick, caller); + } + (ComponentStatus::Existing, InsertMode::Keep) => { + if let Some(drop_fn) = sparse_set.get_drop() { + drop_fn(component_ptr); + } } } } } - } - bundle_component += 1; - }); + bundle_component += 1; + }, + ); for required_component in required_components { required_component.initialize( @@ -1173,7 +1243,6 @@ impl<'w> BundleInserter<'w> { entity: Entity, location: EntityLocation, bundle: T, - insert_mode: InsertMode, caller: MaybeLocation, relationship_hook_mode: RelationshipHookMode, ) -> (EntityLocation, T::Effect) { @@ -1187,23 +1256,22 @@ impl<'w> BundleInserter<'w> { // SAFETY: Mutable references do not alias and will be dropped after this block let mut deferred_world = self.world.into_deferred(); - if insert_mode == InsertMode::Replace { - if archetype.has_replace_observer() { - deferred_world.trigger_observers( - REPLACE, - Some(entity), - archetype_after_insert.iter_existing(), - caller, - ); - } - deferred_world.trigger_on_replace( - archetype, - entity, + // TEMP: not sure what to do with this + if archetype.has_replace_observer() { + deferred_world.trigger_observers( + REPLACE, + Some(entity), archetype_after_insert.iter_existing(), caller, - relationship_hook_mode, ); } + deferred_world.trigger_on_replace( + archetype, + entity, + archetype_after_insert.iter_existing(), + caller, + relationship_hook_mode, + ); } let table = self.table.as_mut(); @@ -1229,7 +1297,6 @@ impl<'w> BundleInserter<'w> { location.table_row, self.change_tick, bundle, - insert_mode, caller, ); @@ -1270,7 +1337,6 @@ impl<'w> BundleInserter<'w> { result.table_row, self.change_tick, bundle, - insert_mode, caller, ); @@ -1352,7 +1418,6 @@ impl<'w> BundleInserter<'w> { move_result.new_row, self.change_tick, bundle, - insert_mode, caller, ); @@ -1381,44 +1446,22 @@ impl<'w> BundleInserter<'w> { caller, ); } - match insert_mode { - InsertMode::Replace => { - // Insert triggers for both new and existing components if we're replacing them. - deferred_world.trigger_on_insert( - new_archetype, - entity, - archetype_after_insert.iter_inserted(), - caller, - relationship_hook_mode, - ); - if new_archetype.has_insert_observer() { - deferred_world.trigger_observers( - INSERT, - Some(entity), - archetype_after_insert.iter_inserted(), - caller, - ); - } - } - InsertMode::Keep => { - // Insert triggers only for new components if we're not replacing them (since - // nothing is actually inserted). - deferred_world.trigger_on_insert( - new_archetype, - entity, - archetype_after_insert.iter_added(), - caller, - relationship_hook_mode, - ); - if new_archetype.has_insert_observer() { - deferred_world.trigger_observers( - INSERT, - Some(entity), - archetype_after_insert.iter_added(), - caller, - ); - } - } + // TEMP: not sure what to do with this + // Insert triggers for both new and existing components if we're replacing them. + deferred_world.trigger_on_insert( + new_archetype, + entity, + archetype_after_insert.iter_inserted(), + caller, + relationship_hook_mode, + ); + if new_archetype.has_insert_observer() { + deferred_world.trigger_observers( + INSERT, + Some(entity), + archetype_after_insert.iter_inserted(), + caller, + ); } } @@ -1809,7 +1852,6 @@ impl<'w> BundleSpawner<'w> { table_row, self.change_tick, bundle, - InsertMode::Replace, caller, ); entities.set(entity.index(), Some(location)); diff --git a/crates/bevy_ecs/src/spawn.rs b/crates/bevy_ecs/src/spawn.rs index d5014f22409fd..66667886f6dd4 100644 --- a/crates/bevy_ecs/src/spawn.rs +++ b/crates/bevy_ecs/src/spawn.rs @@ -215,10 +215,15 @@ impl> DynamicBundle for SpawnRelatedBundle< fn get_components( self, - func: &mut impl FnMut(crate::component::StorageType, bevy_ptr::OwningPtr<'_>), + insert_mode: crate::bundle::InsertMode, + func: &mut impl FnMut( + crate::component::StorageType, + crate::bundle::InsertMode, + bevy_ptr::OwningPtr<'_>, + ), ) -> Self::Effect { ::with_capacity(self.list.size_hint()) - .get_components(func); + .get_components(insert_mode, func); self } } @@ -244,9 +249,15 @@ impl DynamicBundle for SpawnOneRelated { fn get_components( self, - func: &mut impl FnMut(crate::component::StorageType, bevy_ptr::OwningPtr<'_>), + insert_mode: crate::bundle::InsertMode, + func: &mut impl FnMut( + crate::component::StorageType, + crate::bundle::InsertMode, + bevy_ptr::OwningPtr<'_>, + ), ) -> Self::Effect { - ::with_capacity(1).get_components(func); + ::with_capacity(1) + .get_components(insert_mode, func); self } } diff --git a/crates/bevy_ecs/src/system/commands/command.rs b/crates/bevy_ecs/src/system/commands/command.rs index f3fc677e471b1..fbce93d56e2a5 100644 --- a/crates/bevy_ecs/src/system/commands/command.rs +++ b/crates/bevy_ecs/src/system/commands/command.rs @@ -5,7 +5,7 @@ //! [`Commands`](crate::system::Commands). use crate::{ - bundle::{Bundle, InsertMode, NoBundleEffect}, + bundle::{Bundle, NoBundleEffect}, change_detection::MaybeLocation, entity::Entity, error::Result, @@ -85,14 +85,14 @@ where /// /// This is more efficient than inserting the bundles individually. #[track_caller] -pub fn insert_batch(batch: I, insert_mode: InsertMode) -> impl Command +pub fn insert_batch(batch: I) -> impl Command where I: IntoIterator + Send + Sync + 'static, B: Bundle, { let caller = MaybeLocation::caller(); move |world: &mut World| -> Result { - world.try_insert_batch_with_caller(batch, insert_mode, caller)?; + world.try_insert_batch_with_caller(batch, caller)?; Ok(()) } } diff --git a/crates/bevy_ecs/src/system/commands/entity_command.rs b/crates/bevy_ecs/src/system/commands/entity_command.rs index 87bd2d858b27c..b56d8bef2b0f3 100644 --- a/crates/bevy_ecs/src/system/commands/entity_command.rs +++ b/crates/bevy_ecs/src/system/commands/entity_command.rs @@ -8,7 +8,7 @@ use alloc::vec::Vec; use log::info; use crate::{ - bundle::{Bundle, InsertMode}, + bundle::{Bundle, IgnoreIfCollides}, change_detection::MaybeLocation, component::{Component, ComponentId, ComponentInfo}, entity::{Entity, EntityClonerBuilder}, @@ -105,10 +105,10 @@ where /// An [`EntityCommand`] that adds the components in a [`Bundle`] to an entity. #[track_caller] -pub fn insert(bundle: impl Bundle, mode: InsertMode) -> impl EntityCommand { +pub fn insert(bundle: impl Bundle) -> impl EntityCommand { let caller = MaybeLocation::caller(); move |mut entity: EntityWorldMut| { - entity.insert_with_caller(bundle, mode, caller, RelationshipHookMode::Run); + entity.insert_with_caller(bundle, caller, RelationshipHookMode::Run); } } @@ -122,7 +122,6 @@ pub fn insert(bundle: impl Bundle, mode: InsertMode) -> impl EntityCommand { pub unsafe fn insert_by_id( component_id: ComponentId, value: T, - mode: InsertMode, ) -> impl EntityCommand { let caller = MaybeLocation::caller(); move |mut entity: EntityWorldMut| { @@ -130,13 +129,7 @@ pub unsafe fn insert_by_id( // - `component_id` safety is ensured by the caller // - `ptr` is valid within the `make` block OwningPtr::make(value, |ptr| unsafe { - entity.insert_by_id_with_caller( - component_id, - ptr, - mode, - caller, - RelationshipHookMode::Run, - ); + entity.insert_by_id_with_caller(component_id, ptr, caller, RelationshipHookMode::Run); }); } } @@ -144,11 +137,15 @@ pub unsafe fn insert_by_id( /// An [`EntityCommand`] that adds a component to an entity using /// the component's [`FromWorld`] implementation. #[track_caller] -pub fn insert_from_world(mode: InsertMode) -> impl EntityCommand { +pub fn insert_from_world(ignore_if_collides: bool) -> impl EntityCommand { let caller = MaybeLocation::caller(); move |mut entity: EntityWorldMut| { let value = entity.world_scope(|world| T::from_world(world)); - entity.insert_with_caller(value, mode, caller, RelationshipHookMode::Run); + if ignore_if_collides { + entity.insert_with_caller(IgnoreIfCollides(value), caller, RelationshipHookMode::Run); + } else { + entity.insert_with_caller(value, caller, RelationshipHookMode::Run); + } } } diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 84f9784228ff4..272efe3ee424a 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -15,7 +15,7 @@ use core::marker::PhantomData; use crate::{ self as bevy_ecs, - bundle::{Bundle, InsertMode, NoBundleEffect}, + bundle::{Bundle, IgnoreIfCollides, NoBundleEffect}, change_detection::{MaybeLocation, Mut}, component::{Component, ComponentId, Mutable}, entity::{Entities, Entity, EntityClonerBuilder, EntityDoesNotExistError}, @@ -398,7 +398,6 @@ impl<'w, 's> Commands<'w, 's> { entity.insert_with_caller( bundle, - InsertMode::Replace, caller, crate::relationship::RelationshipHookMode::Run, ); @@ -683,7 +682,7 @@ impl<'w, 's> Commands<'w, 's> { I: IntoIterator + Send + Sync + 'static, B: Bundle, { - self.queue(command::insert_batch(batch, InsertMode::Replace)); + self.queue(command::insert_batch(batch)); } /// Adds a series of [`Bundles`](Bundle) to each [`Entity`] they are paired with, @@ -712,9 +711,12 @@ impl<'w, 's> Commands<'w, 's> { pub fn insert_batch_if_new(&mut self, batch: I) where I: IntoIterator + Send + Sync + 'static, + I::IntoIter: Send + Sync + 'static, B: Bundle, { - self.queue(command::insert_batch(batch, InsertMode::Keep)); + self.queue(command::insert_batch( + batch.into_iter().map(|(e, b)| (e, IgnoreIfCollides(b))), + )); } /// Adds a series of [`Bundles`](Bundle) to each [`Entity`] they are paired with, @@ -744,7 +746,7 @@ impl<'w, 's> Commands<'w, 's> { I: IntoIterator + Send + Sync + 'static, B: Bundle, { - self.queue(command::insert_batch(batch, InsertMode::Replace).handle_error_with(warn)); + self.queue(command::insert_batch(batch).handle_error_with(warn)); } /// Adds a series of [`Bundles`](Bundle) to each [`Entity`] they are paired with, @@ -773,9 +775,13 @@ impl<'w, 's> Commands<'w, 's> { pub fn try_insert_batch_if_new(&mut self, batch: I) where I: IntoIterator + Send + Sync + 'static, + I::IntoIter: Send + Sync + 'static, B: Bundle, { - self.queue(command::insert_batch(batch, InsertMode::Keep).handle_error_with(warn)); + self.queue( + command::insert_batch(batch.into_iter().map(|(e, b)| (e, IgnoreIfCollides(b)))) + .handle_error_with(warn), + ); } /// Inserts a [`Resource`] into the [`World`] with an inferred value. @@ -1353,7 +1359,7 @@ impl<'a> EntityCommands<'a> { /// ``` #[track_caller] pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self { - self.queue(entity_command::insert(bundle, InsertMode::Replace)) + self.queue(entity_command::insert(bundle)) } /// Adds a [`Bundle`] of components to the entity if the predicate returns true. @@ -1401,7 +1407,7 @@ impl<'a> EntityCommands<'a> { /// as well as initialize it with a default value. #[track_caller] pub fn insert_if_new(&mut self, bundle: impl Bundle) -> &mut Self { - self.queue(entity_command::insert(bundle, InsertMode::Keep)) + self.queue(entity_command::insert(IgnoreIfCollides(bundle))) } /// Adds a [`Bundle`] of components to the entity without overwriting if the @@ -1441,7 +1447,7 @@ impl<'a> EntityCommands<'a> { // SAFETY: // - `ComponentId` safety is ensured by the caller. // - `T` safety is ensured by the caller. - unsafe { entity_command::insert_by_id(component_id, value, InsertMode::Replace) }, + unsafe { entity_command::insert_by_id(component_id, value) }, ) } @@ -1470,7 +1476,7 @@ impl<'a> EntityCommands<'a> { // SAFETY: // - `ComponentId` safety is ensured by the caller. // - `T` safety is ensured by the caller. - unsafe { entity_command::insert_by_id(component_id, value, InsertMode::Replace) }, + unsafe { entity_command::insert_by_id(component_id, value) }, ignore, ) } @@ -1523,7 +1529,7 @@ impl<'a> EntityCommands<'a> { /// ``` #[track_caller] pub fn try_insert(&mut self, bundle: impl Bundle) -> &mut Self { - self.queue_handled(entity_command::insert(bundle, InsertMode::Replace), ignore) + self.queue_handled(entity_command::insert(bundle), ignore) } /// Adds a [`Bundle`] of components to the entity if the predicate returns true. @@ -1579,7 +1585,7 @@ impl<'a> EntityCommands<'a> { /// the resulting error will be ignored. #[track_caller] pub fn try_insert_if_new(&mut self, bundle: impl Bundle) -> &mut Self { - self.queue_handled(entity_command::insert(bundle, InsertMode::Keep), ignore) + self.queue_handled(entity_command::insert(IgnoreIfCollides(bundle)), ignore) } /// Removes a [`Bundle`] of components from the entity. @@ -2205,7 +2211,7 @@ impl<'a, T: Component> EntityEntryCommands<'a, T> { T: FromWorld, { self.entity_commands - .queue(entity_command::insert_from_world::(InsertMode::Keep)); + .queue(entity_command::insert_from_world::(true)); self } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index d29c3db4283ca..3604357f83a7b 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -2,7 +2,7 @@ use crate::{ archetype::Archetype, bundle::{ Bundle, BundleEffect, BundleFromComponents, BundleInserter, BundleRemover, DynamicBundle, - InsertMode, + IgnoreIfCollides, InsertMode, }, change_detection::{MaybeLocation, MutUntyped}, component::{ @@ -1782,12 +1782,7 @@ impl<'w> EntityWorldMut<'w> { /// If the entity has been despawned while this `EntityWorldMut` is still alive. #[track_caller] pub fn insert(&mut self, bundle: T) -> &mut Self { - self.insert_with_caller( - bundle, - InsertMode::Replace, - MaybeLocation::caller(), - RelationshipHookMode::Run, - ) + self.insert_with_caller(bundle, MaybeLocation::caller(), RelationshipHookMode::Run) } /// Adds a [`Bundle`] of components to the entity. @@ -1810,12 +1805,7 @@ impl<'w> EntityWorldMut<'w> { bundle: T, relationship_hook_mode: RelationshipHookMode, ) -> &mut Self { - self.insert_with_caller( - bundle, - InsertMode::Replace, - MaybeLocation::caller(), - relationship_hook_mode, - ) + self.insert_with_caller(bundle, MaybeLocation::caller(), relationship_hook_mode) } /// Adds a [`Bundle`] of components to the entity without overwriting. @@ -1829,8 +1819,7 @@ impl<'w> EntityWorldMut<'w> { #[track_caller] pub fn insert_if_new(&mut self, bundle: T) -> &mut Self { self.insert_with_caller( - bundle, - InsertMode::Keep, + IgnoreIfCollides(bundle), MaybeLocation::caller(), RelationshipHookMode::Run, ) @@ -1842,7 +1831,6 @@ impl<'w> EntityWorldMut<'w> { pub(crate) fn insert_with_caller( &mut self, bundle: T, - mode: InsertMode, caller: MaybeLocation, relationship_hook_mode: RelationshipHookMode, ) -> &mut Self { @@ -1856,7 +1844,6 @@ impl<'w> EntityWorldMut<'w> { self.entity, location, bundle, - mode, caller, relationship_hook_mode, ) @@ -1891,7 +1878,6 @@ impl<'w> EntityWorldMut<'w> { self.insert_by_id_with_caller( component_id, component, - InsertMode::Replace, MaybeLocation::caller(), RelationshipHookMode::Run, ) @@ -1906,7 +1892,6 @@ impl<'w> EntityWorldMut<'w> { &mut self, component_id: ComponentId, component: OwningPtr<'_>, - mode: InsertMode, caller: MaybeLocation, relationship_hook_insert_mode: RelationshipHookMode, ) -> &mut Self { @@ -1928,7 +1913,6 @@ impl<'w> EntityWorldMut<'w> { location, Some(component).into_iter(), Some(storage_type).iter().cloned(), - mode, caller, relationship_hook_insert_mode, )); @@ -1987,7 +1971,6 @@ impl<'w> EntityWorldMut<'w> { location, iter_components, (*storage_types).iter().cloned(), - InsertMode::Replace, MaybeLocation::caller(), relationship_hook_insert_mode, )); @@ -4361,7 +4344,6 @@ unsafe fn insert_dynamic_bundle< location: EntityLocation, components: I, storage_types: S, - mode: InsertMode, caller: MaybeLocation, relationship_hook_insert_mode: RelationshipHookMode, ) -> EntityLocation { @@ -4373,8 +4355,13 @@ unsafe fn insert_dynamic_bundle< for DynamicInsertBundle<'a, I> { type Effect = (); - fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>)) { - self.components.for_each(|(t, ptr)| func(t, ptr)); + fn get_components( + self, + insert_mode: InsertMode, + func: &mut impl FnMut(StorageType, InsertMode, OwningPtr<'_>), + ) { + self.components + .for_each(|(t, ptr)| func(t, insert_mode, ptr)); } } @@ -4389,7 +4376,6 @@ unsafe fn insert_dynamic_bundle< entity, location, bundle, - mode, caller, relationship_hook_insert_mode, ) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index fca9091dd5f96..fe5d2994905d5 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -13,16 +13,17 @@ pub mod unsafe_world_cell; #[cfg(feature = "bevy_reflect")] pub mod reflect; -pub use crate::{ - change_detection::{Mut, Ref, CHECK_TICK_THRESHOLD}, - world::command_queue::CommandQueue, -}; use crate::{ + bundle::IgnoreIfCollides, error::{DefaultErrorHandler, ErrorHandler}, event::BufferedEvent, lifecycle::{ComponentHooks, ADD, DESPAWN, INSERT, REMOVE, REPLACE}, prelude::{Add, Despawn, Insert, Remove, Replace}, }; +pub use crate::{ + change_detection::{Mut, Ref, CHECK_TICK_THRESHOLD}, + world::command_queue::CommandQueue, +}; pub use bevy_ecs_macros::FromWorld; use bevy_utils::prelude::DebugName; pub use deferred_world::DeferredWorld; @@ -39,8 +40,7 @@ pub use spawn_batch::*; use crate::{ archetype::{ArchetypeId, Archetypes}, bundle::{ - Bundle, BundleEffect, BundleInfo, BundleInserter, BundleSpawner, Bundles, InsertMode, - NoBundleEffect, + Bundle, BundleEffect, BundleInfo, BundleInserter, BundleSpawner, Bundles, NoBundleEffect, }, change_detection::{MaybeLocation, MutUntyped, TicksMut}, component::{ @@ -2236,7 +2236,7 @@ impl World { I::IntoIter: Iterator, B: Bundle, { - self.insert_batch_with_caller(batch, InsertMode::Replace, MaybeLocation::caller()); + self.insert_batch_with_caller(batch, MaybeLocation::caller()); } /// For a given batch of ([`Entity`], [`Bundle`]) pairs, @@ -2261,7 +2261,10 @@ impl World { I::IntoIter: Iterator, B: Bundle, { - self.insert_batch_with_caller(batch, InsertMode::Keep, MaybeLocation::caller()); + self.insert_batch_with_caller( + batch.into_iter().map(|(e, b)| (e, IgnoreIfCollides(b))), + MaybeLocation::caller(), + ); } /// Split into a new function so we can differentiate the calling location. @@ -2270,12 +2273,8 @@ impl World { /// - [`World::insert_batch`] /// - [`World::insert_batch_if_new`] #[inline] - pub(crate) fn insert_batch_with_caller( - &mut self, - batch: I, - insert_mode: InsertMode, - caller: MaybeLocation, - ) where + pub(crate) fn insert_batch_with_caller(&mut self, batch: I, caller: MaybeLocation) + where I: IntoIterator, I::IntoIter: Iterator, B: Bundle, @@ -2316,7 +2315,6 @@ impl World { first_entity, first_location, first_bundle, - insert_mode, caller, RelationshipHookMode::Run, ) @@ -2344,7 +2342,6 @@ impl World { entity, location, bundle, - insert_mode, caller, RelationshipHookMode::Run, ) @@ -2379,7 +2376,7 @@ impl World { I::IntoIter: Iterator, B: Bundle, { - self.try_insert_batch_with_caller(batch, InsertMode::Replace, MaybeLocation::caller()) + self.try_insert_batch_with_caller(batch, MaybeLocation::caller()) } /// For a given batch of ([`Entity`], [`Bundle`]) pairs, /// adds the `Bundle` of components to each `Entity` without overwriting. @@ -2401,7 +2398,10 @@ impl World { I::IntoIter: Iterator, B: Bundle, { - self.try_insert_batch_with_caller(batch, InsertMode::Keep, MaybeLocation::caller()) + self.try_insert_batch_with_caller( + batch.into_iter().map(|(e, b)| (e, IgnoreIfCollides(b))), + MaybeLocation::caller(), + ) } /// Split into a new function so we can differentiate the calling location. @@ -2417,7 +2417,6 @@ impl World { pub(crate) fn try_insert_batch_with_caller( &mut self, batch: I, - insert_mode: InsertMode, caller: MaybeLocation, ) -> Result<(), TryInsertBatchError> where @@ -2466,7 +2465,6 @@ impl World { first_entity, first_location, first_bundle, - insert_mode, caller, RelationshipHookMode::Run, ) @@ -2503,7 +2501,6 @@ impl World { entity, location, bundle, - insert_mode, caller, RelationshipHookMode::Run, )