mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
WIP
This commit is contained in:
parent
2a7c8dea42
commit
a70272c3f0
@ -2072,6 +2072,17 @@ impl RenderState {
|
||||
|
||||
self.drag_layers.viewport_rect = viewport_rect;
|
||||
|
||||
// Sort layers by global render order so the compositing loop paints
|
||||
// the one visually behind first and the one in front last. Without
|
||||
// this, a drag over several selected shapes would swap their
|
||||
// stacking whenever the frontend sent `ids` in a different order.
|
||||
if self.drag_layers.layers.len() > 1 {
|
||||
let order = tree.render_order_indices(&selected_set);
|
||||
self.drag_layers
|
||||
.layers
|
||||
.sort_by_key(|layer| order.get(&layer.shape_id).copied().unwrap_or(usize::MAX));
|
||||
}
|
||||
|
||||
// Restore the workspace render state exactly like `render_shape_pixels`
|
||||
// does. Without this the next workspace render could observe stale
|
||||
// render_area / focus / pending_nodes left over from our snapshots.
|
||||
|
||||
@ -267,6 +267,57 @@ impl ShapesPoolImpl {
|
||||
above
|
||||
}
|
||||
|
||||
/// Walk the tree in render order (DFS pre-order, paint-order among
|
||||
/// siblings: first child = behind, last child = in front) and assign a
|
||||
/// monotonically increasing index to every uuid in `targets`. The map
|
||||
/// returned only contains entries for shapes that actually appear in
|
||||
/// the traversal; unknown or detached ids are skipped.
|
||||
///
|
||||
/// Used by the drag-layer pipeline to blit the per-shape snapshots in
|
||||
/// the same stacking order the workspace would have used, regardless
|
||||
/// of the order in which the frontend sent the selection ids.
|
||||
pub fn render_order_indices(&self, targets: &HashSet<Uuid>) -> HashMap<Uuid, usize> {
|
||||
let mut order = HashMap::with_capacity(targets.len());
|
||||
if targets.is_empty() {
|
||||
return order;
|
||||
}
|
||||
|
||||
let Some(root) = self.get(&Uuid::nil()) else {
|
||||
return order;
|
||||
};
|
||||
|
||||
// DFS with an explicit stack. Push children in reverse so the
|
||||
// iteration pops them in paint order (behind first).
|
||||
// `children_ids_iter_forward` returns a boxed trait object, which
|
||||
// is not `DoubleEndedIterator`, so we collect first and reverse
|
||||
// over the owned `Vec`.
|
||||
let mut stack: Vec<Uuid> = {
|
||||
let children: Vec<Uuid> = root.children_ids_iter_forward(true).copied().collect();
|
||||
children.into_iter().rev().collect()
|
||||
};
|
||||
let mut counter: usize = 0;
|
||||
|
||||
while let Some(id) = stack.pop() {
|
||||
if targets.contains(&id) {
|
||||
order.insert(id, counter);
|
||||
if order.len() == targets.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
counter += 1;
|
||||
|
||||
if let Some(shape) = self.get(&id) {
|
||||
let children: Vec<Uuid> =
|
||||
shape.children_ids_iter_forward(true).copied().collect();
|
||||
for child in children.into_iter().rev() {
|
||||
stack.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
order
|
||||
}
|
||||
|
||||
/// Returns the raw modifier matrix currently applied to `id`, if any.
|
||||
///
|
||||
/// The `get` method above already returns a shape with modifiers baked in,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user