-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Add Disabled marker #12928
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
Add Disabled marker #12928
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,6 +21,12 @@ pub use par_iter::*; | |||||
| pub use state::*; | ||||||
| pub use world_query::*; | ||||||
|
|
||||||
| use crate as bevy_ecs; | ||||||
|
|
||||||
| /// A marker component that excludes an entity from queries that don't specifically request them. | ||||||
|
||||||
| /// A marker component that excludes an entity from queries that don't specifically request them. | |
| /// A special marker component that excludes an entity from queries that don't specifically request them. |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type needs to be Reflect, Clone and Copy, and the type should be registered in bevy_core. This is needed for various serialization use cases, namely networking and save games.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The component should probably also use sparse storage to avoid table moves.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. It would slow down the iteration in turn though. I think we stick to the simplest design for now until we can benchmark it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't slow down iteration unless you are accessing the component. Since it's a ZST that will likely be never.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh actually you're correct since most queries now need to filter on this, disregard.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,7 @@ use crate::{ | |
| change_detection::MutUntyped, | ||
| component::{Component, ComponentId, ComponentTicks, Components, StorageType}, | ||
| entity::{Entities, Entity, EntityLocation}, | ||
| query::{Access, DebugCheckedUnwrap}, | ||
| query::{Access, DebugCheckedUnwrap, Disabled}, | ||
| removal_detection::RemovedComponentEvents, | ||
| storage::Storages, | ||
| world::{Mut, World}, | ||
|
|
@@ -1136,6 +1136,8 @@ impl<'w> EntityWorldMut<'w> { | |
| /// | ||
| /// See [`EntityCommands::retain`](crate::system::EntityCommands::retain) for more details. | ||
| pub fn retain<T: Bundle>(&mut self) -> &mut Self { | ||
| let disabled_id = self.world.init_component::<Disabled>(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This behavior needs to be documented. It's a nice bit of design though! |
||
|
|
||
| let archetypes = &mut self.world.archetypes; | ||
| let storages = &mut self.world.storages; | ||
| let components = &mut self.world.components; | ||
|
|
@@ -1148,7 +1150,7 @@ impl<'w> EntityWorldMut<'w> { | |
|
|
||
| let to_remove = &old_archetype | ||
| .components() | ||
| .filter(|c| !retained_bundle_info.components().contains(c)) | ||
| .filter(|c| !retained_bundle_info.components().contains(c) && *c != disabled_id) | ||
| .collect::<Vec<_>>(); | ||
| let remove_bundle = self.world.bundles.init_dynamic_info(components, to_remove); | ||
|
|
||
|
|
@@ -1269,6 +1271,16 @@ impl<'w> EntityWorldMut<'w> { | |
| self.entity | ||
| } | ||
|
|
||
| /// Enables the current entity, removing the [`Disabled`] marker. | ||
| pub fn enable(&mut self) { | ||
| self.remove::<Disabled>(); | ||
| } | ||
|
|
||
| /// Disables the current entity, adding the [`Disabled`] marker. | ||
| pub fn disable(&mut self) { | ||
| self.insert(Disabled); | ||
| } | ||
|
|
||
| /// Gets read-only access to the world that the current entity belongs to. | ||
| #[inline] | ||
| pub fn world(&self) -> &World { | ||
|
|
@@ -2583,6 +2595,33 @@ mod tests { | |
| assert_eq!(world.entity(ent).archetype().components().next(), None); | ||
| } | ||
|
|
||
| // Test that calling retain retains [`Disabled`]. | ||
| #[test] | ||
| fn retain_disabled() { | ||
| #[derive(Component)] | ||
| struct Marker<const N: usize>; | ||
|
|
||
| let mut world = World::new(); | ||
| let ent = world | ||
| .spawn((Marker::<1>, Marker::<2>, Marker::<3>, Disabled)) | ||
| .id(); | ||
|
|
||
| let disabled_id = world.init_component::<Disabled>(); | ||
| world.entity_mut(ent).retain::<Marker<1>>(); | ||
| assert!(world | ||
| .entity(ent) | ||
| .archetype() | ||
| .components() | ||
| .any(|c| c == disabled_id)); | ||
|
|
||
| world.entity_mut(ent).retain::<()>(); | ||
| assert!(world | ||
| .entity(ent) | ||
| .archetype() | ||
| .components() | ||
| .any(|c| c == disabled_id)) | ||
| } | ||
|
|
||
| // Test removing some components with `retain`, including components not on the entity. | ||
| #[test] | ||
| fn retain_some_components() { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.