Skip to main content

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}