From b2647f30c2fb71628af23d17430e9d7ef6a16cb3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 17 Jun 2025 11:47:39 +0200 Subject: [PATCH 1/5] :sparkles: Support grid editor with wasm modifiers --- .../viewport/grid_layout_editor.cljs | 177 +++++++++++++----- 1 file changed, 131 insertions(+), 46 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs index 2f6ae94a66..4f94b0bde0 100644 --- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs @@ -23,6 +23,7 @@ [app.main.data.workspace.grid-layout.editor :as dwge] [app.main.data.workspace.modifiers :as dwm] [app.main.data.workspace.shape-layout :as dwsl] + [app.main.features :as features] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.css-cursors :as cur] @@ -158,11 +159,13 @@ (mf/deps on-drag-end) (fn [event] (let [raw-pt (mf/ref-val current-pos-ref) - position (uwvv/point->viewport raw-pt)] + position (uwvv/point->viewport raw-pt) + start (mf/ref-val start-pos-ref) + delta (gpt/to-vec start (dom/get-client-position event))] (dom/release-pointer event) (mf/set-ref-val! dragging-ref false) (mf/set-ref-val! start-pos-ref nil) - (when on-drag-end (on-drag-end event position))))) + (when on-drag-end (on-drag-end event position delta))))) handle-pointer-move (mf/use-fn @@ -190,6 +193,9 @@ height (unchecked-get props "height") handler (unchecked-get props "handler") + on-set-modifiers (unchecked-get props "on-set-modifiers") + on-clear-modifiers (unchecked-get props "on-clear-modifiers") + objects (mf/deref refs/workspace-page-objects) {cell-id :id} (unchecked-get props "cell") {:keys [row column row-span column-span]} (get-in shape [:layout-grid-cells cell-id]) @@ -197,10 +203,10 @@ direction (unchecked-get props "direction") layout-data (unchecked-get props "layout-data") - handle-drag-position + calculate-drag-modifiers (mf/use-fn (mf/deps shape row column row-span column-span) - (fn [_ position] + (fn [position] (let [[drag-row drag-column] (gsg/get-position-grid-coord layout-data position) [new-row new-column new-row-span new-column-span] @@ -225,19 +231,34 @@ shape (-> (ctl/resize-cell-area shape row column new-row new-column new-row-span new-column-span) - (ctl/assign-cells objects)) + (ctl/assign-cells objects))] + (-> (ctm/empty) + (ctm/change-property :layout-grid-rows (:layout-grid-rows shape)) + (ctm/change-property :layout-grid-columns (:layout-grid-columns shape)) + (ctm/change-property :layout-grid-cells (:layout-grid-cells shape)))))) - modifiers - (-> (ctm/empty) - (ctm/change-property :layout-grid-rows (:layout-grid-rows shape)) - (ctm/change-property :layout-grid-columns (:layout-grid-columns shape)) - (ctm/change-property :layout-grid-cells (:layout-grid-cells shape)))] - (st/emit! (dwm/set-modifiers (dwm/create-modif-tree [(:id shape)] modifiers)))))) + handle-drag-position + (mf/use-fn + (mf/deps calculate-drag-modifiers on-set-modifiers) + (fn [_ position] + (let [modifiers (calculate-drag-modifiers position) + modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)] + (if (features/active-feature? @st/state "render-wasm/v1") + (do + (when on-set-modifiers (on-set-modifiers modifiers)) + (st/emit! (dwm/set-wasm-modifiers modif-tree))) + (st/emit! (dwm/set-modifiers modif-tree)))))) handle-drag-end (mf/use-fn - (fn [] - (st/emit! (dwm/apply-modifiers)))) + (mf/deps calculate-drag-modifiers on-clear-modifiers) + (fn [_ position] + (if (features/active-feature? @st/state "render-wasm/v1") + (let [modifiers (calculate-drag-modifiers position) + modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)] + (when on-clear-modifiers (on-clear-modifiers modifiers)) + (st/emit! (dwm/apply-wasm-modifiers modif-tree))) + (st/emit! (dwm/apply-modifiers))))) {:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]} (use-drag {:on-drag-position handle-drag-position @@ -291,9 +312,9 @@ text]])) (mf/defc grid-cell - {::mf/memo #{:shape :cell :layout-data :zoom :hover? :selected?} + {::mf/memo #{:shape :cell :layout-data :zoom :hover? :selected? :on-set-modifiers :on-clear-modifiers} ::mf/props :obj} - [{:keys [shape cell layout-data zoom hover? selected?]}] + [{:keys [shape cell layout-data zoom hover? selected? on-set-modifiers on-clear-modifiers]}] (let [cell-bounds (gsg/cell-bounds layout-data cell) cell-origin (gpo/origin cell-bounds) cell-width (gpo/width-points cell-bounds) @@ -408,10 +429,12 @@ :width width :height height :direction dir - :layout-data layout-data}])]))])) + :layout-data layout-data + :on-set-modifiers on-set-modifiers + :on-clear-modifiers on-clear-modifiers}])]))])) (defn use-resize-track - [type shape index track-before track-after zoom snap-pixel?] + [type shape index track-before track-after zoom snap-pixel? on-set-modifiers on-clear-modifiers] (let [start-size-before (mf/use-var nil) start-size-after (mf/use-var nil) @@ -433,13 +456,18 @@ modifiers (-> (ctm/empty) - (ctm/change-property tracks-prop (get shape tracks-prop)))] - (st/emit! (dwm/set-modifiers (dwm/create-modif-tree [(:id shape)] modifiers)))))) + (ctm/change-property tracks-prop (get shape tracks-prop))) - handle-drag-position + modif-tree + (dwm/create-modif-tree [(:id shape)] modifiers)] + (if (features/active-feature? @st/state "render-wasm/v1") + (st/emit! (dwm/set-wasm-modifiers modif-tree)) + (st/emit! (dwm/set-modifiers modif-tree)))))) + + calculate-modifiers (mf/use-fn (mf/deps shape track-before track-after) - (fn [_ position] + (fn [position] (let [[tracks-prop axis] (if (= :column type) [:layout-grid-columns :x] [:layout-grid-rows :y]) @@ -454,20 +482,34 @@ (cond-> (some? track-before) (update-in [tracks-prop (dec index)] merge {:type :fixed :value new-size-before})) (cond-> (some? track-after) - (update-in [tracks-prop index] merge {:type :fixed :value new-size-after}))) + (update-in [tracks-prop index] merge {:type :fixed :value new-size-after})))] + (-> (ctm/empty) + (ctm/change-property tracks-prop (get shape tracks-prop)))))) - modifiers - (-> (ctm/empty) - (ctm/change-property tracks-prop (get shape tracks-prop)))] - (st/emit! (dwm/set-modifiers (dwm/create-modif-tree [(:id shape)] modifiers)))))) + handle-drag-position + (mf/use-fn + (mf/deps calculate-modifiers on-set-modifiers) + (fn [_ position] + (let [modifiers (calculate-modifiers position) + modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)] + (if (features/active-feature? @st/state "render-wasm/v1") + (do + (when on-set-modifiers (on-set-modifiers modifiers)) + (st/emit! (dwm/set-wasm-modifiers modif-tree))) + (st/emit! (dwm/set-modifiers modif-tree)))))) handle-drag-end (mf/use-fn - (mf/deps track-before track-after) - (fn [] + (mf/deps calculate-modifiers on-clear-modifiers) + (fn [_ _ position] + (if (features/active-feature? @st/state "render-wasm/v1") + (let [modifiers (calculate-modifiers position) + modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)] + (when on-clear-modifiers (on-clear-modifiers)) + (st/emit! (dwm/apply-wasm-modifiers modif-tree))) + (st/emit! (dwm/apply-modifiers))) (reset! start-size-before nil) - (reset! start-size-after nil) - (st/emit! (dwm/apply-modifiers))))] + (reset! start-size-after nil)))] (use-drag {:on-drag-start handle-drag-start :on-drag-delta handle-drag-position @@ -485,6 +527,9 @@ track-after (unchecked-get props "track-after") snap-pixel? (unchecked-get props "snap-pixel?") + on-set-modifiers (unchecked-get props "on-set-modifiers") + on-clear-modifiers (unchecked-get props "on-clear-modifiers") + {:keys [column-total-size column-total-gap row-total-size row-total-gap] :as layout-data} (unchecked-get props "layout-data") @@ -499,7 +544,7 @@ [layout-gap-row layout-gap-col] (ctl/gaps shape) {:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]} - (use-resize-track type shape index track-before track-after zoom snap-pixel?) + (use-resize-track type shape index track-before track-after zoom snap-pixel? on-set-modifiers on-clear-modifiers) [width height] (if (= type :column) @@ -656,11 +701,14 @@ track-after (unchecked-get props "track-after") snap-pixel? (unchecked-get props "snap-pixel?") + on-set-modifiers (unchecked-get props "on-set-modifiers") + on-clear-modifiers (unchecked-get props "on-clear-modifiers") + text-x (:x center) text-y (:y center) {:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]} - (use-resize-track type shape index track-before track-after zoom snap-pixel?)] + (use-resize-track type shape index track-before track-after zoom snap-pixel? on-set-modifiers on-clear-modifiers)] [:g {:on-pointer-down handle-pointer-down :on-lost-pointer-capture handle-lost-pointer-capture @@ -699,6 +747,9 @@ on-move-reorder-track (unchecked-get props "on-move-reorder-track") on-end-reorder-track (unchecked-get props "on-end-reorder-track") + on-set-modifiers (unchecked-get props "on-set-modifiers") + on-clear-modifiers (unchecked-get props "on-clear-modifiers") + track-input-ref (mf/use-ref) [layout-gap-row layout-gap-col] (ctl/gaps shape) @@ -876,7 +927,9 @@ :track-before track-before :type type :value (dm/str (inc index)) - :zoom zoom}]] + :zoom zoom + :on-set-modifiers on-set-modifiers + :on-clear-modifiers on-clear-modifiers}]] [:& resize-track-handler {:index index @@ -888,7 +941,9 @@ :track-after track-data :track-before track-before :type type - :zoom zoom}]])) + :zoom zoom + :on-set-modifiers on-set-modifiers + :on-clear-modifiers on-clear-modifiers}]])) (mf/defc editor {::mf/memo true @@ -900,12 +955,18 @@ zoom (unchecked-get props "zoom") view-only (unchecked-get props "view-only") + st-modif (mf/use-state nil) + shape (mf/use-memo - (mf/deps modifiers base-shape) - #(gsh/transform-shape - base-shape - (dm/get-in modifiers [(:id base-shape) :modifiers]))) + (mf/deps base-shape modifiers @st-modif) + #(cond-> base-shape + (some? modifiers) + (gsh/transform-shape + (dm/get-in modifiers [(:id base-shape) :modifiers])) + + (some? @st-modif) + (gsh/transform-shape @st-modif))) snap-pixel? (mf/deref refs/snap-pixel?) @@ -1032,7 +1093,17 @@ (mf/set-ref-val! target-tracks* nil) (reset! drop-track-type* nil) - (reset! drop-track-target* nil)))] + (reset! drop-track-target* nil))) + + handle-set-modifiers + (mf/use-fn + (fn [modifier] + (reset! st-modif modifier))) + + handle-clear-modifiers + (mf/use-fn + (fn [] + (reset! st-modif nil)))] (mf/with-effect [] #(st/emit! (dwge/stop-grid-layout-editing (:id shape)))) @@ -1048,7 +1119,9 @@ :cell cell :zoom zoom :hover? (contains? hover-cells (:id cell)) - :selected? (contains? selected-cells (:id cell))}])] + :selected? (contains? selected-cells (:id cell)) + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}])] (when-not ^boolean view-only [:* @@ -1085,7 +1158,9 @@ :hovering? (contains? hover-columns idx) :on-start-reorder-track handle-start-reorder-track :on-move-reorder-track handle-move-reorder-track - :on-end-reorder-track handle-end-reorder-track}])) + :on-end-reorder-track handle-end-reorder-track + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}])) ;; Last track resize handler (when-not (empty? column-tracks) @@ -1102,7 +1177,9 @@ :track-before (last column-tracks) :type :column :value (dm/str (inc (count column-tracks))) - :zoom zoom}] + :zoom zoom + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}] (let [drop? (and (= :column @drop-track-type*) (= (count column-tracks) @drop-track-target*))] [:& resize-track-handler @@ -1115,7 +1192,9 @@ :start-p end-p :type :column :track-before (last column-tracks) - :zoom zoom}])])) + :zoom zoom + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}])])) (for [[idx row-data] (d/enumerate row-tracks)] (let [drop? (and (= :row @drop-track-type*) @@ -1132,7 +1211,9 @@ :hovering? (contains? hover-rows idx) :on-start-reorder-track handle-start-reorder-track :on-move-reorder-track handle-move-reorder-track - :on-end-reorder-track handle-end-reorder-track}])) + :on-end-reorder-track handle-end-reorder-track + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}])) (when-not (empty? row-tracks) (let [last-track (last row-tracks) start-p (:start-p last-track) @@ -1148,7 +1229,9 @@ :track-before (last row-tracks) :type :row :value (dm/str (inc (count row-tracks))) - :zoom zoom}]] + :zoom zoom + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}]] (let [drop? (and (= :row @drop-track-type*) (= (count row-tracks) @drop-track-target*))] [:& resize-track-handler @@ -1161,4 +1244,6 @@ :type :row :track-before (last row-tracks) :snap-pixel? snap-pixel? - :zoom zoom}])]))])]))) + :zoom zoom + :on-set-modifiers handle-set-modifiers + :on-clear-modifiers handle-clear-modifiers}])]))])]))) From 58e5748b4f68e7a3035db7fdb4551059f2f547c0 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 18 Jun 2025 10:36:29 +0200 Subject: [PATCH 2/5] :bug: Fix wasm layout problems --- render-wasm/src/math.rs | 2 +- render-wasm/src/shapes/modifiers.rs | 28 +++++++++++-------- .../src/shapes/modifiers/constraints.rs | 8 +++--- .../src/shapes/modifiers/flex_layout.rs | 23 +++++++++------ 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/render-wasm/src/math.rs b/render-wasm/src/math.rs index 25e6989184..2d6d06062a 100644 --- a/render-wasm/src/math.rs +++ b/render-wasm/src/math.rs @@ -412,7 +412,7 @@ pub fn resize_matrix( parent_transform.post_translate(center); parent_transform.pre_translate(-center); - let parent_transform_inv = &parent_transform.invert().unwrap(); + let parent_transform_inv = &parent_transform.invert().unwrap_or_default(); let origin = parent_transform_inv.map_point(child_bounds.nw); let mut scale = Matrix::scale((scale_width, scale_height)); diff --git a/render-wasm/src/shapes/modifiers.rs b/render-wasm/src/shapes/modifiers.rs index eaf5bbd220..92fd7e69e0 100644 --- a/render-wasm/src/shapes/modifiers.rs +++ b/render-wasm/src/shapes/modifiers.rs @@ -115,22 +115,28 @@ fn set_pixel_precision(transform: &mut Matrix, bounds: &mut Bounds) { let x = bounds.min_x().round(); let y = bounds.min_y().round(); - let mut round_transform = Matrix::scale(( - bounds.width().round() / bounds.width(), - bounds.height().round() / bounds.height(), - )); - round_transform.post_concat(&tr); - round_transform.pre_concat(&tr_inv); + let scale_width = f32::max(0.01, bounds.width().round() / bounds.width()); + let scale_height = f32::max(0.01, bounds.height().round() / bounds.height()); - transform.post_concat(&round_transform); - bounds.transform_mut(&round_transform); + if f32::is_finite(scale_width) + && f32::is_finite(scale_height) + && (!math::is_close_to(scale_width, 1.0) || !math::is_close_to(scale_height, 1.0)) + { + let mut round_transform = Matrix::scale((scale_width, scale_height)); + round_transform.post_concat(&tr); + round_transform.pre_concat(&tr_inv); + transform.post_concat(&round_transform); + bounds.transform_mut(&round_transform); + } let dx = x - bounds.min_x(); let dy = y - bounds.min_y(); - let round_transform = Matrix::translate((dx, dy)); - transform.post_concat(&round_transform); - bounds.transform_mut(&round_transform); + if f32::is_finite(dx) && f32::is_finite(dy) { + let round_transform = Matrix::translate((dx, dy)); + transform.post_concat(&round_transform); + bounds.transform_mut(&round_transform); + } } pub fn propagate_modifiers( diff --git a/render-wasm/src/shapes/modifiers/constraints.rs b/render-wasm/src/shapes/modifiers/constraints.rs index c764201007..1a838c0a9a 100644 --- a/render-wasm/src/shapes/modifiers/constraints.rs +++ b/render-wasm/src/shapes/modifiers/constraints.rs @@ -11,26 +11,26 @@ pub fn calculate_resize( ) -> Option<(f32, f32)> { let scale_width = match constraint_h { ConstraintH::Left | ConstraintH::Right | ConstraintH::Center => { - parent_before.width() / parent_after.width() + parent_before.width() / f32::max(0.01, parent_after.width()) } ConstraintH::LeftRight => { let left = parent_before.left(child_before.nw); let right = parent_before.right(child_before.ne); let target_width = parent_after.width() - left - right; - target_width / child_after.width() + target_width / f32::max(0.01, child_after.width()) } _ => 1.0, }; let scale_height = match constraint_v { ConstraintV::Top | ConstraintV::Bottom | ConstraintV::Center => { - parent_before.height() / parent_after.height() + parent_before.height() / f32::max(0.01, parent_after.height()) } ConstraintV::TopBottom => { let top = parent_before.top(child_before.nw); let bottom = parent_before.bottom(child_before.sw); let target_height = parent_after.height() - top - bottom; - target_height / child_after.height() + target_height / f32::max(0.01, child_after.height()) } _ => 1.0, }; diff --git a/render-wasm/src/shapes/modifiers/flex_layout.rs b/render-wasm/src/shapes/modifiers/flex_layout.rs index 8e7a47a456..1d26392146 100644 --- a/render-wasm/src/shapes/modifiers/flex_layout.rs +++ b/render-wasm/src/shapes/modifiers/flex_layout.rs @@ -269,7 +269,11 @@ fn initialize_tracks( // Resize main axis fill fn distribute_fill_main_space(layout_axis: &LayoutAxis, tracks: &mut [TrackData]) { for track in tracks.iter_mut() { - let mut left_space = layout_axis.main_space() - track.main_size; + let mut left_space = if layout_axis.is_auto_main { + 0.0 + } else { + layout_axis.main_space() - track.main_size + }; let mut to_resize_children: Vec<&mut ChildAxis> = Vec::new(); for child in track.shapes.iter_mut() { @@ -299,7 +303,13 @@ fn distribute_fill_main_space(layout_axis: &LayoutAxis, tracks: &mut [TrackData] fn distribute_fill_across_space(layout_axis: &LayoutAxis, tracks: &mut [TrackData]) { let total_across_size = tracks.iter().map(|t| t.across_size).sum::() + (tracks.len() - 1) as f32 * layout_axis.gap_across; - let mut left_space = layout_axis.across_space() - total_across_size; + + let mut left_space = if layout_axis.is_auto_across { + 0.0 + } else { + layout_axis.across_space() - total_across_size + }; + let mut to_resize_tracks: Vec<&mut TrackData> = Vec::new(); for track in tracks.iter_mut() { @@ -435,13 +445,8 @@ fn calculate_track_data( structure, ); - if !layout_axis.is_auto_main { - distribute_fill_main_space(&layout_axis, &mut tracks); - } - - if !layout_axis.is_auto_across { - distribute_fill_across_space(&layout_axis, &mut tracks); - } + distribute_fill_main_space(&layout_axis, &mut tracks); + distribute_fill_across_space(&layout_axis, &mut tracks); let total_across_size = tracks.iter().map(|t| t.across_size).sum::(); From 5b4cd9f4f168153a5b6c633dfacbfbbcca049a02 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 18 Jun 2025 14:51:46 +0200 Subject: [PATCH 3/5] :bug: Fix problem when moving masks, bools, groups with wasm --- .../app/main/data/workspace/modifiers.cljs | 88 +++++++++++-------- render-wasm/src/main.rs | 2 +- render-wasm/src/render.rs | 9 +- render-wasm/src/render/grid_layout.rs | 2 +- render-wasm/src/shapes.rs | 34 ++++--- render-wasm/src/shapes/modifiers.rs | 6 +- .../src/shapes/modifiers/flex_layout.rs | 2 +- .../src/shapes/modifiers/grid_layout.rs | 2 +- 8 files changed, 86 insertions(+), 59 deletions(-) diff --git a/frontend/src/app/main/data/workspace/modifiers.cljs b/frontend/src/app/main/data/workspace/modifiers.cljs index 6f8ffb5b21..b83085e354 100644 --- a/frontend/src/app/main/data/workspace/modifiers.cljs +++ b/frontend/src/app/main/data/workspace/modifiers.cljs @@ -39,6 +39,43 @@ (def ^:private xf:without-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 ------------------------------------------- ;; During an interactive transformation of shapes (e.g. when resizing or rotating @@ -598,6 +635,18 @@ ptk/WatchEvent (watch [_ 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) snap-pixel? @@ -627,7 +676,7 @@ (clear-local-transform) (ptk/event ::dwg/move-frame-guides {:ids ids :transforms transforms}) (ptk/event ::dwcm/move-frame-comment-threads transforms) - (dwsh/update-shapes ids update-shape)))))) + (dwsh/update-shapes ids update-shape options)))))) (def ^:private xf-rotation-shape @@ -714,43 +763,6 @@ (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* "A lower-level version of apply-modifiers, that expects receive ready to use objects, object-modifiers and text-modifiers." diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 91fd754491..ef6e1867f4 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -457,7 +457,7 @@ pub extern "C" fn set_structure_modifiers() { let Some(shape) = state.shapes.get(&entry.id) else { 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); } } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 135225c1a3..7139846c05 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -930,7 +930,8 @@ impl RenderState { let children_clip_bounds = 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 if element.has_layout() { @@ -1020,7 +1021,7 @@ impl RenderState { let Some(root) = tree.get(&Uuid::nil()) else { 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 // let's check if there are more pending nodes @@ -1119,7 +1120,7 @@ impl RenderState { self.update_tile_for(&shape); } else { // 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() { nodes.push(*child_id); } @@ -1149,7 +1150,7 @@ impl RenderState { 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() { nodes.push(*child_id); } diff --git a/render-wasm/src/render/grid_layout.rs b/render-wasm/src/render/grid_layout.rs index c617854287..23e7a0bba0 100644 --- a/render-wasm/src/render/grid_layout.rs +++ b/render-wasm/src/render/grid_layout.rs @@ -30,7 +30,7 @@ pub fn render_overlay( } 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( true, diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index da6e5dcda7..27e21047e3 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -728,7 +728,11 @@ impl Shape { self.children.first() } - pub fn children_ids(&self) -> IndexSet { + pub fn children_ids(&self, include_hidden: bool) -> IndexSet { + if include_hidden { + return self.children.clone().into_iter().rev().collect(); + } + if let Type::Bool(_) = self.shape_type { IndexSet::::new() } else if let Type::Group(group) = self.shape_type { @@ -747,14 +751,22 @@ impl Shape { } } - pub fn all_children_with_self(&self, shapes: &HashMap) -> IndexSet { + pub fn all_children_with_self( + &self, + shapes: &HashMap, + include_hidden: bool, + ) -> IndexSet { once(self.id) - .chain(self.children_ids().into_iter().flat_map(|id| { - shapes - .get(&id) - .map(|s| s.all_children_with_self(shapes)) - .unwrap_or_default() - })) + .chain( + self.children_ids(include_hidden) + .into_iter() + .flat_map(|id| { + shapes + .get(&id) + .map(|s| s.all_children_with_self(shapes, include_hidden)) + .unwrap_or_default() + }), + ) .collect() } @@ -935,9 +947,11 @@ impl Shape { pub fn modified_children_ids( element: &Shape, structure: Option<&Vec>, + include_hidden: bool, ) -> IndexSet { if let Some(structure) = structure { - let mut result: Vec = Vec::from_iter(element.children_ids().iter().copied()); + let mut result: Vec = + Vec::from_iter(element.children_ids(include_hidden).iter().copied()); let mut to_remove = HashSet::<&Uuid>::new(); for st in structure { @@ -960,7 +974,7 @@ pub fn modified_children_ids( ret } else { - element.children_ids() + element.children_ids(include_hidden) } } diff --git a/render-wasm/src/shapes/modifiers.rs b/render-wasm/src/shapes/modifiers.rs index 92fd7e69e0..e5ce7cc3a1 100644 --- a/render-wasm/src/shapes/modifiers.rs +++ b/render-wasm/src/shapes/modifiers.rs @@ -25,7 +25,7 @@ fn propagate_children( structure: &HashMap>, scale_content: &HashMap, ) -> VecDeque { - 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) { return VecDeque::new(); @@ -95,7 +95,7 @@ fn calculate_group_bounds( let shape_bounds = bounds.find(shape); let mut result = Vec::::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() { let Some(child) = shapes.get(child_id) else { continue; @@ -272,7 +272,7 @@ pub fn propagate_modifiers( } Type::Group(Group { masked: true }) => { 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]) { let child_bounds = bounds.find(child); bounds.insert(shape.id, child_bounds); diff --git a/render-wasm/src/shapes/modifiers/flex_layout.rs b/render-wasm/src/shapes/modifiers/flex_layout.rs index 1d26392146..acaa118de1 100644 --- a/render-wasm/src/shapes/modifiers/flex_layout.rs +++ b/render-wasm/src/shapes/modifiers/flex_layout.rs @@ -184,7 +184,7 @@ fn initialize_tracks( ) -> Vec { let mut tracks = Vec::::new(); 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; if flex_data.is_reverse() { diff --git a/render-wasm/src/shapes/modifiers/grid_layout.rs b/render-wasm/src/shapes/modifiers/grid_layout.rs index 5ac85911d9..fca6203059 100644 --- a/render-wasm/src/shapes/modifiers/grid_layout.rs +++ b/render-wasm/src/shapes/modifiers/grid_layout.rs @@ -634,7 +634,7 @@ pub fn reflow_grid_layout( ) -> VecDeque { let mut result = VecDeque::new(); 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( true, From b997d5a320a25636f8597a3b28ab216b96c3ed08 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 19 Jun 2025 11:20:43 +0200 Subject: [PATCH 4/5] :bug: Fix problem with grid layout wasm --- render-wasm/src/render/grid_layout.rs | 16 +++++++++++++++- render-wasm/src/shapes/modifiers.rs | 2 +- render-wasm/src/shapes/modifiers/grid_layout.rs | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/render-wasm/src/render/grid_layout.rs b/render-wasm/src/render/grid_layout.rs index 23e7a0bba0..04c732355e 100644 --- a/render-wasm/src/render/grid_layout.rs +++ b/render-wasm/src/render/grid_layout.rs @@ -1,6 +1,8 @@ use skia_safe::{self as skia}; use std::collections::HashMap; +use crate::shapes::modifiers::common::GetBounds; + use crate::math::{Bounds, Matrix, Rect}; use crate::shapes::modifiers::grid_layout::{calculate_tracks, create_cell_data}; use crate::shapes::{modified_children_ids, Frame, Layout, Shape, StructureEntry, Type}; @@ -22,7 +24,7 @@ pub fn render_overlay( return; }; - let bounds = &HashMap::::new(); + let bounds = &mut HashMap::::new(); let shape = &mut shape.clone(); if let Some(modifiers) = modifiers.get(&shape.id) { @@ -32,6 +34,18 @@ pub fn render_overlay( let layout_bounds = shape.bounds(); let children = modified_children_ids(shape, structure.get(&shape.id), false); + for child_id in children.iter() { + let Some(child) = shapes.get(child_id) else { + continue; + }; + + if let Some(modifier) = modifiers.get(child_id) { + let mut b = bounds.find(child); + b.transform_mut(modifier); + bounds.insert(*child_id, b); + } + } + let column_tracks = calculate_tracks( true, shape, diff --git a/render-wasm/src/shapes/modifiers.rs b/render-wasm/src/shapes/modifiers.rs index e5ce7cc3a1..28a25dcc0a 100644 --- a/render-wasm/src/shapes/modifiers.rs +++ b/render-wasm/src/shapes/modifiers.rs @@ -1,5 +1,5 @@ use std::collections::{HashMap, HashSet, VecDeque}; -mod common; +pub mod common; mod constraints; mod flex_layout; pub mod grid_layout; diff --git a/render-wasm/src/shapes/modifiers/grid_layout.rs b/render-wasm/src/shapes/modifiers/grid_layout.rs index fca6203059..712c2ea8a1 100644 --- a/render-wasm/src/shapes/modifiers/grid_layout.rs +++ b/render-wasm/src/shapes/modifiers/grid_layout.rs @@ -117,7 +117,7 @@ fn set_auto_base_size( (cell.row, cell.row_span) }; - if prop_span != 1 || (prop as usize) >= tracks.len() { + if prop_span != 1 || (prop as usize) > tracks.len() { continue; } From 11467e26a28930c09597b91293cdf0c8c766d6af Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 19 Jun 2025 13:03:05 +0200 Subject: [PATCH 5/5] :bug: Fix problem with flex wrap in wasm --- render-wasm/src/shapes/modifiers/flex_layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render-wasm/src/shapes/modifiers/flex_layout.rs b/render-wasm/src/shapes/modifiers/flex_layout.rs index acaa118de1..ea2e55d280 100644 --- a/render-wasm/src/shapes/modifiers/flex_layout.rs +++ b/render-wasm/src/shapes/modifiers/flex_layout.rs @@ -421,7 +421,7 @@ fn calculate_track_positions( for track in tracks.iter_mut() { track.anchor = next_anchor; - next_anchor += layout_axis.across_v * real_gap; + next_anchor += layout_axis.across_v * (track.across_size + real_gap); } }