async_ecs/access/read_storage.rs
1use crate::{
2 component::Component,
3 entity::Entities,
4 misc::TryDefault,
5 resource::{Ref, ResourceId},
6 storage::{MaskedStorage, StorageWrapper},
7 system::SystemData,
8 world::World,
9};
10
11/// A storage with read access.
12///
13/// This is just a type alias for a fetched component storage.
14///
15/// The main functionality it provides is listed in the following,
16/// however make sure to also check out the documentation for the
17/// respective methods on `Storage`.
18///
19/// ## Aliasing
20///
21/// **It is strictly disallowed to get both a `ReadStorage` and a `WriteStorage`
22/// of the same component.**
23/// Because Specs uses interior mutability for its resources, we can't check
24/// this at compile time. If you try to do this, you will get a panic.
25///
26/// It is explicitly allowed to get multiple `ReadStorage`s for the same
27/// component.
28///
29/// ## Joining storages
30///
31/// `&ReadStorage` implements `Join`, which allows to do
32/// something like this:
33///
34/// ```
35/// use async_ecs::*;
36///
37/// struct Pos;
38///
39/// impl Component for Pos {
40/// type Storage = VecStorage<Self>;
41/// }
42///
43/// struct Vel;
44///
45/// impl Component for Vel {
46/// type Storage = VecStorage<Self>;
47/// }
48///
49/// let mut world = World::default();
50/// world.register_component::<Pos>();
51/// world.register_component::<Vel>();
52///
53/// let pos_storage = world.component::<Pos>();
54/// let vel_storage = world.component::<Vel>();
55///
56/// for (pos, vel) in (&pos_storage, &vel_storage).join() {}
57/// ```
58///
59/// This joins the position and the velocity storage, which means it only
60/// iterates over the components of entities that have both a position
61/// **and** a velocity.
62///
63/// ## Retrieving single components
64///
65/// If you have an entity (for example because you stored it before
66/// or because you're joining over `Entities`), you can get a single
67/// component by calling `Storage::get`:
68///
69/// ```
70/// # use async_ecs::*;
71/// #
72/// # #[derive(Debug, PartialEq)]
73/// # struct Pos;
74/// # impl Component for Pos { type Storage = VecStorage<Self>; }
75/// #
76/// # #[derive(Debug, PartialEq)]
77/// # struct Vel;
78/// # impl Component for Vel { type Storage = VecStorage<Self>; }
79/// #
80/// # let mut world = World::default();
81/// # world.register_component::<Pos>();
82/// # world.register_component::<Vel>();
83/// #
84/// let entity1 = world.create_entity().with(Pos).build();
85/// let entity2 = world.create_entity().with(Vel).build();
86///
87/// # let pos_storage = world.component::<Pos>();
88/// # let vel_storage = world.component::<Vel>();
89/// assert_eq!(pos_storage.get(entity1), Some(&Pos));
90/// assert_eq!(pos_storage.get(entity2), None);
91///
92/// assert_eq!(vel_storage.get(entity1), None);
93/// assert_eq!(vel_storage.get(entity2), Some(&Vel));
94/// ```
95///
96/// ## Usage as `SystemData`
97///
98/// `ReadStorage` implements `SystemData` which allows you to
99/// get it inside a system by simply adding it to the tuple:
100///
101/// ```
102/// # use async_ecs::*;
103/// #[derive(Debug)]
104/// struct Pos {
105/// x: f32,
106/// y: f32,
107/// }
108///
109/// impl Component for Pos {
110/// type Storage = VecStorage<Self>;
111/// }
112///
113/// struct Sys;
114///
115/// impl<'a> System<'a> for Sys {
116/// type SystemData = (Entities<'a>, ReadStorage<'a, Pos>);
117///
118/// fn run(&mut self, (ent, pos): Self::SystemData) {
119/// for (ent, pos) in (&*ent, &pos).join() {
120/// println!("Entitiy with id {} has a position of {:?}", ent.id(), pos);
121/// }
122/// }
123/// }
124/// ```
125///
126/// These operations can't mutate anything; if you want to do
127/// insertions or modify components, you need to use `WriteStorage`.
128/// Note that you can also use `LazyUpdate` , which does insertions on
129/// `World::maintain`. This allows more concurrency and is designed
130/// to be used for entity initialization.
131pub type ReadStorage<'a, T> = StorageWrapper<'a, T, Ref<'a, MaskedStorage<T>>>;
132
133impl<'a, T> SystemData<'a> for ReadStorage<'a, T>
134where
135 T: Component,
136{
137 fn setup(world: &mut World) {
138 world.register_component_with_storage::<T, _>(TryDefault::unwrap_default);
139 }
140
141 fn fetch(world: &'a World) -> Self {
142 Self::new(world.borrow(), world.borrow())
143 }
144
145 fn reads() -> Vec<ResourceId> {
146 vec![
147 ResourceId::new::<Entities>(),
148 ResourceId::new::<MaskedStorage<T>>(),
149 ]
150 }
151
152 fn writes() -> Vec<ResourceId> {
153 vec![]
154 }
155}