1use std::cell::{Cell, RefCell, RefMut};
2
3thread_local! {
4 static CURRENT_SYSTEM: Cell<Option<&'static str>> = Cell::new(None);
14}
15
16pub(crate) struct CurrentSystemGuard(Option<&'static str>);
20
21impl Drop for CurrentSystemGuard {
22 fn drop(&mut self) {
23 CURRENT_SYSTEM.with(|c| c.set(self.0));
24 }
25}
26
27pub(crate) fn set_current_system(name: &'static str) -> CurrentSystemGuard {
28 let previous = CURRENT_SYSTEM.with(|c| c.replace(Some(name)));
29 CurrentSystemGuard(previous)
30}
31
32fn current_system_suffix() -> String {
33 CURRENT_SYSTEM.with(|c| match c.get() {
34 Some(name) => format!(" (while running system `{name}`)"),
35 None => String::new(),
36 })
37}
38
39pub struct Resources {
45 pub(crate) resource_entity: hecs::Entity,
46 cmds: RefCell<hecs::CommandBuffer>,
47 generation: Cell<u64>,
48}
49
50impl Resources {
51 pub fn new(world: &mut hecs::World) -> Self {
53 Self {
54 resource_entity: world.spawn(()),
55 cmds: RefCell::new(hecs::CommandBuffer::default()),
56 generation: Cell::new(0),
57 }
58 }
59
60 pub fn insert_resource<T>(&mut self, world: &mut hecs::World, res: T)
62 where
63 T: hecs::Component,
64 {
65 world.insert_one(self.resource_entity, res).ok();
66 self.generation.set(self.generation.get() + 1);
67 }
68
69 pub fn get_resource<'a, T>(&self, world: &'a hecs::World) -> hecs::Ref<'a, T>
71 where
72 T: hecs::Component,
73 {
74 world.get::<&T>(self.resource_entity).unwrap_or_else(|_| {
75 panic!(
76 "Resource not found: {}{}",
77 std::any::type_name::<T>(),
78 current_system_suffix()
79 )
80 })
81 }
82
83 pub fn get_resource_mut<'a, T>(&self, world: &'a hecs::World) -> hecs::RefMut<'a, T>
85 where
86 T: hecs::Component,
87 {
88 world.get::<&mut T>(self.resource_entity).unwrap_or_else(|_| {
89 panic!(
90 "Resource not found: {}{}",
91 std::any::type_name::<T>(),
92 current_system_suffix()
93 )
94 })
95 }
96
97 pub fn has_resource<T>(&self, world: &hecs::World) -> bool
99 where
100 T: hecs::Component,
101 {
102 if let Ok(_) = world.get::<&T>(self.resource_entity) {
103 return true;
104 }
105
106 false
107 }
108
109 pub fn get_command_buffer<'a>(&'a self) -> RefMut<'a, hecs::CommandBuffer> {
111 self.cmds.borrow_mut()
112 }
113
114 pub fn try_insert<T>(&mut self, world: &mut hecs::World, res: T) -> bool
118 where
119 T: hecs::Component,
120 {
121 if self.has_resource::<T>(world) {
122 return false;
123 }
124 world.insert_one(self.resource_entity, res).ok();
125 self.generation.set(self.generation.get() + 1);
126 true
127 }
128
129 pub fn generation(&self) -> u64 {
130 self.generation.get()
131 }
132
133 pub(crate) fn bump_generation(&self) {
139 self.generation.set(self.generation.get() + 1);
140 }
141}