Move LazySpan rows through one retained offset
This commit is contained in:
1 parent
992482414f
commit
f95835593f
8 files changed
+453
-50
No files matched your search
+49
-4
@@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
Axis, Color, Len, RegionAlign, RenderedText, Size, StrongWidget, TextAttrs, TextBuffer,
|
||||
TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2, WidgetId,
|
||||
Axis, Color, Len, MoveOffset, RegionAlign, RenderedText, Size, StrongWidget, TextAttrs,
|
||||
TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2,
|
||||
WidgetId,
|
||||
render::{
|
||||
Drawn, GlyphPrimitive, IMAGE_BINDING, Mask, MaskIdx, MoveIdx, NOT_DRAWN, Primitive,
|
||||
PrimitiveHandle, PrimitiveInst, RectPrimitive,
|
||||
@@ -16,6 +17,7 @@ pub struct Painter<'a> {
|
||||
pub(super) region: UiRegion,
|
||||
pub(super) mask: MaskIdx,
|
||||
pub(super) move_slot: MoveIdx,
|
||||
pub(super) child_move_slot: Option<MoveIdx>,
|
||||
/// This widget's retained mask slot.
|
||||
pub(super) own_mask: MaskIdx,
|
||||
pub(super) textures: Vec<TextureHandle>,
|
||||
@@ -217,6 +219,47 @@ impl<'a> Painter<'a> {
|
||||
self.widget_at(id, region.within(&self.region))
|
||||
}
|
||||
|
||||
/// Translate this widget's children as one retained subtree, in output
|
||||
/// pixels. The first call must happen before drawing a child, because the
|
||||
/// slot becomes the parent of every direct child's ordinary move slot.
|
||||
/// Once retained, it may be updated later in a redraw (for example after
|
||||
/// measuring a changed child). All deeper descendants inherit it and the
|
||||
/// CPU hit-test walk resolves the same translation as the shader.
|
||||
///
|
||||
/// This offsets the child coordinate space, not this widget: its own
|
||||
/// primitives and hit region remain fixed. Once allocated, the boundary
|
||||
/// stays in the chain across redraws; set it to zero to return children to
|
||||
/// their unshifted positions.
|
||||
pub fn set_child_offset(&mut self, offset: Vec2) {
|
||||
let slot = match self.child_move_slot {
|
||||
Some(slot) => slot,
|
||||
None => {
|
||||
assert!(
|
||||
self.children.is_empty(),
|
||||
"a child offset must be created before drawing a child"
|
||||
);
|
||||
let parent = self.move_slot.idx() as u32;
|
||||
let slot = self
|
||||
.rsc
|
||||
.ui_mut()
|
||||
.move_offsets
|
||||
.push(MoveOffset::new([offset.x, offset.y], parent));
|
||||
// One ref for this widget's ownership and one on the
|
||||
// up-link. Direct children take their own refs when their
|
||||
// move slots are allocated.
|
||||
self.rsc.ui_mut().move_offsets.push_ref(slot);
|
||||
self.rsc.ui_mut().move_offsets.push_ref(self.move_slot);
|
||||
self.child_move_slot = Some(slot);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let next = [offset.x, offset.y];
|
||||
if self.rsc.ui().move_offsets[slot.idx()].delta != next {
|
||||
self.rsc.ui_mut().move_offsets.get_mut(slot).delta = next;
|
||||
self.state.note_move();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn known_len<W: ?Sized>(&self, id: &StrongWidget<W>, axis: Axis) -> Option<Len> {
|
||||
if let Some(len) = self.rsc.widgets().get_dyn(id.id())?.size_hint(axis) {
|
||||
return Some(len.fold_dp(self.density()));
|
||||
@@ -236,12 +279,13 @@ impl<'a> Painter<'a> {
|
||||
// call -- would always find nothing. `self.move_slot` is this
|
||||
// widget's own slot, already known, and always correct regardless
|
||||
// of insertion order. See `UiRenderState::move_parent_of`.
|
||||
let parent_move_slot = self.child_move_slot.unwrap_or(self.move_slot);
|
||||
self.state.draw_inner(
|
||||
self.layer,
|
||||
id.id(),
|
||||
region,
|
||||
Some(self.id),
|
||||
self.move_slot.idx() as u32,
|
||||
parent_move_slot.idx() as u32,
|
||||
self.mask,
|
||||
Retained::default(),
|
||||
self.rsc,
|
||||
@@ -261,12 +305,13 @@ impl<'a> Painter<'a> {
|
||||
} else if let Some((layer, mask)) = retained {
|
||||
self.children.push(id.id());
|
||||
self.rsc.widgets_mut().needs_redraw.insert(id.id());
|
||||
let parent_move_slot = self.child_move_slot.unwrap_or(self.move_slot);
|
||||
self.state.draw_inner(
|
||||
layer,
|
||||
id.id(),
|
||||
region,
|
||||
Some(self.id),
|
||||
self.move_slot.idx() as u32,
|
||||
parent_move_slot.idx() as u32,
|
||||
mask,
|
||||
Retained::default(),
|
||||
self.rsc,
|
||||
|
||||
Reference in new issue
Block a user