bones_lib/reset.rs
1//! Conveniences for resetting a World to its' default state.
2use crate::prelude::*;
3
4/// Convenience type for selecting resources to keep before clearing the
5/// components, entities, and resources on a [`World`].
6/// ```ignore
7/// ResetWorld::standard()
8/// .keep::<Scoreboard>()
9/// .keep::<WritingRust>()
10/// .keep::<TheBugsAway>()
11/// .reset(world);
12/// ```
13/// Reseting the world should likely be the first call in your systems when
14/// applicable so that components are rendered continuously without disappearing
15/// for a frame before respawning world startup components.
16///
17/// You can create the type with [`Self::standard`], which is recommended for
18/// keeping certain special resources like [`SessionOptions`] & [`Entities`] on
19/// creation, or you can use [`Self::empty`] to create a new type that won't
20/// keep any resources on creation.
21///
22/// To add more resources to the list you can use [`self.keep`](Self::keep) with
23/// the specified type, no data needed, and chain the methods like the example
24/// above.
25///
26/// Uses a [`HashSet`] of [`SchemaId`] to determine the resources that will not
27/// be removed from the world on reset.
28#[derive(HasSchema, Default, Clone, Deref, DerefMut)]
29pub struct ResetWorld(pub HashSet<SchemaId>);
30
31impl ResetWorld {
32 /// Create a [`ResetWorld`] with no resources kept as opposed to the
33 /// [`Self::standard`] which keeps certain special resources on creation.
34 pub fn empty() -> Self {
35 Self(HashSet::default())
36 }
37 /// Create a [`ResetWorld`] that already keeps some basic special resources
38 /// that are usually needed like [`SessionOptions`] & [`Entities`].
39 pub fn standard() -> Self {
40 Self::empty()
41 // Even though Entities is completely cleared on reset, it is always
42 // expected everywhere so we can't remove it from the World.
43 .keep::<Entities>()
44 // SessionOptions is re-inserted every frame, but may still be
45 // wanted right after reset and is expected in `Game` right now.
46 .keep::<SessionOptions>()
47 }
48 /// Adds the [`SchemaId`] of the type given to the set of resources to keep
49 /// on reset.
50 ///
51 /// Returns `Self` to allow chaining the method:
52 /// ```ignore
53 /// Self::standard()
54 /// .keep::<Scoreboard>()
55 /// .keep::<WritingRust>()
56 /// .keep::<TheBugsAway>()
57 /// .reset(world);
58 /// ```
59 pub fn keep<T: HasSchema>(mut self) -> Self {
60 self.insert(T::schema().id());
61 self
62 }
63 /// Reset the given [`World`], clearing resources that are not included in
64 /// `self` as well as components and entities.
65 pub fn reset(self, world: &World) {
66 world.resource_mut::<Entities>().kill_all(); // `kill_all` for component clearing
67 world.maintain(); // clear components
68 *world.resource_mut::<Entities>() = Entities::default(); // fully reset entities
69 world.retain_owned_resources(|schema_id| self.contains(&schema_id));
70 }
71 /// Reset the given [`World`]'s resources that are not included in `self`.
72 pub fn reset_resources(self, world: &World) {
73 world.retain_owned_resources(|schema_id| self.contains(&schema_id));
74 }
75}