🐛 Fix problem when moving masks, bools, groups with wasm

This commit is contained in:
alonso.torres 2025-06-18 14:51:46 +02:00
parent 58e5748b4f
commit 5b4cd9f4f1
8 changed files with 86 additions and 59 deletions

View File

@ -39,6 +39,43 @@
(def ^:private xf:without-uuid-zero (def ^:private xf:without-uuid-zero
(remove #(= % uuid/zero))) (remove #(= % uuid/zero)))
(def ^:private transform-attrs
#{:selrect
:points
:x
:y
:r1
:r2
:r3
:r4
:shadow
:blur
:strokes
:width
:height
:content
:transform
:transform-inverse
:rotation
:flip-x
:flip-y
:grow-type
:position-data
:layout-gap
:layout-padding
:layout-item-h-sizing
:layout-item-max-h
:layout-item-max-w
:layout-item-min-h
:layout-item-min-w
:layout-item-v-sizing
:layout-padding-type
:layout-item-margin
:layout-item-margin-type
:layout-grid-cells
:layout-grid-columns
:layout-grid-rows})
;; -- temporary modifiers ------------------------------------------- ;; -- temporary modifiers -------------------------------------------
;; During an interactive transformation of shapes (e.g. when resizing or rotating ;; During an interactive transformation of shapes (e.g. when resizing or rotating
@ -598,6 +635,18 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (dsh/lookup-page-objects state) (let [objects (dsh/lookup-page-objects state)
ignore-tree
(calculate-ignore-tree modif-tree objects)
options
(-> params
(assoc :reg-objects? true)
(assoc :ignore-tree ignore-tree)
;; Attributes that can change in the transform. This
;; way we don't have to check all the attributes
(assoc :attrs transform-attrs))
geometry-entries (parse-geometry-modifiers modif-tree) geometry-entries (parse-geometry-modifiers modif-tree)
snap-pixel? snap-pixel?
@ -627,7 +676,7 @@
(clear-local-transform) (clear-local-transform)
(ptk/event ::dwg/move-frame-guides {:ids ids :transforms transforms}) (ptk/event ::dwg/move-frame-guides {:ids ids :transforms transforms})
(ptk/event ::dwcm/move-frame-comment-threads transforms) (ptk/event ::dwcm/move-frame-comment-threads transforms)
(dwsh/update-shapes ids update-shape)))))) (dwsh/update-shapes ids update-shape options))))))
(def ^:private (def ^:private
xf-rotation-shape xf-rotation-shape
@ -714,43 +763,6 @@
(assoc state :workspace-modifiers modif-tree))))) (assoc state :workspace-modifiers modif-tree)))))
(def ^:private transform-attrs
#{:selrect
:points
:x
:y
:r1
:r2
:r3
:r4
:shadow
:blur
:strokes
:width
:height
:content
:transform
:transform-inverse
:rotation
:flip-x
:flip-y
:grow-type
:position-data
:layout-gap
:layout-padding
:layout-item-h-sizing
:layout-item-max-h
:layout-item-max-w
:layout-item-min-h
:layout-item-min-w
:layout-item-v-sizing
:layout-padding-type
:layout-item-margin
:layout-item-margin-type
:layout-grid-cells
:layout-grid-columns
:layout-grid-rows})
(defn apply-modifiers* (defn apply-modifiers*
"A lower-level version of apply-modifiers, that expects receive ready "A lower-level version of apply-modifiers, that expects receive ready
to use objects, object-modifiers and text-modifiers." to use objects, object-modifiers and text-modifiers."

View File

@ -457,7 +457,7 @@ pub extern "C" fn set_structure_modifiers() {
let Some(shape) = state.shapes.get(&entry.id) else { let Some(shape) = state.shapes.get(&entry.id) else {
continue; continue;
}; };
for id in shape.all_children_with_self(&state.shapes) { for id in shape.all_children_with_self(&state.shapes, true) {
state.scale_content.insert(id, entry.value); state.scale_content.insert(id, entry.value);
} }
} }

View File

@ -930,7 +930,8 @@ impl RenderState {
let children_clip_bounds = let children_clip_bounds =
node_render_state.get_children_clip_bounds(element, modifiers.get(&element.id)); node_render_state.get_children_clip_bounds(element, modifiers.get(&element.id));
let mut children_ids = modified_children_ids(element, structure.get(&element.id)); let mut children_ids =
modified_children_ids(element, structure.get(&element.id), false);
// Z-index ordering on Layouts // Z-index ordering on Layouts
if element.has_layout() { if element.has_layout() {
@ -1020,7 +1021,7 @@ impl RenderState {
let Some(root) = tree.get(&Uuid::nil()) else { let Some(root) = tree.get(&Uuid::nil()) else {
return Err(String::from("Root shape not found")); return Err(String::from("Root shape not found"));
}; };
let root_ids = modified_children_ids(root, structure.get(&root.id)); let root_ids = modified_children_ids(root, structure.get(&root.id), false);
// If we finish processing every node rendering is complete // If we finish processing every node rendering is complete
// let's check if there are more pending nodes // let's check if there are more pending nodes
@ -1119,7 +1120,7 @@ impl RenderState {
self.update_tile_for(&shape); self.update_tile_for(&shape);
} else { } else {
// We only need to rebuild tiles from the first level. // We only need to rebuild tiles from the first level.
let children = modified_children_ids(&shape, structure.get(&shape.id)); let children = modified_children_ids(&shape, structure.get(&shape.id), false);
for child_id in children.iter() { for child_id in children.iter() {
nodes.push(*child_id); nodes.push(*child_id);
} }
@ -1149,7 +1150,7 @@ impl RenderState {
self.update_tile_for(&shape); self.update_tile_for(&shape);
} }
let children = modified_children_ids(&shape, structure.get(&shape.id)); let children = modified_children_ids(&shape, structure.get(&shape.id), false);
for child_id in children.iter() { for child_id in children.iter() {
nodes.push(*child_id); nodes.push(*child_id);
} }

View File

@ -30,7 +30,7 @@ pub fn render_overlay(
} }
let layout_bounds = shape.bounds(); let layout_bounds = shape.bounds();
let children = modified_children_ids(shape, structure.get(&shape.id)); let children = modified_children_ids(shape, structure.get(&shape.id), false);
let column_tracks = calculate_tracks( let column_tracks = calculate_tracks(
true, true,

View File

@ -728,7 +728,11 @@ impl Shape {
self.children.first() self.children.first()
} }
pub fn children_ids(&self) -> IndexSet<Uuid> { pub fn children_ids(&self, include_hidden: bool) -> IndexSet<Uuid> {
if include_hidden {
return self.children.clone().into_iter().rev().collect();
}
if let Type::Bool(_) = self.shape_type { if let Type::Bool(_) = self.shape_type {
IndexSet::<Uuid>::new() IndexSet::<Uuid>::new()
} else if let Type::Group(group) = self.shape_type { } else if let Type::Group(group) = self.shape_type {
@ -747,14 +751,22 @@ impl Shape {
} }
} }
pub fn all_children_with_self(&self, shapes: &HashMap<Uuid, &mut Shape>) -> IndexSet<Uuid> { pub fn all_children_with_self(
&self,
shapes: &HashMap<Uuid, &mut Shape>,
include_hidden: bool,
) -> IndexSet<Uuid> {
once(self.id) once(self.id)
.chain(self.children_ids().into_iter().flat_map(|id| { .chain(
shapes self.children_ids(include_hidden)
.get(&id) .into_iter()
.map(|s| s.all_children_with_self(shapes)) .flat_map(|id| {
.unwrap_or_default() shapes
})) .get(&id)
.map(|s| s.all_children_with_self(shapes, include_hidden))
.unwrap_or_default()
}),
)
.collect() .collect()
} }
@ -935,9 +947,11 @@ impl Shape {
pub fn modified_children_ids( pub fn modified_children_ids(
element: &Shape, element: &Shape,
structure: Option<&Vec<StructureEntry>>, structure: Option<&Vec<StructureEntry>>,
include_hidden: bool,
) -> IndexSet<Uuid> { ) -> IndexSet<Uuid> {
if let Some(structure) = structure { if let Some(structure) = structure {
let mut result: Vec<Uuid> = Vec::from_iter(element.children_ids().iter().copied()); let mut result: Vec<Uuid> =
Vec::from_iter(element.children_ids(include_hidden).iter().copied());
let mut to_remove = HashSet::<&Uuid>::new(); let mut to_remove = HashSet::<&Uuid>::new();
for st in structure { for st in structure {
@ -960,7 +974,7 @@ pub fn modified_children_ids(
ret ret
} else { } else {
element.children_ids() element.children_ids(include_hidden)
} }
} }

View File

@ -25,7 +25,7 @@ fn propagate_children(
structure: &HashMap<Uuid, Vec<StructureEntry>>, structure: &HashMap<Uuid, Vec<StructureEntry>>,
scale_content: &HashMap<Uuid, f32>, scale_content: &HashMap<Uuid, f32>,
) -> VecDeque<Modifier> { ) -> VecDeque<Modifier> {
let children_ids = modified_children_ids(shape, structure.get(&shape.id)); let children_ids = modified_children_ids(shape, structure.get(&shape.id), true);
if children_ids.is_empty() || identitish(transform) { if children_ids.is_empty() || identitish(transform) {
return VecDeque::new(); return VecDeque::new();
@ -95,7 +95,7 @@ fn calculate_group_bounds(
let shape_bounds = bounds.find(shape); let shape_bounds = bounds.find(shape);
let mut result = Vec::<Point>::new(); let mut result = Vec::<Point>::new();
let children_ids = modified_children_ids(shape, structure.get(&shape.id)); let children_ids = modified_children_ids(shape, structure.get(&shape.id), true);
for child_id in children_ids.iter() { for child_id in children_ids.iter() {
let Some(child) = shapes.get(child_id) else { let Some(child) = shapes.get(child_id) else {
continue; continue;
@ -272,7 +272,7 @@ pub fn propagate_modifiers(
} }
Type::Group(Group { masked: true }) => { Type::Group(Group { masked: true }) => {
let children_ids = let children_ids =
modified_children_ids(shape, state.structure.get(&shape.id)); modified_children_ids(shape, state.structure.get(&shape.id), true);
if let Some(child) = shapes.get(&children_ids[0]) { if let Some(child) = shapes.get(&children_ids[0]) {
let child_bounds = bounds.find(child); let child_bounds = bounds.find(child);
bounds.insert(shape.id, child_bounds); bounds.insert(shape.id, child_bounds);

View File

@ -184,7 +184,7 @@ fn initialize_tracks(
) -> Vec<TrackData> { ) -> Vec<TrackData> {
let mut tracks = Vec::<TrackData>::new(); let mut tracks = Vec::<TrackData>::new();
let mut current_track = TrackData::default(); let mut current_track = TrackData::default();
let mut children = modified_children_ids(shape, structure.get(&shape.id)); let mut children = modified_children_ids(shape, structure.get(&shape.id), true);
let mut first = true; let mut first = true;
if flex_data.is_reverse() { if flex_data.is_reverse() {

View File

@ -634,7 +634,7 @@ pub fn reflow_grid_layout(
) -> VecDeque<Modifier> { ) -> VecDeque<Modifier> {
let mut result = VecDeque::new(); let mut result = VecDeque::new();
let layout_bounds = bounds.find(shape); let layout_bounds = bounds.find(shape);
let children = modified_children_ids(shape, structure.get(&shape.id)); let children = modified_children_ids(shape, structure.get(&shape.id), true);
let column_tracks = calculate_tracks( let column_tracks = calculate_tracks(
true, true,