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}