zengine_ecs/system/
mod.rs1use zengine_macro::all_tuples;
64
65use crate::world::World;
66
67mod system_parameter;
68pub use system_parameter::*;
69
70pub trait SystemFunction<P: SystemParam> {
72 fn run_function(&self, parameter: SystemParamItem<P>);
73}
74
75pub trait IntoSystem<P: SystemParam> {
77 type System: SystemFunction<P>;
78
79 fn into_system(self) -> SystemWrapper<Self::System, P>;
80}
81
82impl<Param: SystemParam, F> IntoSystem<Param> for F
83where
84 F: SystemFunction<Param>,
85{
86 type System = F;
87 fn into_system(self) -> SystemWrapper<Self::System, Param> {
88 SystemWrapper {
89 _marker: std::marker::PhantomData::default(),
90 function: self,
91 param_state: Param::Fetch::default(),
92 }
93 }
94}
95
96pub struct SystemWrapper<F: SystemFunction<P>, P: SystemParam> {
98 _marker: std::marker::PhantomData<P>,
99 function: F,
100 param_state: P::Fetch,
101}
102
103pub trait System {
105 fn init(&mut self, world: &mut World);
106
107 fn run(&mut self, world: &World);
108
109 fn apply(&mut self, world: &mut World);
110}
111
112impl<F: SystemFunction<P>, P: SystemParam> System for SystemWrapper<F, P> {
113 fn init(&mut self, world: &mut World) {
114 self.param_state.init(world);
115 }
116
117 fn run(&mut self, world: &World) {
118 let data: <<P as SystemParam>::Fetch as SystemParamFetch>::Item =
119 <P as SystemParam>::Fetch::fetch(&mut self.param_state, world);
120 self.function.run_function(data);
121 }
122
123 fn apply(&mut self, world: &mut World) {
124 self.param_state.apply(world);
125 }
126}
127
128macro_rules! impl_system_function {
129 () => {
130 #[allow(non_snake_case)]
131 impl<'a> SystemParamFetch<'a> for () {
132 type Item = ();
133
134 fn fetch(&mut self, _world: &'a World) -> Self::Item {}
135 }
136
137 impl SystemParam for () {
138 type Fetch = ();
139 }
140
141 #[allow(non_snake_case)]
142 impl<Sys> SystemFunction<()> for Sys
143 where
144 for<'a> &'a Sys: Fn(),
145 {
146 fn run_function(&self, _parameter: SystemParamItem<()>) {
147 #[allow(clippy::too_many_arguments)]
148 fn call_inner(f: impl Fn()) {
149 f()
150 }
151
152 call_inner(self)
153 }
154 }
155 };
156 ($($param: ident),+) => {
157 #[allow(non_snake_case)]
158 impl<'a, $($param: SystemParamFetch<'a>),*> SystemParamFetch<'a> for ($($param,)*) {
159 type Item = ($($param::Item,)*);
160
161 fn init(&mut self, world: &mut World) {
162 let ($($param,)*) = self;
163
164 ($($param::init($param, world),)*);
165 }
166
167 fn fetch(&'a mut self, world: &'a World) -> Self::Item {
168 let ($($param,)*) = self;
169
170 ($($param::fetch($param, world),)*)
171 }
172
173 fn apply(&mut self, world: &mut World) {
174 let ($($param,)*) = self;
175
176 ($($param::apply($param, world),)*);
177 }
178 }
179
180 impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
181 type Fetch = ($($param::Fetch,)*);
182 }
183
184 #[allow(non_snake_case)]
185 impl<$($param: SystemParam),*, Sys> SystemFunction<($($param,)*)> for Sys
186 where
187 for<'a> &'a Sys: Fn( $($param),*)
188 + Fn(
189 $(<<$param as SystemParam>::Fetch as SystemParamFetch>::Item,)*
190 ),
191 {
192 fn run_function(&self, parameter: SystemParamItem<($($param,)*)>) {
193 #[allow(clippy::too_many_arguments)]
194 fn call_inner<$($param),*>(f: impl Fn($($param,)*), $($param: $param,)*) {
195 f($($param,)*)
196 }
197
198 let ($($param,)*) = parameter;
199 call_inner(self, $($param),*)
200 }
201 }
202 }
203}
204all_tuples!(impl_system_function, 0, 12, F);
205
206#[cfg(test)]
207mod tests {
208
209 use crate::{query::Query, world::World, Component, Resource};
210
211 use super::{
212 system_parameter::{Local, Res},
213 IntoSystem, System, SystemParam,
214 };
215
216 #[derive(Default)]
217 struct Executor {
218 world: World,
219 systems: Vec<Box<dyn System>>,
220 }
221
222 impl Executor {
223 fn add_system<Params: SystemParam + 'static>(
224 mut self,
225 system: impl IntoSystem<Params> + 'static,
226 ) -> Self {
227 self.systems.push(Box::new(system.into_system()));
228
229 self
230 }
231 }
232
233 impl Executor {
234 pub fn run(mut self) {
235 for s in self.systems.iter_mut() {
236 s.init(&mut self.world);
237 }
238
239 for s in self.systems.iter_mut() {
240 s.run(&self.world);
241 }
242 }
243 }
244
245 #[derive(PartialEq, Debug)]
246 struct CacheTest {
247 data: u32,
248 }
249 impl Default for CacheTest {
250 fn default() -> Self {
251 Self { data: 6 }
252 }
253 }
254
255 #[derive(Debug, Default)]
256 struct Resource1 {
257 _data: u32,
258 }
259 impl Resource for Resource1 {}
260
261 #[derive(Debug)]
262 struct Component1 {
263 _data: u32,
264 }
265 impl Component for Component1 {}
266
267 fn test() {
268 println!("hello")
269 }
270
271 fn test1(_query: Query<(&Component1,)>) {}
272 fn test2(_res: Res<Resource1>) {}
273 fn test3(_res: Res<Resource1>, _query: Query<(&Component1,)>) {}
274 fn test4(_local: Local<Resource1>, _query: Query<(&Component1,)>) {}
275
276 #[test]
277 fn test_executor() {
278 Executor::default()
279 .add_system(test)
280 .add_system(test1)
281 .add_system(test2)
282 .add_system(test3)
283 .add_system(test4)
284 .run();
285 }
286}