hassium_core/
app.rs

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}