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