Skip to main content

euv_engine/scheduler/
struct.rs

1use super::*;
2
3/// Configuration parameters for the fixed-timestep scheduler.
4#[derive(Clone, Copy, Data, Debug, New, PartialEq, PartialOrd)]
5pub struct SchedulerConfig {
6    /// The fixed simulation timestep in seconds (e.g., 1/60 for 60 Hz updates).
7    ///
8    /// `get_fixed_timestep` is public because tests/api_visibility/fn.rs, tests/config/fn.rs, tests/scheduler/fn.rs reads this field from
9    /// outside this crate. `get_mut` / `set` stay crate-internal.
10    #[get_mut(pub(crate))]
11    #[get(type(copy))]
12    #[set(pub(crate))]
13    pub fixed_timestep: f64,
14    /// The maximum allowed frame time in seconds before the scheduler starts dropping updates.
15    ///
16    /// `get_max_frame_time` is public because tests/api_visibility/fn.rs, tests/config/fn.rs reads this field from
17    /// outside this crate. `get_mut` / `set` stay crate-internal.
18    #[get_mut(pub(crate))]
19    #[get(type(copy))]
20    #[set(pub(crate))]
21    pub max_frame_time: f64,
22}
23
24/// The runtime state of a scheduler instance.
25#[derive(Clone, Data, Debug, New, PartialEq)]
26pub struct SchedulerState {
27    /// The accumulated time waiting to be processed by fixed updates.
28    ///
29    /// `get_accumulator` is public because tests/api_visibility/fn.rs, tests/config/fn.rs reads this field from
30    /// outside this crate. `get_mut` / `set` stay crate-internal.
31    #[get_mut(pub(crate))]
32    #[get(type(copy))]
33    #[set(pub(crate))]
34    #[new(skip)]
35    pub accumulator: f64,
36    /// The timestamp of the previous frame in seconds, or `UNINITIALIZED_TIME` before the first frame.
37    ///
38    /// `get_last_time` is public because tests/api_visibility/fn.rs reads this field from
39    /// outside this crate. `get_mut` / `set` stay crate-internal.
40    #[get_mut(pub(crate))]
41    #[get(type(copy))]
42    #[set(pub(crate))]
43    pub last_time: f64,
44    /// Whether the scheduler is currently running and scheduling animation frames.
45    ///
46    /// `get_running` is public because tests/api_visibility/fn.rs, tests/config/fn.rs reads this field from
47    /// outside this crate. `get_mut` / `set` stay crate-internal.
48    #[get_mut(pub(crate))]
49    #[get(type(copy))]
50    #[set(pub(crate))]
51    #[new(skip)]
52    pub running: bool,
53    /// The most recent `requestAnimationFrame` ID, used to cancel the next frame.
54    ///
55    /// `get_raf_id` is public because tests/api_visibility/fn.rs, tests/config/fn.rs reads this field from
56    /// outside this crate. `get_mut` / `set` stay crate-internal.
57    #[get_mut(pub(crate))]
58    #[get(type(copy))]
59    #[set(pub(crate))]
60    #[new(skip)]
61    pub raf_id: Option<i32>,
62    /// The total number of fixed update steps executed since the scheduler started.
63    ///
64    /// `get_update_count` is public because tests/api_visibility/fn.rs, tests/config/fn.rs, tests/input/fn.rs, tests/scheduler/fn.rs reads this field from
65    /// outside this crate. `get_mut` / `set` stay crate-internal.
66    #[get_mut(pub(crate))]
67    #[get(type(copy))]
68    #[set(pub(crate))]
69    #[new(skip)]
70    pub update_count: u64,
71    /// The total number of render frames executed since the scheduler started.
72    ///
73    /// `get_frame_count` is public because tests/api_visibility/fn.rs, tests/config/fn.rs, tests/input/fn.rs, tests/scheduler/fn.rs reads this field from
74    /// outside this crate. `get_mut` / `set` stay crate-internal.
75    #[get_mut(pub(crate))]
76    #[get(type(copy))]
77    #[set(pub(crate))]
78    #[new(skip)]
79    pub frame_count: u64,
80}
81
82/// A handle to a running scheduler, allowing the caller to stop it later.
83#[derive(Clone, Data, New)]
84pub struct SchedulerHandle {
85    /// The shared scheduler state, held behind `EngineCell` (an
86    /// `UnsafeCell`-backed `Sync` newtype) so multiple closure
87    /// captures can mutate it without `RefCell`'s runtime borrow
88    /// check. Mirrors `core::reactive::schedule` shape.
89    ///
90    /// `get_state` is public because tests/api_visibility/fn.rs reads this field from
91    /// outside this crate. `get_mut` / `set` stay crate-internal.
92    #[get_mut(pub(crate))]
93    #[set(pub(crate))]
94    pub state: Rc<EngineCell<SchedulerState>>,
95    /// The shared closure cell keeping the RAF callback alive. Held
96    /// behind `MaybeEngineCell` because the cell is empty both
97    /// before `spawn` runs and after cleanup tears the closure down.
98    ///
99    /// `get_closure_cell` is public because tests/api_visibility/fn.rs reads this field from
100    /// outside this crate. `get_mut` / `set` stay crate-internal.
101    #[get_mut(pub(crate))]
102    #[set(pub(crate))]
103    pub closure_cell: RafClosureCell,
104}
105
106/// A registry of [`Updatable`] tasks driven by the fixed-timestep scheduler.
107///
108/// The scheduler itself only knows how to run a single [`TickHandler`]; every
109/// other simulation object in the engine — `Timer`, `Tween`,
110/// `ParticleEmitter`, `Entity`, `Animator`, `SceneManager`, and the
111/// `PhysicsWorld2D` / `PhysicsWorld3D` containers — exposes its advancement
112/// through the [`Updatable`] trait instead. This registry is the driver that
113/// gives those objects a heartbeat: [`SchedulerState::tick`] calls
114/// [`TaskRegistry::update_all`] once per fixed step, immediately *after* the
115/// handler's `on_update` callback returns, so gameplay logic registered in
116/// `on_update` sees task state that has already advanced this step.
117///
118/// Tasks are updated in registration order, which makes the relative ordering
119/// of independent tasks explicit and reproducible rather than dependent on
120/// container iteration order.
121#[derive(Data, Default, New)]
122pub struct TaskRegistry {
123    /// The registered tasks, in registration order. `Box<dyn Updatable>`
124    /// erases the concrete task type so heterogeneous tasks (a `Timer` next
125    /// to a `Tween<f64>` next to a `ParticleEmitter`) coexist in one list.
126    #[get_mut(pub(crate))]
127    #[get(pub(crate))]
128    #[set(pub(crate))]
129    pub(crate) tasks: Vec<Box<dyn Updatable>>,
130}
131
132/// A handle to a task registered with a [`TaskRegistry`].
133///
134/// The handle is returned by [`TaskRegistry::register`] and is the only way
135/// to remove that task later. It identifies the task by its index in the
136/// registry's insertion-ordered task list, which keeps registration and
137/// removal O(1) for the common append-then-remove-last pattern.
138#[derive(Clone, Copy, Data, Debug, New, PartialEq, PartialOrd)]
139pub struct TaskHandle {
140    /// The zero-based index of the task in the registry's task list.
141    #[get(pub(crate), type(copy))]
142    #[get_mut(pub(crate))]
143    #[set(pub(crate))]
144    pub(crate) id: u64,
145}