goud_engine/ecs/world/resources.rs
1use super::super::resource::{Res, ResMut, Resource};
2use super::World;
3
4impl World {
5 // =========================================================================
6 // Resource Management
7 // =========================================================================
8
9 /// Inserts a resource into the world.
10 ///
11 /// Resources are singleton data that exists outside the entity-component
12 /// model. Unlike components, each resource type can only have one instance.
13 ///
14 /// If a resource of this type already exists, it is replaced and the old
15 /// value is returned.
16 ///
17 /// # Type Parameters
18 ///
19 /// - `T`: The resource type (must implement `Send + Sync + 'static`)
20 ///
21 /// # Arguments
22 ///
23 /// * `resource` - The resource value to insert
24 ///
25 /// # Returns
26 ///
27 /// - `Some(old_resource)` if a resource of this type was replaced
28 /// - `None` if this is a new resource type
29 ///
30 /// # Example
31 ///
32 /// ```
33 /// use goud_engine::ecs::World;
34 ///
35 /// struct Time { delta: f32, total: f32 }
36 ///
37 /// let mut world = World::new();
38 /// world.insert_resource(Time { delta: 0.016, total: 0.0 });
39 ///
40 /// let time = world.get_resource::<Time>().unwrap();
41 /// assert_eq!(time.delta, 0.016);
42 /// ```
43 #[inline]
44 pub fn insert_resource<T: Resource>(&mut self, resource: T) -> Option<T> {
45 self.resources.insert(resource)
46 }
47
48 /// Removes a resource from the world and returns it.
49 ///
50 /// # Type Parameters
51 ///
52 /// - `T`: The resource type to remove
53 ///
54 /// # Returns
55 ///
56 /// - `Some(resource)` if the resource existed
57 /// - `None` if no resource of this type exists
58 ///
59 /// # Example
60 ///
61 /// ```
62 /// use goud_engine::ecs::World;
63 ///
64 /// struct Config { debug: bool }
65 ///
66 /// let mut world = World::new();
67 /// world.insert_resource(Config { debug: true });
68 ///
69 /// let config = world.remove_resource::<Config>();
70 /// assert!(config.is_some());
71 /// assert!(world.get_resource::<Config>().is_none());
72 /// ```
73 #[inline]
74 pub fn remove_resource<T: Resource>(&mut self) -> Option<T> {
75 self.resources.remove()
76 }
77
78 /// Returns an immutable reference to a resource.
79 ///
80 /// # Type Parameters
81 ///
82 /// - `T`: The resource type to access
83 ///
84 /// # Returns
85 ///
86 /// - `Some(&T)` if the resource exists
87 /// - `None` if no resource of this type exists
88 ///
89 /// # Example
90 ///
91 /// ```
92 /// use goud_engine::ecs::World;
93 ///
94 /// struct Score(u32);
95 ///
96 /// let mut world = World::new();
97 /// world.insert_resource(Score(100));
98 ///
99 /// if let Some(score) = world.get_resource::<Score>() {
100 /// println!("Score: {}", score.0);
101 /// }
102 /// ```
103 #[inline]
104 pub fn get_resource<T: Resource>(&self) -> Option<&T> {
105 self.resources.get()
106 }
107
108 /// Returns a mutable reference to a resource.
109 ///
110 /// # Type Parameters
111 ///
112 /// - `T`: The resource type to access
113 ///
114 /// # Returns
115 ///
116 /// - `Some(&mut T)` if the resource exists
117 /// - `None` if no resource of this type exists
118 ///
119 /// # Example
120 ///
121 /// ```
122 /// use goud_engine::ecs::World;
123 ///
124 /// struct Score(u32);
125 ///
126 /// let mut world = World::new();
127 /// world.insert_resource(Score(100));
128 ///
129 /// if let Some(score) = world.get_resource_mut::<Score>() {
130 /// score.0 += 50;
131 /// }
132 ///
133 /// assert_eq!(world.get_resource::<Score>().unwrap().0, 150);
134 /// ```
135 #[inline]
136 pub fn get_resource_mut<T: Resource>(&mut self) -> Option<&mut T> {
137 self.resources.get_mut()
138 }
139
140 /// Returns an immutable [`Res`] wrapper for a resource.
141 ///
142 /// This is the primary way to access resources in systems. The `Res<T>`
143 /// wrapper provides convenient access via `Deref`.
144 ///
145 /// # Type Parameters
146 ///
147 /// - `T`: The resource type to access
148 ///
149 /// # Returns
150 ///
151 /// - `Some(Res<T>)` if the resource exists
152 /// - `None` if no resource of this type exists
153 ///
154 /// # Example
155 ///
156 /// ```
157 /// use goud_engine::ecs::World;
158 ///
159 /// struct Time { delta: f32 }
160 ///
161 /// let mut world = World::new();
162 /// world.insert_resource(Time { delta: 0.016 });
163 ///
164 /// let time = world.resource::<Time>().unwrap();
165 /// assert_eq!(time.delta, 0.016);
166 /// ```
167 #[inline]
168 pub fn resource<T: Resource>(&self) -> Option<Res<'_, T>> {
169 self.resources.get::<T>().map(Res::new)
170 }
171
172 /// Returns a mutable [`ResMut`] wrapper for a resource.
173 ///
174 /// This is the primary way to mutably access resources in systems. The
175 /// `ResMut<T>` wrapper provides convenient access via `Deref` and `DerefMut`.
176 ///
177 /// # Type Parameters
178 ///
179 /// - `T`: The resource type to access
180 ///
181 /// # Returns
182 ///
183 /// - `Some(ResMut<T>)` if the resource exists
184 /// - `None` if no resource of this type exists
185 ///
186 /// # Example
187 ///
188 /// ```
189 /// use goud_engine::ecs::World;
190 ///
191 /// struct Score(u32);
192 ///
193 /// let mut world = World::new();
194 /// world.insert_resource(Score(100));
195 ///
196 /// {
197 /// let mut score = world.resource_mut::<Score>().unwrap();
198 /// score.0 += 50;
199 /// }
200 ///
201 /// assert_eq!(world.get_resource::<Score>().unwrap().0, 150);
202 /// ```
203 #[inline]
204 pub fn resource_mut<T: Resource>(&mut self) -> Option<ResMut<'_, T>> {
205 self.resources.get_mut::<T>().map(ResMut::new)
206 }
207
208 /// Returns `true` if a resource of the specified type exists.
209 ///
210 /// # Type Parameters
211 ///
212 /// - `T`: The resource type to check
213 ///
214 /// # Example
215 ///
216 /// ```
217 /// use goud_engine::ecs::World;
218 ///
219 /// struct Score(u32);
220 ///
221 /// let mut world = World::new();
222 /// assert!(!world.contains_resource::<Score>());
223 ///
224 /// world.insert_resource(Score(100));
225 /// assert!(world.contains_resource::<Score>());
226 /// ```
227 #[inline]
228 pub fn contains_resource<T: Resource>(&self) -> bool {
229 self.resources.contains::<T>()
230 }
231
232 /// Returns the number of resources in the world.
233 ///
234 /// # Example
235 ///
236 /// ```
237 /// use goud_engine::ecs::World;
238 ///
239 /// struct Score(u32);
240 /// struct Time { delta: f32 }
241 ///
242 /// let mut world = World::new();
243 /// assert_eq!(world.resource_count(), 0);
244 ///
245 /// world.insert_resource(Score(100));
246 /// world.insert_resource(Time { delta: 0.016 });
247 /// assert_eq!(world.resource_count(), 2);
248 /// ```
249 #[inline]
250 pub fn resource_count(&self) -> usize {
251 self.resources.len()
252 }
253
254 /// Clears all resources from the world.
255 ///
256 /// This removes all resources but leaves entities and components intact.
257 ///
258 /// # Example
259 ///
260 /// ```
261 /// use goud_engine::ecs::World;
262 ///
263 /// struct Score(u32);
264 ///
265 /// let mut world = World::new();
266 /// world.insert_resource(Score(100));
267 ///
268 /// world.clear_resources();
269 /// assert_eq!(world.resource_count(), 0);
270 /// ```
271 #[inline]
272 pub fn clear_resources(&mut self) {
273 self.resources.clear();
274 }
275}