Expand description
Interior clips — the main-world half of clip-independent layer capture.
A promoted layer’s capture must not bake ancestor clipping (scroll
containers / viewport) into its cached pixels: the cache treats scroll as
pure translation (see super::fold_member_geometry), so pixels captured
under an ancestor clip would be stale the moment the layer scrolls. Web
semantics agree: filter applies to the element’s full painted content,
and ancestor overflow clips the result at composite time.
sync_layer_clips therefore re-runs bevy_ui‘s clip cascade
(update_clipping semantics: a node’s inherited clip is its ancestors’
overflow intersection; its own overflow only clips its children) —
but restarted at each layer root with no inherited clip. The result
is two per-frame maps in LayerClips:
interior: per subtree member, the clip its extracted items should use inside the capture — clips originating inside the subtree still apply (they move with the layer, so cached pixels stay valid); everything above the root is stripped. Consumed by the render world’s extract-window swap (layer::render::clip), which substitutes these into the members’CalculatedClipfor exactly the duration ofExtractSchedule— the main world is exclusively borrowed there, so no main-world system (picking, focus) can ever observe the swap, and every stock extractor (backgrounds, text, gradients, box shadows, texture slices) picks the interior clips up uniformly. Text self-clips (TextScrollcontent boxes) recompose automatically in the stock text extractors from the swapped value.quads: per layer root, the screen-space rect its composite quad clamps to instead — a top-level root’s inheritedCalculatedClip, or, for a nested root, the enclosing layer’s interior cascade value at the root (its quad draws inside the enclosing capture).
Outside the extract window the real CalculatedClip values are always in
place: picking (crate::pick_clip) and bevy_ui’s own consumers keep
seeing true inherited clips.
Known divergence (deliberate, rare): an OverrideClip escapee inside a
subtree is still clamped by the layer’s quad clip at composite time
(stock lets it escape every ancestor clip).
Offscreen layers still capture (when dirty) like any other — a fully clipped-away quad simply draws nothing. The cost is invisible re-captures for continuously-animated offscreen layers; the win is that scrolling never re-captures and a layer scrolled into view is correct by construction (the bug this module fixes: captures taken under clipping were cached and served stale after scrolling).
Structs§
- Layer
Clips - Per-frame clip maps for promoted layers, rebuilt from scratch by
sync_layer_clips(likeLayerMembership— nothing persists).
Functions§
- sync_
layer_ clips - Rebuilds
LayerClipsfor this frame. Runs inPostUpdateaftersuper::sync_layer_geometry(freshLayerMembership) and afterbevy_ui’sUiSystems::PostLayout(finalCalculatedClipvalues for the top-level quad clips). Must NOT feedsuper::resolve_layer_repaints: clip changes never dirty a capture — that is the point.