1use crate::{
2 hierarchy::{HierarchyChangeRes, Name, NonPersistent, Parent, Tag},
3 state::{State, StateChange, StateToken},
4};
5use specs::{
6 world::EntitiesRes, Component, Dispatcher, DispatcherBuilder, Entity, Join, RunNow, System,
7 World,
8};
9use specs_hierarchy::HierarchySystem;
10use std::{
11 cell::RefCell,
12 collections::HashSet,
13 rc::Rc,
14 time::{Duration, Instant},
15};
16
17pub trait AppTimer: Send + Sync {
18 fn tick(&mut self);
19 fn delta_time(&self) -> Duration;
20 fn delta_time_seconds(&self) -> f64;
21}
22
23pub struct StandardAppTimer {
24 timer: Instant,
25 delta_time: Duration,
26 delta_time_seconds: f64,
27}
28
29impl Default for StandardAppTimer {
30 fn default() -> Self {
31 Self {
32 timer: Instant::now(),
33 delta_time: Duration::default(),
34 delta_time_seconds: 0.0,
35 }
36 }
37}
38
39impl AppTimer for StandardAppTimer {
40 fn tick(&mut self) {
41 let d = self.timer.elapsed();
42 self.timer = Instant::now();
43 self.delta_time = d;
44 self.delta_time_seconds = d.as_secs() as f64 + f64::from(d.subsec_nanos()) * 1e-9;
45 }
46
47 fn delta_time(&self) -> Duration {
48 self.delta_time
49 }
50
51 fn delta_time_seconds(&self) -> f64 {
52 self.delta_time_seconds
53 }
54}
55
56pub struct AppLifeCycle {
57 pub running: bool,
58 pub(crate) timer: Box<dyn AppTimer>,
59 pub(crate) states_tokens: Vec<StateToken>,
60}
61
62impl AppLifeCycle {
63 pub fn new(timer: Box<dyn AppTimer>) -> Self {
64 Self {
65 running: true,
66 timer,
67 states_tokens: vec![StateToken::new()],
68 }
69 }
70
71 pub fn delta_time(&self) -> Duration {
72 self.timer.delta_time()
73 }
74
75 pub fn delta_time_seconds(&self) -> f64 {
76 self.timer.delta_time_seconds()
77 }
78
79 pub fn current_state_token(&self) -> StateToken {
80 if let Some(token) = self.states_tokens.last() {
81 *token
82 } else {
83 StateToken::new()
84 }
85 }
86}
87
88pub struct AppRunner<'a, 'b> {
89 pub app: Rc<RefCell<App<'a, 'b>>>,
90}
91
92impl<'a, 'b> AppRunner<'a, 'b> {
93 pub fn new(app: App<'a, 'b>) -> Self {
94 Self {
95 app: Rc::new(RefCell::new(app)),
96 }
97 }
98
99 pub fn run<BAR, E>(&mut self, mut backend_app_runner: BAR) -> Result<(), E>
100 where
101 BAR: BackendAppRunner<'a, 'b, E>,
102 {
103 backend_app_runner.run(self.app.clone())
104 }
105}
106
107pub trait BackendAppRunner<'a, 'b, E> {
108 fn run(&mut self, app: Rc<RefCell<App<'a, 'b>>>) -> Result<(), E>;
109}
110
111#[derive(Default)]
112pub struct SyncAppRunner {
113 pub sleep_time: Option<Duration>,
114}
115
116impl SyncAppRunner {
117 pub fn new() -> Self {
118 Self::default()
119 }
120
121 pub fn with_sleep_time(value: Duration) -> Self {
122 Self {
123 sleep_time: Some(value),
124 }
125 }
126}
127
128impl<'a, 'b> BackendAppRunner<'a, 'b, ()> for SyncAppRunner {
129 fn run(&mut self, app: Rc<RefCell<App<'a, 'b>>>) -> Result<(), ()> {
130 while app.borrow().world().read_resource::<AppLifeCycle>().running {
131 app.borrow_mut().process();
132 if let Some(sleep_time) = self.sleep_time {
133 std::thread::sleep(sleep_time);
134 }
135 }
136 Ok(())
137 }
138}
139
140pub struct App<'a, 'b> {
141 world: World,
142 states: Vec<Box<dyn State>>,
143 dispatcher: Dispatcher<'a, 'b>,
144 setup: bool,
145}
146
147impl<'a, 'b> App<'a, 'b> {
148 #[inline]
149 pub fn build() -> AppBuilder<'a, 'b> {
150 AppBuilder::default()
151 }
152
153 #[inline]
154 pub fn world(&self) -> &World {
155 &self.world
156 }
157
158 #[inline]
159 pub fn world_mut(&mut self) -> &mut World {
160 &mut self.world
161 }
162
163 #[inline]
164 pub fn process(&mut self) {
165 if self.states.is_empty() {
166 self.world.write_resource::<AppLifeCycle>().running = false;
167 return;
168 }
169 if self.setup {
170 self.states.last_mut().unwrap().on_enter(&mut self.world);
171 self.setup = false;
172 }
173 let count = self.states.len() - 1;
174 for state in self.states.iter_mut().take(count) {
175 state.on_process_background(&mut self.world);
176 }
177 let change = self.states.last_mut().unwrap().on_process(&mut self.world);
178 self.dispatcher.dispatch(&self.world.res);
179 match &change {
180 StateChange::Pop | StateChange::Swap(_) => {
181 let token = {
182 self.world
183 .read_resource::<AppLifeCycle>()
184 .current_state_token()
185 };
186 let to_delete = {
187 let entities = self.world.read_resource::<EntitiesRes>();
188 let non_persistents = self.world.read_storage::<NonPersistent>();
189 (&entities, &non_persistents)
190 .join()
191 .filter_map(
192 |(entity, pers)| if pers.0 == token { Some(entity) } else { None },
193 )
194 .collect::<Vec<_>>()
195 };
196 for entity in to_delete {
197 drop(self.world.delete_entity(entity));
198 }
199 }
200 StateChange::Quit => {
201 let to_delete = {
202 let entities = self.world.read_resource::<EntitiesRes>();
203 let non_persistents = self.world.read_storage::<NonPersistent>();
204 (&entities, &non_persistents)
205 .join()
206 .map(|(entity, _)| entity)
207 .collect::<Vec<_>>()
208 };
209 for entity in to_delete {
210 drop(self.world.delete_entity(entity));
211 }
212 }
213 _ => {}
214 }
215 self.world.maintain();
216 {
217 let mut changes = self.world.write_resource::<HierarchyChangeRes>();
218 changes.added.clear();
219 changes.removed.clear();
220 let entities = self
221 .world
222 .read_resource::<EntitiesRes>()
223 .join()
224 .collect::<HashSet<_>>();
225 let ptr = &mut changes.removed as *mut Vec<Entity>;
226 for entity in changes.entities.difference(&entities) {
227 unsafe {
228 (&mut *ptr).push(*entity);
229 }
230 }
231 let ptr = &mut changes.added as *mut Vec<Entity>;
232 for entity in entities.difference(&changes.entities) {
233 unsafe {
234 (&mut *ptr).push(*entity);
235 }
236 }
237 changes.entities = entities;
238 }
239 match change {
240 StateChange::Push(mut state) => {
241 self.states.last_mut().unwrap().on_pause(&mut self.world);
242 self.world
243 .write_resource::<AppLifeCycle>()
244 .states_tokens
245 .push(StateToken::new());
246 state.on_enter(&mut self.world);
247 self.states.push(state);
248 }
249 StateChange::Pop => {
250 self.states.pop().unwrap().on_exit(&mut self.world);
251 self.world
252 .write_resource::<AppLifeCycle>()
253 .states_tokens
254 .pop();
255 if let Some(state) = self.states.last_mut() {
256 state.on_resume(&mut self.world);
257 }
258 }
259 StateChange::Swap(mut state) => {
260 self.states.pop().unwrap().on_exit(&mut self.world);
261 {
262 let lifecycle = &mut self.world.write_resource::<AppLifeCycle>();
263 lifecycle.states_tokens.pop();
264 lifecycle.states_tokens.push(StateToken::new());
265 }
266 state.on_enter(&mut self.world);
267 self.states.push(state);
268 }
269 StateChange::Quit => {
270 while let Some(mut state) = self.states.pop() {
271 state.on_exit(&mut self.world);
272 self.world
273 .write_resource::<AppLifeCycle>()
274 .states_tokens
275 .pop();
276 }
277 }
278 _ => {}
279 }
280 {
281 let lifecycle = &mut self.world.write_resource::<AppLifeCycle>();
282 lifecycle.timer.tick();
283 }
284 }
285}
286
287pub struct AppBuilder<'a, 'b> {
288 world: World,
289 dispatcher_builder: DispatcherBuilder<'a, 'b>,
290}
291
292impl<'a, 'b> Default for AppBuilder<'a, 'b> {
293 fn default() -> Self {
294 Self::new()
295 }
296}
297
298impl<'a, 'b> AppBuilder<'a, 'b> {
299 #[inline]
300 pub fn new() -> Self {
301 let mut result = Self {
302 world: Default::default(),
303 dispatcher_builder: Default::default(),
304 };
305 result
306 .dispatcher_builder
307 .add(HierarchySystem::<Parent>::new(), "hierarchy", &[]);
308 result
309 }
310
311 #[inline]
312 pub fn world_mut(&mut self) -> &mut World {
313 &mut self.world
314 }
315
316 #[inline]
317 pub fn with_bundle<ABI, D>(mut self, mut installer: ABI, data: D) -> Self
318 where
319 ABI: FnMut(&mut AppBuilder<'a, 'b>, D),
320 {
321 installer(&mut self, data);
322 self
323 }
324
325 #[inline]
326 pub fn with_system<T>(mut self, system: T, name: &str, deps: &[&str]) -> Self
327 where
328 T: for<'c> System<'c> + Send + 'a,
329 {
330 self.dispatcher_builder.add(system, name, deps);
331 self
332 }
333
334 #[inline]
335 pub fn with_thread_local_system<T>(mut self, system: T) -> Self
336 where
337 T: for<'c> RunNow<'c> + 'b,
338 {
339 self.dispatcher_builder.add_thread_local(system);
340 self
341 }
342
343 #[inline]
344 pub fn with_barrier(mut self) -> Self {
345 self.dispatcher_builder.add_barrier();
346 self
347 }
348
349 #[inline]
350 pub fn with_resource<T>(mut self, resource: T) -> Self
351 where
352 T: Send + Sync + 'static,
353 {
354 self.world.add_resource(resource);
355 self
356 }
357
358 #[inline]
359 pub fn with_component<T: Component>(mut self) -> Self
360 where
361 T::Storage: Default,
362 {
363 self.world.register::<T>();
364 self
365 }
366
367 #[inline]
368 pub fn install_bundle<ABI, D>(&mut self, mut installer: ABI, data: D)
369 where
370 ABI: FnMut(&mut AppBuilder<'a, 'b>, D),
371 {
372 installer(self, data);
373 }
374
375 #[inline]
376 pub fn install_system<T>(&mut self, system: T, name: &str, deps: &[&str])
377 where
378 T: for<'c> System<'c> + Send + 'a,
379 {
380 self.dispatcher_builder.add(system, name, deps);
381 }
382
383 #[inline]
384 pub fn install_thread_local_system<T>(&mut self, system: T)
385 where
386 T: for<'c> RunNow<'c> + 'b,
387 {
388 self.dispatcher_builder.add_thread_local(system);
389 }
390
391 #[inline]
392 pub fn install_barrier(&mut self) {
393 self.dispatcher_builder.add_barrier();
394 }
395
396 #[inline]
397 pub fn install_resource<T>(&mut self, resource: T)
398 where
399 T: Send + Sync + 'static,
400 {
401 self.world.add_resource(resource);
402 }
403
404 #[inline]
405 pub fn install_component<T: Component>(&mut self)
406 where
407 T::Storage: Default,
408 {
409 self.world.register::<T>();
410 }
411
412 pub fn build<S, AT>(mut self, state: S, app_timer: AT) -> App<'a, 'b>
413 where
414 S: State + 'static,
415 AT: AppTimer + 'static,
416 {
417 self.world
418 .add_resource(AppLifeCycle::new(Box::new(app_timer)));
419 self.world.add_resource(HierarchyChangeRes::default());
420 self.world.register::<Parent>();
421 self.world.register::<Name>();
422 self.world.register::<Tag>();
423 self.world.register::<NonPersistent>();
424 let mut dispatcher = self.dispatcher_builder.build();
425 dispatcher.setup(&mut self.world.res);
426 App {
427 world: self.world,
428 states: vec![Box::new(state)],
429 dispatcher,
430 setup: true,
431 }
432 }
433
434 pub fn build_empty<AT>(self, app_timer: AT) -> App<'a, 'b>
435 where
436 AT: AppTimer + 'static,
437 {
438 self.build((), app_timer)
439 }
440}