Skip to main content

bevy_ecs/world/
filtered_resource.rs

1use crate::{
2    change_detection::{ComponentTicksMut, ComponentTicksRef, Mut, MutUntyped, Ref, Tick},
3    component::ComponentId,
4    query::Access,
5    resource::Resource,
6    world::{unsafe_world_cell::UnsafeWorldCell, World},
7};
8use bevy_ptr::Ptr;
9
10use super::error::ResourceFetchError;
11
12/// Provides read-only access to a set of [`Resource`]s defined by the contained [`Access`].
13///
14/// Use [`FilteredResourcesMut`] if you need mutable access to some resources.
15///
16/// To be useful as a [`SystemParam`](crate::system::SystemParam),
17/// this must be configured using a [`FilteredResourcesParamBuilder`](crate::system::FilteredResourcesParamBuilder)
18/// to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
19///
20/// # Examples
21///
22/// ```
23/// # use bevy_ecs::{prelude::*, system::*};
24/// #
25/// # #[derive(Default, Resource)]
26/// # struct A;
27/// #
28/// # #[derive(Default, Resource)]
29/// # struct B;
30/// #
31/// # #[derive(Default, Resource)]
32/// # struct C;
33/// #
34/// # let mut world = World::new();
35/// // Use `FilteredResourcesParamBuilder` to declare access to resources.
36/// let system = (FilteredResourcesParamBuilder::new(|builder| {
37///     builder.add_read::<B>().add_read::<C>();
38/// }),)
39///     .build_state(&mut world)
40///     .build_system(resource_system);
41///
42/// world.init_resource::<A>();
43/// world.init_resource::<C>();
44///
45/// fn resource_system(res: FilteredResources) {
46///     // The resource exists, but we have no access, so we can't read it.
47///     assert!(res.get::<A>().is_err());
48///     // The resource doesn't exist, so we can't read it.
49///     assert!(res.get::<B>().is_err());
50///     // The resource exists and we have access, so we can read it.
51///     let c = res.get::<C>().unwrap();
52///     // The type parameter can be left out if it can be determined from use.
53///     let c: Ref<C> = res.get().unwrap();
54/// }
55/// #
56/// # world.run_system_once(system);
57/// ```
58///
59/// This can be used alongside ordinary [`Res`](crate::system::Res) and [`ResMut`](crate::system::ResMut) parameters if they do not conflict.
60///
61/// ```
62/// # use bevy_ecs::{prelude::*, system::*};
63/// #
64/// # #[derive(Default, Resource)]
65/// # struct A;
66/// #
67/// # #[derive(Default, Resource)]
68/// # struct B;
69/// #
70/// # let mut world = World::new();
71/// # world.init_resource::<A>();
72/// # world.init_resource::<B>();
73/// #
74/// let system = (
75///     FilteredResourcesParamBuilder::new(|builder| {
76///         builder.add_read::<A>();
77///     }),
78///     ParamBuilder,
79///     ParamBuilder,
80/// )
81///     .build_state(&mut world)
82///     .build_system(resource_system);
83///
84/// // Read access to A does not conflict with read access to A or write access to B.
85/// fn resource_system(filtered: FilteredResources, res_a: Res<A>, res_mut_b: ResMut<B>) {
86///     let res_a_2: Ref<A> = filtered.get::<A>().unwrap();
87/// }
88/// #
89/// # world.run_system_once(system);
90/// ```
91///
92/// But it will conflict if it tries to read the same resource that another parameter writes.
93///
94/// ```should_panic
95/// # use bevy_ecs::{prelude::*, system::*};
96/// #
97/// # #[derive(Default, Resource)]
98/// # struct A;
99/// #
100/// # let mut world = World::new();
101/// # world.init_resource::<A>();
102/// #
103/// let system = (
104///     FilteredResourcesParamBuilder::new(|builder| {
105///         builder.add_read::<A>();
106///     }),
107///     ParamBuilder,
108/// )
109///     .build_state(&mut world)
110///     .build_system(invalid_resource_system);
111///
112/// // Read access to A conflicts with write access to A.
113/// fn invalid_resource_system(filtered: FilteredResources, res_mut_a: ResMut<A>) { }
114/// #
115/// # world.run_system_once(system);
116/// ```
117#[derive(Clone, Copy)]
118#[deprecated(
119    since = "0.20.0",
120    note = "Use `QueryState` and `QueryBuilder` instead."
121)]
122pub struct FilteredResources<'w, 's> {
123    world: UnsafeWorldCell<'w>,
124    access: &'s Access,
125    last_run: Tick,
126    this_run: Tick,
127}
128
129#[expect(deprecated, reason = "`FilteredResources` will be removed.")]
130impl<'w, 's> FilteredResources<'w, 's> {
131    /// Creates a new [`FilteredResources`].
132    /// # Safety
133    /// It is the callers responsibility to ensure that nothing else may access the any resources in the `world` in a way that conflicts with `access`.
134    pub(crate) unsafe fn new(
135        world: UnsafeWorldCell<'w>,
136        access: &'s Access,
137        last_run: Tick,
138        this_run: Tick,
139    ) -> Self {
140        Self {
141            world,
142            access,
143            last_run,
144            this_run,
145        }
146    }
147
148    /// Returns a reference to the underlying [`Access`].
149    pub fn access(&self) -> &Access {
150        self.access
151    }
152
153    /// Returns `true` if the `FilteredResources` has access to the given resource.
154    /// Note that [`Self::get()`] may still return `Err` if the resource does not exist.
155    pub fn has_read<R: Resource>(&self) -> bool {
156        let component_id = self.world.components().component_id::<R>();
157        component_id.is_some_and(|component_id| self.access.has_read(component_id))
158    }
159
160    /// Gets a reference to the resource of the given type if it exists and the `FilteredResources` has access to it.
161    pub fn get<R: Resource>(&self) -> Result<Ref<'w, R>, ResourceFetchError> {
162        let component_id = self
163            .world
164            .components()
165            .valid_component_id::<R>()
166            .ok_or(ResourceFetchError::NotRegistered)?;
167        if !self.access.has_read(component_id) {
168            return Err(ResourceFetchError::NoResourceAccess(component_id));
169        }
170
171        // SAFETY: We have read access to this resource
172        let (value, ticks) = unsafe { self.world.get_resource_with_ticks(component_id) }
173            .ok_or(ResourceFetchError::DoesNotExist(component_id))?;
174
175        Ok(Ref {
176            // SAFETY: `component_id` was obtained from the type ID of `R`.
177            value: unsafe { value.deref() },
178            // SAFETY: We have read access to the resource, so no mutable reference can exist.
179            ticks: unsafe {
180                ComponentTicksRef::from_tick_cells(ticks, self.last_run, self.this_run)
181            },
182        })
183    }
184
185    /// Gets a pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
186    pub fn get_by_id(&self, component_id: ComponentId) -> Result<Ptr<'w>, ResourceFetchError> {
187        if !self.access.has_read(component_id) {
188            return Err(ResourceFetchError::NoResourceAccess(component_id));
189        }
190        // SAFETY: We have read access to this resource
191        unsafe { self.world.get_resource_by_id(component_id) }
192            .ok_or(ResourceFetchError::DoesNotExist(component_id))
193    }
194}
195
196#[expect(deprecated, reason = "`FilteredResources` will be removed.")]
197impl<'w, 's> From<FilteredResourcesMut<'w, 's>> for FilteredResources<'w, 's> {
198    fn from(resources: FilteredResourcesMut<'w, 's>) -> Self {
199        // SAFETY:
200        // - `FilteredResourcesMut` guarantees exclusive access to all resources in the new `FilteredResources`.
201        unsafe {
202            FilteredResources::new(
203                resources.world,
204                resources.access,
205                resources.last_run,
206                resources.this_run,
207            )
208        }
209    }
210}
211
212#[expect(deprecated, reason = "`FilteredResources` will be removed.")]
213impl<'w, 's> From<&'w FilteredResourcesMut<'_, 's>> for FilteredResources<'w, 's> {
214    fn from(resources: &'w FilteredResourcesMut<'_, 's>) -> Self {
215        // SAFETY:
216        // - `FilteredResourcesMut` guarantees exclusive access to all components in the new `FilteredResources`.
217        unsafe {
218            FilteredResources::new(
219                resources.world,
220                resources.access,
221                resources.last_run,
222                resources.this_run,
223            )
224        }
225    }
226}
227
228#[expect(deprecated, reason = "`FilteredResources` will be removed.")]
229impl<'w> From<&'w World> for FilteredResources<'w, 'static> {
230    fn from(value: &'w World) -> Self {
231        const READ_ALL_RESOURCES: &Access = const { &Access::new_read_all() };
232
233        let last_run = value.last_change_tick();
234        let this_run = value.read_change_tick();
235        // SAFETY: We have a reference to the entire world, so nothing else can alias with read access to all resources.
236        unsafe {
237            Self::new(
238                value.as_unsafe_world_cell_readonly(),
239                READ_ALL_RESOURCES,
240                last_run,
241                this_run,
242            )
243        }
244    }
245}
246
247#[expect(deprecated, reason = "`FilteredResources` will be removed.")]
248impl<'w> From<&'w mut World> for FilteredResources<'w, 'static> {
249    fn from(value: &'w mut World) -> Self {
250        Self::from(&*value)
251    }
252}
253
254/// Provides mutable access to a set of [`Resource`]s defined by the contained [`Access`].
255///
256/// Use [`FilteredResources`] if you only need read-only access to resources.
257///
258/// To be useful as a [`SystemParam`](crate::system::SystemParam),
259/// this must be configured using a [`FilteredResourcesMutParamBuilder`](crate::system::FilteredResourcesMutParamBuilder)
260/// to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
261///
262/// # Examples
263///
264/// ```
265/// # use bevy_ecs::{prelude::*, system::*};
266/// #
267/// # #[derive(Default, Resource)]
268/// # struct A;
269/// #
270/// # #[derive(Default, Resource)]
271/// # struct B;
272/// #
273/// # #[derive(Default, Resource)]
274/// # struct C;
275/// #
276/// # #[derive(Default, Resource)]
277/// # struct D;
278/// #
279/// # let mut world = World::new();
280/// // Use `FilteredResourcesMutParamBuilder` to declare access to resources.
281/// let system = (FilteredResourcesMutParamBuilder::new(|builder| {
282///     builder.add_write::<B>().add_read::<C>().add_write::<D>();
283/// }),)
284///     .build_state(&mut world)
285///     .build_system(resource_system);
286///
287/// world.init_resource::<A>();
288/// world.init_resource::<C>();
289/// world.init_resource::<D>();
290///
291/// fn resource_system(mut res: FilteredResourcesMut) {
292///     // The resource exists, but we have no access, so we can't read it or write it.
293///     assert!(res.get::<A>().is_err());
294///     assert!(res.get_mut::<A>().is_err());
295///     // The resource doesn't exist, so we can't read it or write it.
296///     assert!(res.get::<B>().is_err());
297///     assert!(res.get_mut::<B>().is_err());
298///     // The resource exists and we have read access, so we can read it but not write it.
299///     let c = res.get::<C>().unwrap();
300///     assert!(res.get_mut::<C>().is_err());
301///     // The resource exists and we have write access, so we can read it or write it.
302///     let d = res.get::<D>().unwrap();
303///     let d = res.get_mut::<D>().unwrap();
304///     // The type parameter can be left out if it can be determined from use.
305///     let c: Ref<C> = res.get().unwrap();
306/// }
307/// #
308/// # world.run_system_once(system);
309/// ```
310///
311/// This can be used alongside ordinary [`Res`](crate::system::ResMut) and [`ResMut`](crate::system::ResMut) parameters if they do not conflict.
312///
313/// ```
314/// # use bevy_ecs::{prelude::*, system::*};
315/// #
316/// # #[derive(Default, Resource)]
317/// # struct A;
318/// #
319/// # #[derive(Default, Resource)]
320/// # struct B;
321/// #
322/// # #[derive(Default, Resource)]
323/// # struct C;
324/// #
325/// # let mut world = World::new();
326/// # world.init_resource::<A>();
327/// # world.init_resource::<B>();
328/// # world.init_resource::<C>();
329/// #
330/// let system = (
331///     FilteredResourcesMutParamBuilder::new(|builder| {
332///         builder.add_read::<A>().add_write::<B>();
333///     }),
334///     ParamBuilder,
335///     ParamBuilder,
336/// )
337///     .build_state(&mut world)
338///     .build_system(resource_system);
339///
340/// // Read access to A does not conflict with read access to A or write access to C.
341/// // Write access to B does not conflict with access to A or C.
342/// fn resource_system(mut filtered: FilteredResourcesMut, res_a: Res<A>, res_mut_c: ResMut<C>) {
343///     let res_a_2: Ref<A> = filtered.get::<A>().unwrap();
344///     let res_mut_b: Mut<B> = filtered.get_mut::<B>().unwrap();
345/// }
346/// #
347/// # world.run_system_once(system);
348/// ```
349///
350/// But it will conflict if it tries to read the same resource that another parameter writes,
351/// or write the same resource that another parameter reads.
352///
353/// ```should_panic
354/// # use bevy_ecs::{prelude::*, system::*};
355/// #
356/// # #[derive(Default, Resource)]
357/// # struct A;
358/// #
359/// # let mut world = World::new();
360/// # world.init_resource::<A>();
361/// #
362/// let system = (
363///     FilteredResourcesMutParamBuilder::new(|builder| {
364///         builder.add_write::<A>();
365///     }),
366///     ParamBuilder,
367/// )
368///     .build_state(&mut world)
369///     .build_system(invalid_resource_system);
370///
371/// // Read access to A conflicts with write access to A.
372/// fn invalid_resource_system(filtered: FilteredResourcesMut, res_a: Res<A>) { }
373/// #
374/// # world.run_system_once(system);
375/// ```
376#[deprecated(
377    since = "0.20.0",
378    note = "Use `QueryState` and `QueryBuilder` instead."
379)]
380pub struct FilteredResourcesMut<'w, 's> {
381    world: UnsafeWorldCell<'w>,
382    access: &'s Access,
383    last_run: Tick,
384    this_run: Tick,
385}
386
387#[expect(deprecated, reason = "`FilteredResourcesMut` will be removed.")]
388impl<'w, 's> FilteredResourcesMut<'w, 's> {
389    /// Creates a new [`FilteredResources`].
390    /// # Safety
391    /// It is the callers responsibility to ensure that nothing else may access the any resources in the `world` in a way that conflicts with `access`.
392    pub(crate) unsafe fn new(
393        world: UnsafeWorldCell<'w>,
394        access: &'s Access,
395        last_run: Tick,
396        this_run: Tick,
397    ) -> Self {
398        Self {
399            world,
400            access,
401            last_run,
402            this_run,
403        }
404    }
405
406    /// Gets read-only access to all of the resources this `FilteredResourcesMut` can access.
407    pub fn as_readonly(&self) -> FilteredResources<'_, 's> {
408        FilteredResources::from(self)
409    }
410
411    /// Returns a new instance with a shorter lifetime.
412    /// This is useful if you have `&mut FilteredResourcesMut`, but you need `FilteredResourcesMut`.
413    pub fn reborrow(&mut self) -> FilteredResourcesMut<'_, 's> {
414        // SAFETY: We have exclusive access to this access for the duration of `'_`, so there cannot be anything else that conflicts.
415        unsafe { Self::new(self.world, self.access, self.last_run, self.this_run) }
416    }
417
418    /// Returns a reference to the underlying [`Access`].
419    pub fn access(&self) -> &Access {
420        self.access
421    }
422
423    /// Returns `true` if the `FilteredResources` has read access to the given resource.
424    /// Note that [`Self::get()`] may still return `Err` if the resource does not exist.
425    pub fn has_read<R: Resource>(&self) -> bool {
426        let component_id = self.world.components().component_id::<R>();
427        component_id.is_some_and(|component_id| self.access.has_read(component_id))
428    }
429
430    /// Returns `true` if the `FilteredResources` has write access to the given resource.
431    /// Note that [`Self::get_mut()`] may still return `Err` if the resource does not exist.
432    pub fn has_write<R: Resource>(&self) -> bool {
433        let component_id = self.world.components().component_id::<R>();
434        component_id.is_some_and(|component_id| self.access.has_write(component_id))
435    }
436
437    /// Gets a reference to the resource of the given type if it exists and the `FilteredResources` has access to it.
438    pub fn get<R: Resource>(&self) -> Result<Ref<'_, R>, ResourceFetchError> {
439        self.as_readonly().get()
440    }
441
442    /// Gets a pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
443    pub fn get_by_id(&self, component_id: ComponentId) -> Result<Ptr<'_>, ResourceFetchError> {
444        self.as_readonly().get_by_id(component_id)
445    }
446
447    /// Gets a mutable reference to the resource of the given type if it exists and the `FilteredResources` has access to it.
448    pub fn get_mut<R: Resource>(&mut self) -> Result<Mut<'_, R>, ResourceFetchError> {
449        // SAFETY: We have exclusive access to the resources in `access` for `'_`, and we shorten the returned lifetime to that.
450        unsafe { self.get_mut_unchecked() }
451    }
452
453    /// Gets a mutable pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
454    pub fn get_mut_by_id(
455        &mut self,
456        component_id: ComponentId,
457    ) -> Result<MutUntyped<'_>, ResourceFetchError> {
458        // SAFETY: We have exclusive access to the resources in `access` for `'_`, and we shorten the returned lifetime to that.
459        unsafe { self.get_mut_by_id_unchecked(component_id) }
460    }
461
462    /// Consumes self and gets mutable access to resource of the given type with the world `'w` lifetime if it exists and the `FilteredResources` has access to it.
463    pub fn into_mut<R: Resource>(mut self) -> Result<Mut<'w, R>, ResourceFetchError> {
464        // SAFETY: This consumes self, so we have exclusive access to the resources in `access` for the entirety of `'w`.
465        unsafe { self.get_mut_unchecked() }
466    }
467
468    /// Consumes self and gets mutable access to resource with the given [`ComponentId`] with the world `'w` lifetime if it exists and the `FilteredResources` has access to it.
469    pub fn into_mut_by_id(
470        mut self,
471        component_id: ComponentId,
472    ) -> Result<MutUntyped<'w>, ResourceFetchError> {
473        // SAFETY: This consumes self, so we have exclusive access to the resources in `access` for the entirety of `'w`.
474        unsafe { self.get_mut_by_id_unchecked(component_id) }
475    }
476
477    /// Gets a mutable pointer to the resource of the given type if it exists and the `FilteredResources` has access to it.
478    /// # Safety
479    /// It is the callers responsibility to ensure that there are no conflicting borrows of anything in `access` for the duration of the returned value.
480    unsafe fn get_mut_unchecked<R: Resource>(&mut self) -> Result<Mut<'w, R>, ResourceFetchError> {
481        let component_id = self
482            .world
483            .components()
484            .valid_component_id::<R>()
485            .ok_or(ResourceFetchError::NotRegistered)?;
486        // SAFETY: THe caller ensures that there are no conflicting borrows.
487        unsafe { self.get_mut_by_id_unchecked(component_id) }
488            // SAFETY: The underlying type of the resource is `R`.
489            .map(|ptr| unsafe { ptr.with_type::<R>() })
490    }
491
492    /// Gets a mutable pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
493    /// # Safety
494    /// It is the callers responsibility to ensure that there are no conflicting borrows of anything in `access` for the duration of the returned value.
495    unsafe fn get_mut_by_id_unchecked(
496        &mut self,
497        component_id: ComponentId,
498    ) -> Result<MutUntyped<'w>, ResourceFetchError> {
499        if !self.access.has_write(component_id) {
500            return Err(ResourceFetchError::NoResourceAccess(component_id));
501        }
502
503        // SAFETY: We have read access to this resource
504        let (value, ticks) = unsafe { self.world.get_resource_with_ticks(component_id) }
505            .ok_or(ResourceFetchError::DoesNotExist(component_id))?;
506
507        // SAFETY: Resource is present, so its component info exists
508        let mutable = unsafe { self.world.components().get_info_unchecked(component_id) }.mutable();
509        if !mutable {
510            return Err(ResourceFetchError::Immutable(component_id));
511        }
512
513        Ok(MutUntyped {
514            // SAFETY: We have exclusive access to the underlying storage.
515            value: unsafe { value.assert_unique() },
516            // SAFETY: We have exclusive access to the underlying storage.
517            ticks: unsafe {
518                ComponentTicksMut::from_tick_cells(ticks, self.last_run, self.this_run)
519            },
520        })
521    }
522}
523
524#[expect(deprecated, reason = "`FilteredResourcesMut` will be removed.")]
525impl<'w> From<&'w mut World> for FilteredResourcesMut<'w, 'static> {
526    fn from(value: &'w mut World) -> Self {
527        const WRITE_ALL_RESOURCES: &Access = const { &Access::new_write_all() };
528
529        let last_run = value.last_change_tick();
530        let this_run = value.change_tick();
531        // SAFETY: We have a mutable reference to the entire world, so nothing else can alias with mutable access to all resources.
532        unsafe {
533            Self::new(
534                value.as_unsafe_world_cell_readonly(),
535                WRITE_ALL_RESOURCES,
536                last_run,
537                this_run,
538            )
539        }
540    }
541}
542
543/// Builder struct to define the access for a [`FilteredResources`].
544///
545/// This is passed to a callback in [`FilteredResourcesParamBuilder`](crate::system::FilteredResourcesParamBuilder).
546#[deprecated(since = "0.20.0", note = "Use `QueryBuilder` instead.")]
547pub struct FilteredResourcesBuilder<'w> {
548    world: &'w mut World,
549    access: Access,
550}
551
552#[expect(deprecated, reason = "`FilteredResourcesBuilder` will be removed.")]
553impl<'w> FilteredResourcesBuilder<'w> {
554    /// Creates a new builder with no access.
555    pub fn new(world: &'w mut World) -> Self {
556        Self {
557            world,
558            access: Access::new(),
559        }
560    }
561
562    /// Returns a reference to the underlying [`Access`].
563    pub fn access(&self) -> &Access {
564        &self.access
565    }
566
567    /// Add accesses required to read all resources.
568    pub fn add_read_all(&mut self) -> &mut Self {
569        self.access.read_all();
570        self
571    }
572
573    /// Add accesses required to read the resource of the given type.
574    pub fn add_read<R: Resource>(&mut self) -> &mut Self {
575        let component_id = self
576            .world
577            .components_registrator()
578            .register_component::<R>();
579        self.add_read_by_id(component_id)
580    }
581
582    /// Add accesses required to read the resource with the given [`ComponentId`].
583    pub fn add_read_by_id(&mut self, component_id: ComponentId) -> &mut Self {
584        self.access.add_read(component_id);
585        self
586    }
587
588    /// Create an [`Access`] that represents the accesses of the builder.
589    pub fn build(self) -> Access {
590        self.access
591    }
592}
593
594/// Builder struct to define the access for a [`FilteredResourcesMut`].
595///
596/// This is passed to a callback in [`FilteredResourcesMutParamBuilder`](crate::system::FilteredResourcesMutParamBuilder).
597#[deprecated(since = "0.20.0", note = "Use `QueryBuilder` instead.")]
598pub struct FilteredResourcesMutBuilder<'w> {
599    world: &'w mut World,
600    access: Access,
601}
602
603#[expect(deprecated, reason = "`FilteredResourcesMutBuilder` will be removed.")]
604impl<'w> FilteredResourcesMutBuilder<'w> {
605    /// Creates a new builder with no access.
606    pub fn new(world: &'w mut World) -> Self {
607        Self {
608            world,
609            access: Access::new(),
610        }
611    }
612
613    /// Returns a reference to the underlying [`Access`].
614    pub fn access(&self) -> &Access {
615        &self.access
616    }
617
618    /// Add accesses required to read all resources.
619    pub fn add_read_all(&mut self) -> &mut Self {
620        self.access.read_all();
621        self
622    }
623
624    /// Add accesses required to read the resource of the given type.
625    pub fn add_read<R: Resource>(&mut self) -> &mut Self {
626        let component_id = self
627            .world
628            .components_registrator()
629            .register_component::<R>();
630        self.add_read_by_id(component_id)
631    }
632
633    /// Add accesses required to read the resource with the given [`ComponentId`].
634    pub fn add_read_by_id(&mut self, component_id: ComponentId) -> &mut Self {
635        self.access.add_read(component_id);
636        self
637    }
638
639    /// Add accesses required to get mutable access to all resources.
640    pub fn add_write_all(&mut self) -> &mut Self {
641        self.access.write_all();
642        self
643    }
644
645    /// Add accesses required to get mutable access to the resource of the given type.
646    pub fn add_write<R: Resource>(&mut self) -> &mut Self {
647        let component_id = self
648            .world
649            .components_registrator()
650            .register_component::<R>();
651        self.add_write_by_id(component_id)
652    }
653
654    /// Add accesses required to get mutable access to the resource with the given [`ComponentId`].
655    pub fn add_write_by_id(&mut self, component_id: ComponentId) -> &mut Self {
656        self.access.add_write(component_id);
657        self
658    }
659
660    /// Create an [`Access`] that represents the accesses of the builder.
661    pub fn build(self) -> Access {
662        self.access
663    }
664}