simvx.core.scene_step¶
The single canonical per-frame logic-phase sequence, shared by every embedder.
Consumers that drive a :class:~simvx.core.scene_tree.SceneTree one frame at a time
(the windowed/headless/streaming :class:FrameLoop and the editor’s PlayMode today;
the AI rendered session and future embedders next) re-spell the same load-bearing
order: step physics, dispatch queued UI events, run logic. The order is pure
SceneTree logic (physics_tick / interpolate_physics / tick are core
methods with zero Vulkan), so it lives in core where every embedder, including the
ones that cannot import graphics, can share one definition. (The web runtime and
SceneRunner own deliberately different policies and are not routed through here yet:
see their notes.)
- func:
step_scene_logicruns exactly that sequence and stops BEFORE the GPU half (Draw2D reset +tree.render+ submit/present) and BEFORE the windowed Input frame boundary (Input._end_frame/Input._new_frame): those are the caller’s job, because they diverge per embedder (swapchain present vs offscreen render-to-target vs nothing). This module imports nothing from graphics.
Per-phase variation is expressed through :class:ScenePhases: a frozen set of
optional hooks. phases=None runs the engine-default behaviour (one fixed
physics step + interpolate to the step boundary, then one logic tick). A caller
that owns a different physics-stepping policy (the windowed accumulator clock) or
a different per-node walk (the editor’s error-tolerant / profiled walkers) supplies
node_walk; a caller with a queued UI-event drain or a between-physics-and-logic
window-sync supplies ui_events; a profiler supplies on_phase.
Module Contents¶
Classes¶
Optional per-phase hooks for :func: |
Functions¶
Run one frame of the canonical logic-phase sequence on |
Data¶
API¶
- simvx.core.scene_step.__all__¶
[‘ScenePhases’, ‘step_scene_logic’]
- class simvx.core.scene_step.ScenePhases[source]¶
Optional per-phase hooks for :func:
step_scene_logic.Every field defaults to
None, which selects the engine-default behaviour for that phase. Supply a hook only to override one phase; the canonical order (physics, then UI events, then logic) is fixed and not overridable.Attributes: node_walk:
(root, dt, phase)wherephaseis"physics"or"process". When supplied it replaces the default physics step and/or the default logic tick: the caller owns how the tree is walked for that phase (its own physics-stepping policy, an error-tolerant or profiled per-node walk, etc.).rootis the scene root, orNonewhen the tree has no root. ui_events: called once, after physics and before logic, to drain queued UI / input events into the tree. This is the same slot the windowed loop uses for gamepad + window-size sync and the editor uses to flush its viewport UI-event queue. on_phase:(name, edge)withedgein{"begin", "end"}, fired around each of"physics","ui","process"so a profiler can bracket per-phase timings.- node_walk: collections.abc.Callable[[simvx.core.node.Node | None, float, str], None] | None¶
None
- ui_events: collections.abc.Callable[[], None] | None¶
None
- on_phase: collections.abc.Callable[[str, str], None] | None¶
None
- simvx.core.scene_step.step_scene_logic(tree: simvx.core.scene_tree.SceneTree, dt: float, *, time_scale: float = 1.0, phases: simvx.core.scene_step.ScenePhases | None = None) None[source]¶
Run one frame of the canonical logic-phase sequence on
tree.Order (load-bearing):
physics –
tree.physics_tick(dt * time_scale)thentree.interpolate_physics(1.0), ORphases.node_walk(root, dt, "physics").ui –
phases.ui_events()if supplied (no engine default).process –
tree.tick(dt * time_scale), ORphases.node_walk(root, dt, "process").
Stops before Draw2D / submit / present and before the Input frame boundary: those stay with the caller. Imports nothing from graphics.
With
phases=Nonethis is byte-identical to a hand-rolledtree.physics_tick(dt * time_scale); tree.interpolate_physics(1.0); tree.tick(dt * time_scale).Args: tree: the scene tree to advance. dt: frame delta in seconds (unscaled). time_scale: multiplier applied to
dtfor the default physics and logic steps (slow-mo / fast-forward). Whennode_walkis supplied the caller owns scaling, sodtis passed through unscaled. phases: optional per-phase overrides;Noneselects engine defaults.