Skip to main content

fui/
frame_signal.rs

1use crate::signal::{Callback, Signal, SubscriptionGuard};
2use std::cell::RefCell;
3use std::rc::Rc;
4
5#[derive(Clone, Copy)]
6pub struct FrameTimeSignalHandle;
7
8thread_local! {
9    static FRAME_TIME_SIGNAL: RefCell<Signal<f64>> = RefCell::new(Signal::new(0.0));
10}
11
12impl FrameTimeSignalHandle {
13    pub fn value(&self) -> f64 {
14        FRAME_TIME_SIGNAL.with(|slot| slot.borrow().get())
15    }
16
17    pub fn subscribe(&self, handler: impl Fn(f64) + 'static) -> SubscriptionGuard {
18        handler(self.value());
19        FRAME_TIME_SIGNAL.with(|slot| {
20            let callback: Callback = Rc::new(move || handler(frame_time_signal().value()));
21            slot.borrow_mut().subscribe(callback)
22        })
23    }
24}
25
26pub fn frame_time_signal() -> FrameTimeSignalHandle {
27    FrameTimeSignalHandle
28}
29
30pub(crate) fn set_frame_time(timestamp_ms: f64) {
31    FRAME_TIME_SIGNAL.with(|slot| {
32        let callbacks = slot.borrow_mut().set(timestamp_ms);
33        if let Some(callbacks) = callbacks {
34            for callback in callbacks {
35                callback();
36            }
37        }
38    });
39}
40
41#[cfg(test)]
42mod tests {
43    use super::{frame_time_signal, set_frame_time};
44    use std::cell::Cell;
45    use std::rc::Rc;
46
47    #[test]
48    fn updates_frame_time_signal_and_notifies_subscribers() {
49        let count = Rc::new(Cell::new(0));
50        let seen = Rc::new(Cell::new(0.0));
51        let count_for_handler = count.clone();
52        let seen_for_handler = seen.clone();
53        let _guard = frame_time_signal().subscribe(move |value| {
54            count_for_handler.set(count_for_handler.get() + 1);
55            seen_for_handler.set(value);
56        });
57
58        set_frame_time(1234.5);
59
60        assert_eq!(frame_time_signal().value(), 1234.5);
61        assert_eq!(seen.get(), 1234.5);
62        assert!(count.get() >= 2);
63    }
64}