Found by dogfooding the promo video (examples/rustmotion-promo.json, scene 4): a shape in normal flex flow with a motion_blur effect renders its temporal ghosts as flow siblings — each ghost BoxNode takes its own layout slot in the column (vertical stack of faded pills) instead of overlapping the principal.
Root cause: #61's build_child returns ghosts as additional BoxNodes that the parent flex container lays out. The pixel tests only used absolutely-positioned children (render_new_at places components with PositionMode::Absolute), where ghost css clones inherit the absolute position and overlap correctly — flow layout was never exercised.
Fix direction: ghosts must not occupy layout slots. Cleanest: exclude ghost nodes from the taffy tree entirely and paint them using the principal's BoxLayout (e.g. BoxNode.layout_ref: Option<NodeId> consulted by paint_pass, or reuse the principal's id for layout lookup while keeping the ghost's own slot id for dispatch/time_params).
Red test first: a rect with motion_blur in a flex column between two siblings — siblings' positions must be identical with and without the effect, and ghost pixels must overlap the principal's row, not stack below it.
Workaround applied in the promo example meanwhile: the moving shape is absolutely positioned.
Found by dogfooding the promo video (examples/rustmotion-promo.json, scene 4): a shape in normal flex flow with a
motion_blureffect renders its temporal ghosts as flow siblings — each ghost BoxNode takes its own layout slot in the column (vertical stack of faded pills) instead of overlapping the principal.Root cause: #61's
build_childreturns ghosts as additional BoxNodes that the parent flex container lays out. The pixel tests only used absolutely-positioned children (render_new_atplaces components withPositionMode::Absolute), where ghost css clones inherit the absolute position and overlap correctly — flow layout was never exercised.Fix direction: ghosts must not occupy layout slots. Cleanest: exclude ghost nodes from the taffy tree entirely and paint them using the principal's BoxLayout (e.g.
BoxNode.layout_ref: Option<NodeId>consulted by paint_pass, or reuse the principal's id for layout lookup while keeping the ghost's own slot id for dispatch/time_params).Red test first: a rect with
motion_blurin a flex column between two siblings — siblings' positions must be identical with and without the effect, and ghost pixels must overlap the principal's row, not stack below it.Workaround applied in the promo example meanwhile: the moving shape is absolutely positioned.