Path: blob/main/crates/bevy_ecs/src/world/entity_access/entry.rs
7224 views
use crate::{1component::{Component, Mutable},2world::{EntityWorldMut, Mut},3};45use core::marker::PhantomData;67/// A view into a single entity and component in a world, which may either be vacant or occupied.8///9/// This `enum` can only be constructed from the [`entry`] method on [`EntityWorldMut`].10///11/// [`entry`]: EntityWorldMut::entry12pub enum ComponentEntry<'w, 'a, T: Component> {13/// An occupied entry.14Occupied(OccupiedComponentEntry<'w, 'a, T>),15/// A vacant entry.16Vacant(VacantComponentEntry<'w, 'a, T>),17}1819impl<'w, 'a, T: Component<Mutability = Mutable>> ComponentEntry<'w, 'a, T> {20/// Provides in-place mutable access to an occupied entry.21///22/// # Examples23///24/// ```25/// # use bevy_ecs::prelude::*;26/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]27/// struct Comp(u32);28///29/// # let mut world = World::new();30/// let mut entity = world.spawn(Comp(0));31///32/// entity.entry::<Comp>().and_modify(|mut c| c.0 += 1);33/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 1);34/// ```35#[inline]36pub fn and_modify<F: FnOnce(Mut<'_, T>)>(self, f: F) -> Self {37match self {38ComponentEntry::Occupied(mut entry) => {39f(entry.get_mut());40ComponentEntry::Occupied(entry)41}42ComponentEntry::Vacant(entry) => ComponentEntry::Vacant(entry),43}44}45}4647impl<'w, 'a, T: Component> ComponentEntry<'w, 'a, T> {48/// Replaces the component of the entry, and returns an [`OccupiedComponentEntry`].49///50/// # Examples51///52/// ```53/// # use bevy_ecs::prelude::*;54/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]55/// struct Comp(u32);56///57/// # let mut world = World::new();58/// let mut entity = world.spawn_empty();59///60/// let entry = entity.entry().insert_entry(Comp(4));61/// assert_eq!(entry.get(), &Comp(4));62///63/// let entry = entity.entry().insert_entry(Comp(2));64/// assert_eq!(entry.get(), &Comp(2));65/// ```66#[inline]67pub fn insert_entry(self, component: T) -> OccupiedComponentEntry<'w, 'a, T> {68match self {69ComponentEntry::Occupied(mut entry) => {70entry.insert(component);71entry72}73ComponentEntry::Vacant(entry) => entry.insert(component),74}75}7677/// Ensures the entry has this component by inserting the given default if empty, and78/// returns a mutable reference to this component in the entry.79///80/// # Examples81///82/// ```83/// # use bevy_ecs::prelude::*;84/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]85/// struct Comp(u32);86///87/// # let mut world = World::new();88/// let mut entity = world.spawn_empty();89///90/// entity.entry().or_insert(Comp(4));91/// # let entity_id = entity.id();92/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 4);93///94/// # let mut entity = world.get_entity_mut(entity_id).unwrap();95/// entity.entry().or_insert(Comp(15)).into_mut().0 *= 2;96/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 8);97/// ```98#[inline]99pub fn or_insert(self, default: T) -> OccupiedComponentEntry<'w, 'a, T> {100match self {101ComponentEntry::Occupied(entry) => entry,102ComponentEntry::Vacant(entry) => entry.insert(default),103}104}105106/// Ensures the entry has this component by inserting the result of the default function if107/// empty, and returns a mutable reference to this component in the entry.108///109/// # Examples110///111/// ```112/// # use bevy_ecs::prelude::*;113/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]114/// struct Comp(u32);115///116/// # let mut world = World::new();117/// let mut entity = world.spawn_empty();118///119/// entity.entry().or_insert_with(|| Comp(4));120/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 4);121/// ```122#[inline]123pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> OccupiedComponentEntry<'w, 'a, T> {124match self {125ComponentEntry::Occupied(entry) => entry,126ComponentEntry::Vacant(entry) => entry.insert(default()),127}128}129}130131impl<'w, 'a, T: Component + Default> ComponentEntry<'w, 'a, T> {132/// Ensures the entry has this component by inserting the default value if empty, and133/// returns a mutable reference to this component in the entry.134///135/// # Examples136///137/// ```138/// # use bevy_ecs::prelude::*;139/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]140/// struct Comp(u32);141///142/// # let mut world = World::new();143/// let mut entity = world.spawn_empty();144///145/// entity.entry::<Comp>().or_default();146/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 0);147/// ```148#[inline]149pub fn or_default(self) -> OccupiedComponentEntry<'w, 'a, T> {150match self {151ComponentEntry::Occupied(entry) => entry,152ComponentEntry::Vacant(entry) => entry.insert(Default::default()),153}154}155}156157/// A view into an occupied entry in a [`EntityWorldMut`]. It is part of the [`OccupiedComponentEntry`] enum.158///159/// The contained entity must have the component type parameter if we have this struct.160pub struct OccupiedComponentEntry<'w, 'a, T: Component> {161pub(crate) entity_world: &'a mut EntityWorldMut<'w>,162pub(crate) _marker: PhantomData<T>,163}164165impl<'w, 'a, T: Component> OccupiedComponentEntry<'w, 'a, T> {166/// Gets a reference to the component in the entry.167///168/// # Examples169///170/// ```171/// # use bevy_ecs::{prelude::*, world::ComponentEntry};172/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]173/// struct Comp(u32);174///175/// # let mut world = World::new();176/// let mut entity = world.spawn(Comp(5));177///178/// if let ComponentEntry::Occupied(o) = entity.entry::<Comp>() {179/// assert_eq!(o.get().0, 5);180/// }181/// ```182#[inline]183pub fn get(&self) -> &T {184// This shouldn't panic because if we have an OccupiedComponentEntry the component must exist.185self.entity_world.get::<T>().unwrap()186}187188/// Replaces the component of the entry.189///190/// # Examples191///192/// ```193/// # use bevy_ecs::{prelude::*, world::ComponentEntry};194/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]195/// struct Comp(u32);196///197/// # let mut world = World::new();198/// let mut entity = world.spawn(Comp(5));199///200/// if let ComponentEntry::Occupied(mut o) = entity.entry::<Comp>() {201/// o.insert(Comp(10));202/// }203///204/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 10);205/// ```206#[inline]207pub fn insert(&mut self, component: T) {208self.entity_world.insert(component);209}210211/// Removes the component from the entry and returns it.212///213/// # Examples214///215/// ```216/// # use bevy_ecs::{prelude::*, world::ComponentEntry};217/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]218/// struct Comp(u32);219///220/// # let mut world = World::new();221/// let mut entity = world.spawn(Comp(5));222///223/// if let ComponentEntry::Occupied(o) = entity.entry::<Comp>() {224/// assert_eq!(o.take(), Comp(5));225/// }226///227/// assert_eq!(world.query::<&Comp>().iter(&world).len(), 0);228/// ```229#[inline]230pub fn take(self) -> T {231// This shouldn't panic because if we have an OccupiedComponentEntry the component must exist.232self.entity_world.take().unwrap()233}234}235236impl<'w, 'a, T: Component<Mutability = Mutable>> OccupiedComponentEntry<'w, 'a, T> {237/// Gets a mutable reference to the component in the entry.238///239/// If you need a reference to the [`OccupiedComponentEntry`] which may outlive the destruction of240/// the [`OccupiedComponentEntry`] value, see [`into_mut`].241///242/// [`into_mut`]: Self::into_mut243///244/// # Examples245///246/// ```247/// # use bevy_ecs::{prelude::*, world::ComponentEntry};248/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]249/// struct Comp(u32);250///251/// # let mut world = World::new();252/// let mut entity = world.spawn(Comp(5));253///254/// if let ComponentEntry::Occupied(mut o) = entity.entry::<Comp>() {255/// o.get_mut().0 += 10;256/// assert_eq!(o.get().0, 15);257///258/// // We can use the same Entry multiple times.259/// o.get_mut().0 += 2260/// }261///262/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 17);263/// ```264#[inline]265pub fn get_mut(&mut self) -> Mut<'_, T> {266// This shouldn't panic because if we have an OccupiedComponentEntry the component must exist.267self.entity_world.get_mut::<T>().unwrap()268}269270/// Converts the [`OccupiedComponentEntry`] into a mutable reference to the value in the entry with271/// a lifetime bound to the `EntityWorldMut`.272///273/// If you need multiple references to the [`OccupiedComponentEntry`], see [`get_mut`].274///275/// [`get_mut`]: Self::get_mut276///277/// # Examples278///279/// ```280/// # use bevy_ecs::{prelude::*, world::ComponentEntry};281/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]282/// struct Comp(u32);283///284/// # let mut world = World::new();285/// let mut entity = world.spawn(Comp(5));286///287/// if let ComponentEntry::Occupied(o) = entity.entry::<Comp>() {288/// o.into_mut().0 += 10;289/// }290///291/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 15);292/// ```293#[inline]294pub fn into_mut(self) -> Mut<'a, T> {295// This shouldn't panic because if we have an OccupiedComponentEntry the component must exist.296self.entity_world.get_mut().unwrap()297}298}299300/// A view into a vacant entry in a [`EntityWorldMut`]. It is part of the [`ComponentEntry`] enum.301pub struct VacantComponentEntry<'w, 'a, T: Component> {302pub(crate) entity_world: &'a mut EntityWorldMut<'w>,303pub(crate) _marker: PhantomData<T>,304}305306impl<'w, 'a, T: Component> VacantComponentEntry<'w, 'a, T> {307/// Inserts the component into the [`VacantComponentEntry`] and returns an [`OccupiedComponentEntry`].308///309/// # Examples310///311/// ```312/// # use bevy_ecs::{prelude::*, world::ComponentEntry};313/// #[derive(Component, Default, Clone, Copy, Debug, PartialEq)]314/// struct Comp(u32);315///316/// # let mut world = World::new();317/// let mut entity = world.spawn_empty();318///319/// if let ComponentEntry::Vacant(v) = entity.entry::<Comp>() {320/// v.insert(Comp(10));321/// }322///323/// assert_eq!(world.query::<&Comp>().single(&world).unwrap().0, 10);324/// ```325#[inline]326pub fn insert(self, component: T) -> OccupiedComponentEntry<'w, 'a, T> {327self.entity_world.insert(component);328OccupiedComponentEntry {329entity_world: self.entity_world,330_marker: PhantomData,331}332}333}334335336