Skip to main content

viewport_lib/runtime/
context.rs

1//! Per-frame and per-step context types for runtime plugins.
2
3use crate::camera::camera::Camera;
4use crate::interaction::input::ActionFrame;
5use crate::scene::scene::Scene;
6
7use super::output::{RuntimeOutput, TransformWriteback};
8use super::resources::RuntimeResources;
9
10/// Per-frame inputs to [`super::ViewportRuntime::step`].
11#[derive(Default)]
12#[non_exhaustive]
13pub struct RuntimeFrameContext {
14    /// Wall-clock delta time in seconds since the last frame.
15    pub dt: f32,
16    /// Current camera state.
17    pub camera: Camera,
18    /// Viewport dimensions in logical pixels.
19    pub viewport_size: glam::Vec2,
20    /// Resolved input actions for this frame.
21    pub input: ActionFrame,
22    /// Pick result under the cursor for this frame. Supply from CPU or GPU picking.
23    /// None if no picking was done or nothing was hit.
24    pub pick_hit: Option<crate::interaction::picking::PickHit>,
25    /// True on the frame the primary pointer button was clicked (pressed and released without drag).
26    pub clicked: bool,
27    /// True on the frame a primary drag began.
28    pub drag_started: bool,
29    /// True while a primary drag is ongoing.
30    pub dragging: bool,
31    /// Pointer movement in viewport pixels since last frame.
32    pub pointer_delta: glam::Vec2,
33    /// Cursor position in viewport-local pixels. None when outside the viewport.
34    pub cursor_viewport: Option<glam::Vec2>,
35    /// True when the shift modifier is held (for shift-click multi-select).
36    pub shift_held: bool,
37}
38
39/// Context passed to each plugin during its execution step.
40///
41/// Provides read-only scene access and write access to the transform writeback
42/// buffer, output accumulator, and shared resource registry. To write transforms,
43/// call [`TransformWriteback::set`] on `self.writeback`. To share state between
44/// plugins, use `self.resources`.
45pub struct RuntimeStepContext<'a> {
46    /// The numeric priority of the plugin executing in this context.
47    pub priority: i32,
48    /// Delta time for this step. For plugins in the simulate range with a fixed
49    /// timestep this is the fixed step size, not the wall dt.
50    pub dt: f32,
51    /// Read-only scene access. To write transforms, use `writeback`.
52    pub scene: &'a Scene,
53    /// Accumulate transform writes here. The runtime flushes them to the scene
54    /// after the writeback phase.
55    pub writeback: &'a mut TransformWriteback,
56    /// Accumulate selection changes and contact events here.
57    pub output: &'a mut RuntimeOutput,
58    /// Forwarded from RuntimeFrameContext for plugins that need the current pick result.
59    pub pick_hit: Option<crate::interaction::picking::PickHit>,
60    /// Shared typed resource registry. Plugins use this to coordinate through
61    /// engine-owned state without custom wiring in the application.
62    ///
63    /// In `submit` (called with `&RuntimeStepContext`), only `get` and `contains`
64    /// are accessible through the shared reference. In `step`, `collect`, and
65    /// `on_event` (called with `&mut RuntimeStepContext`), full insert/get_mut/remove
66    /// access is available.
67    pub resources: &'a mut RuntimeResources,
68}
69
70impl<'a> RuntimeStepContext<'a> {
71    /// Construct a [`SimulationStepContext`] from this context.
72    ///
73    /// Pass the step count from [`super::ViewportRuntime::step_index`] so the
74    /// simulation context reflects the current runtime step. The runtime does not
75    /// thread the step index into `RuntimeStepContext` automatically -- you must
76    /// supply it.
77    ///
78    /// ```rust,ignore
79    /// fn step(&mut self, ctx: &mut RuntimeStepContext) {
80    ///     let sim = ctx.as_simulation(runtime.step_index());
81    ///     // use sim.step_index for deterministic seeding or replay
82    /// }
83    /// ```
84    ///
85    /// Note: within a fixed-timestep frame that runs N simulate steps,
86    /// `runtime.step_index()` returns the count at the start of that frame.
87    /// If you need a per-sub-step index (0..N) within a single frame, maintain
88    /// a local counter in your plugin.
89    ///
90    /// Passing an incorrect value does not cause undefined behavior, but
91    /// physics code that uses `step_index` for deterministic seeding or replay
92    /// will produce wrong results.
93    pub fn as_simulation(&mut self, step_index: u64) -> SimulationStepContext<'_> {
94        SimulationStepContext {
95            dt: self.dt,
96            step_index,
97            scene: self.scene,
98            writeback: self.writeback,
99        }
100    }
101}
102
103/// Narrower context for simulation plugins that need a per-step index.
104///
105/// Constructed via [`RuntimeStepContext::as_simulation`] inside a simulate-range
106/// plugin to get the current simulation step count alongside scene and writeback access.
107pub struct SimulationStepContext<'a> {
108    /// Fixed step size in seconds.
109    pub dt: f32,
110    /// Monotonically increasing step counter (wraps on overflow).
111    pub step_index: u64,
112    /// Read-only scene access.
113    pub scene: &'a Scene,
114    /// Write transforms to this buffer.
115    pub writeback: &'a mut TransformWriteback,
116}