euv_engine/scheduler/
impl.rs1use super::*;
2
3impl Default for SchedulerConfig {
5 fn default() -> SchedulerConfig {
6 SchedulerConfig::new(DEFAULT_FIXED_TIMESTEP, DEFAULT_MAX_FRAME_TIME)
7 }
8}
9
10impl Default for SchedulerState {
12 fn default() -> SchedulerState {
13 SchedulerState::new(UNINITIALIZED_TIME)
14 }
15}
16
17impl SchedulerState {
19 pub fn current_time() -> f64 {
28 let Some(window_value) = window() else {
29 return 0.0;
30 };
31 let Ok(performance) = Reflect::get(
32 window_value.as_ref(),
33 &JsValue::from_str(PERFORMANCE_OBJECT),
34 ) else {
35 return 0.0;
36 };
37 let Ok(now_value) = Reflect::get(&performance, &JsValue::from_str(PERFORMANCE_NOW_METHOD))
38 else {
39 return 0.0;
40 };
41 let Some(now_millis) = now_value.as_f64() else {
42 return 0.0;
43 };
44 now_millis / 1000.0
45 }
46
47 pub fn tick(&mut self, config: &SchedulerConfig, handler: &TickHandlerRc) {
58 let current_time: f64 = Self::current_time();
59 let frame_time: f64 = if self.get_last_time() == UNINITIALIZED_TIME {
60 config.get_fixed_timestep()
61 } else {
62 current_time - self.get_last_time()
63 };
64 self.set_last_time(current_time);
65 let clamped_frame_time: f64 = frame_time.min(config.get_max_frame_time());
66 *self.get_mut_accumulator() += clamped_frame_time;
67 while self.get_accumulator() >= config.get_fixed_timestep() {
68 handler.get_mut().on_update(config.get_fixed_timestep());
69 *self.get_mut_accumulator() -= config.get_fixed_timestep();
70 *self.get_mut_update_count() += 1;
71 }
72 let interpolation: f64 = self.get_accumulator() / config.get_fixed_timestep();
73 handler.get_mut().on_render(interpolation);
74 *self.get_mut_frame_count() += 1;
75 }
76}
77
78impl SchedulerHandle {
80 pub fn stop(&self) {
82 let state: &mut SchedulerState = self.get_state().get_mut();
83 state.set_running(false);
84 if let Some(id) = state.get_mut_raf_id().take() {
85 let Some(window_value) = window() else {
86 let _ = self.get_closure_cell().try_take();
88 return;
89 };
90 let _: Result<(), JsValue> = window_value.cancel_animation_frame(id);
91 }
92 let _ = self.get_closure_cell().try_take();
94 }
95
96 pub fn is_running(&self) -> bool {
102 self.get_state().get().get_running()
105 }
106
107 pub fn update_count(&self) -> u64 {
113 self.get_state().get().get_update_count()
114 }
115
116 pub fn frame_count(&self) -> u64 {
122 self.get_state().get().get_frame_count()
123 }
124
125 pub fn start(config: SchedulerConfig, handler: TickHandlerRc) -> SchedulerHandle {
142 let state: Rc<EngineCell<SchedulerState>> =
143 Rc::new(EngineCell::new(SchedulerState::new(UNINITIALIZED_TIME)));
144 let closure_cell: RafClosureCell = Rc::new(MaybeEngineCell::new());
145 let state_ref_init: &mut SchedulerState = state.get_mut();
147 state_ref_init.set_running(true);
148 let state_clone: Rc<EngineCell<SchedulerState>> = state.clone();
149 let closure_cell_clone: RafClosureCell = closure_cell.clone();
150 let handler_clone: TickHandlerRc = handler.clone();
151 let raf_closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
152 {
153 let state_ref: &mut SchedulerState = state_clone.get_mut();
154 if !state_ref.get_running() {
155 return;
156 }
157 state_ref.tick(&config, &handler_clone);
158 }
159 let state_ro: &SchedulerState = state_clone.get();
160 if state_ro.get_running() {
161 let Some(window_value) = window() else {
162 return;
163 };
164 let cell: RafClosureCell = closure_cell_clone.clone();
165 let Some(raf_closure) = cell.try_get() else {
166 return;
167 };
168 let id: i32 = window_value
169 .request_animation_frame(raf_closure.as_ref().unchecked_ref())
170 .unwrap_or(0);
171 let state_ref_id: &mut SchedulerState = state_clone.get_mut();
172 state_ref_id.set_raf_id(Some(id));
173 }
174 }));
175 let Some(window_value) = window() else {
176 let state_ref_stop: &mut SchedulerState = state.get_mut();
179 state_ref_stop.set_running(false);
180 let _ = closure_cell.try_set(raf_closure);
181 return SchedulerHandle::new(state, closure_cell);
182 };
183 let id: i32 = window_value
184 .request_animation_frame(raf_closure.as_ref().unchecked_ref())
185 .unwrap_or(0);
186 let state_ref_id: &mut SchedulerState = state.get_mut();
187 state_ref_id.set_raf_id(Some(id));
188 let _ = closure_cell.try_set(raf_closure);
189 SchedulerHandle::new(state, closure_cell)
190 }
191}