Add dynamic properties modifiers to WASM

This commit is contained in:
alonso.torres 2025-04-24 12:05:52 +02:00 committed by Alonso Torres
parent 44d68ad723
commit 8ce71e792e
5 changed files with 238 additions and 123 deletions

View file

@ -30,6 +30,7 @@
[app.main.data.workspace.undo :as dwu]
[app.main.features :as features]
[app.render-wasm.api :as wasm.api]
[app.render-wasm.shape :as wasm.shape]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@ -162,17 +163,46 @@
change-to-fixed?
(assoc :grow-type :fixed))))
(defn- set-wasm-props!
[objects prev-wasm-props wasm-props]
(let [;; Set old value for previous properties
clean-props
(->> prev-wasm-props
(map (fn [[id {:keys [property] :as change}]]
(let [shape (get objects id)]
[id (assoc change :value (get shape property))]))))
wasm-props
(concat clean-props wasm-props)
wasm-props
(-> (group-by first wasm-props)
(update-vals #(map second %)))]
;; Props are grouped by id and then assoc to the shape the new value
(doseq [[id properties] wasm-props]
(let [shape
(->> properties
(reduce
(fn [shape {:keys [property value]}]
(assoc shape property value))
(get objects id)))]
;; With the new values to the shape change multi props
(wasm.shape/set-wasm-multi-attrs! shape (->> properties (map :property)))))))
(defn clear-local-transform []
(ptk/reify ::clear-local-transform
ptk/EffectEvent
(effect [_ state _]
(when (features/active-feature? state "render-wasm/v1")
(wasm.api/clean-modifiers)))
(wasm.api/clean-modifiers)
(set-wasm-props! (dsh/lookup-page-objects state) (:wasm-props state) [])))
ptk/UpdateEvent
(update [_ state]
(-> state
(dissoc :workspace-modifiers)
(dissoc :workspace-modifiers :wasm-props :prev-wasm-props)
(dissoc :app.main.data.workspace.transforms/current-move-selected)))))
(defn create-modif-tree
@ -459,6 +489,15 @@
:transform (ctm/modifiers->transform (:modifiers data))})))
modif-tree))
(defn- extract-property-changes
[modif-tree]
(->> modif-tree
(mapcat (fn [[id {:keys [modifiers]}]]
(->> (:structure-parent modifiers)
(map #(vector id %)))))
(filter (fn [[_ {:keys [type]}]]
(= type :change-property)))))
(defn set-wasm-modifiers
([modif-tree]
(set-wasm-modifiers modif-tree false))
@ -471,15 +510,31 @@
([modif-tree _ignore-constraints _ignore-snap-pixel _params]
(ptk/reify ::set-wasm-modifiers
ptk/UpdateEvent
(update [_ state]
(let [property-changes
(extract-property-changes modif-tree)]
(-> state
(assoc :prev-wasm-props (:wasm-props state))
(assoc :wasm-props property-changes))))
ptk/EffectEvent
(effect [_ _ _]
(effect [_ state _]
(wasm.api/clean-modifiers)
(let [structure-entries (parse-structure-modifiers modif-tree)]
(wasm.api/set-structure-modifiers structure-entries)
(let [geometry-entries (parse-geometry-modifiers modif-tree)
modifiers-new
(wasm.api/propagate-modifiers geometry-entries)]
(wasm.api/set-modifiers modifiers-new)))))))
(let [prev-wasm-props (:prev-wasm-props state)
wasm-props (:wasm-props state)
objects (dsh/lookup-page-objects state)]
(set-wasm-props! objects prev-wasm-props wasm-props)
(let [structure-entries (parse-structure-modifiers modif-tree)]
(wasm.api/set-structure-modifiers structure-entries)
(let [geometry-entries (parse-geometry-modifiers modif-tree)
modifiers-new
(wasm.api/propagate-modifiers geometry-entries)]
(wasm.api/set-modifiers modifiers-new))))))))
(defn set-selrect-transform
[modifiers]

View file

@ -409,9 +409,8 @@
padding-bottom
padding-left)))
(defn set-grid-layout
(defn set-grid-layout-data
[shape]
(let [dir (-> (or (dm/get-prop shape :layout-grid-dir) :row) sr/translate-layout-grid-dir)
gap (dm/get-prop shape :layout-gap)
row-gap (or (dm/get-prop gap :row-gap) 0)
@ -440,11 +439,11 @@
padding-top
padding-right
padding-bottom
padding-left))
padding-left)))
;; Send Rows
(let [entries (:layout-grid-rows shape)
size (grid-layout-get-row-entries-size entries)
(defn set-grid-layout-rows
[entries]
(let [size (grid-layout-get-row-entries-size entries)
offset (mem/alloc-bytes size)
heap
@ -459,11 +458,11 @@
(.set heap (sr/u8 (sr/translate-grid-track-type type)) (+ current-offset 0))
(.set heap (sr/f32->u8 value) (+ current-offset 1))
(recur (rest entries) (+ current-offset GRID-LAYOUT-ROW-ENTRY-SIZE)))))
(h/call wasm/internal-module "_set_grid_rows"))
(h/call wasm/internal-module "_set_grid_rows")))
;; Send Columns
(let [entries (:layout-grid-columns shape)
size (grid-layout-get-column-entries-size entries)
(defn set-grid-layout-columns
[entries]
(let [size (grid-layout-get-column-entries-size entries)
offset (mem/alloc-bytes size)
heap
@ -478,10 +477,11 @@
(.set heap (sr/u8 (sr/translate-grid-track-type type)) (+ current-offset 0))
(.set heap (sr/f32->u8 value) (+ current-offset 1))
(recur (rest entries) (+ current-offset GRID-LAYOUT-COLUMN-ENTRY-SIZE)))))
(h/call wasm/internal-module "_set_grid_columns"))
(h/call wasm/internal-module "_set_grid_columns")))
;; Send cells
(let [entries (-> shape :layout-grid-cells vals)
(defn set-grid-layout-cells
[cells]
(let [entries (vals cells)
size (grid-layout-get-cell-entries-size entries)
offset (mem/alloc-bytes size)
@ -533,6 +533,13 @@
(h/call wasm/internal-module "_set_grid_cells")))
(defn set-grid-layout
[shape]
(set-grid-layout-data shape)
(set-grid-layout-rows (:layout-grid-rows shape))
(set-grid-layout-columns (:layout-grid-columns shape))
(set-grid-layout-cells (:layout-grid-cells shape)))
(defn set-layout-child
[shape]
(let [margins (dm/get-prop shape :layout-item-margin)
@ -868,4 +875,4 @@
(p/merr (fn [cause]
(js/console.error cause)
(p/resolved false)))))
(p/resolved false))))
(p/resolved false))))

View file

@ -108,106 +108,135 @@
;; --- SHAPE IMPL
(defn- set-wasm-attrs
(defn set-wasm-single-attr!
[shape k]
(let [v (get shape k)]
(case k
:parent-id (api/set-parent-id v)
:type (api/set-shape-type v)
:bool-type (api/set-shape-bool-type v)
:selrect (api/set-shape-selrect v)
:show-content (if (= (:type shape) :frame)
(api/set-shape-clip-content (not v))
(api/set-shape-clip-content false))
:rotation (api/set-shape-rotation v)
:transform (api/set-shape-transform v)
:fills (into [] (api/set-shape-fills v))
:strokes (into [] (api/set-shape-strokes v))
:blend-mode (api/set-shape-blend-mode v)
:opacity (api/set-shape-opacity v)
:hidden (api/set-shape-hidden v)
:shapes (api/set-shape-children v)
:blur (api/set-shape-blur v)
:shadow (api/set-shape-shadows v)
:constraints-h (api/set-constraints-h v)
:constraints-v (api/set-constraints-v v)
:svg-attrs
(when (= (:type shape) :path)
(api/set-shape-path-attrs v))
:masked-group
(when (and (= (:type shape) :group) (:masked-group shape))
(api/set-masked (:masked-group shape)))
:content
(cond
(or (= (:type shape) :path)
(= (:type shape) :bool))
(api/set-shape-path-content v)
(= (:type shape) :svg-raw)
(api/set-shape-svg-raw-content (api/get-static-markup shape))
(= (:type shape) :text)
(into [] (api/set-shape-text-content v)))
(:layout-item-margin
:layout-item-margin-type
:layout-item-h-sizing
:layout-item-v-sizing
:layout-item-max-h
:layout-item-min-h
:layout-item-max-w
:layout-item-min-w
:layout-item-absolute
:layout-item-z-index)
(api/set-layout-child shape)
:layout-grid-rows
(api/set-grid-layout-rows v)
:layout-grid-columns
(api/set-grid-layout-columns v)
:layout-grid-cells
(api/set-grid-layout-cells v)
(:layout
:layout-flex-dir
:layout-gap-type
:layout-gap
:layout-align-items
:layout-align-content
:layout-justify-items
:layout-justify-content
:layout-wrap-type
:layout-padding-type
:layout-padding)
(cond
(ctl/grid-layout? shape)
(api/set-grid-layout-data shape)
(ctl/flex-layout? shape)
(api/set-flex-layout shape))
nil)))
(defn set-wasm-multi-attrs!
[shape properties]
(api/use-shape (:id shape))
(let [pending
(->> properties
(mapcat #(set-wasm-single-attr! shape %)))]
(if (and pending (seq pending))
(->> (rx/from pending)
(rx/mapcat identity)
(rx/reduce conj [])
(rx/subs!
(fn [_]
(api/update-shape-tiles)
(api/clear-drawing-cache)
(api/request-render "set-wasm-attrs-pending"))))
(do
(api/update-shape-tiles)
(api/request-render "set-wasm-attrs")))))
(defn set-wasm-attrs!
[shape k v]
(let [shape (assoc shape k v)]
(api/use-shape (:id shape))
(let [pending (set-wasm-single-attr! shape k)]
;; TODO: set-wasm-attrs is called twice with every set
(if (and pending (seq pending))
(->> (rx/from pending)
(rx/mapcat identity)
(rx/reduce conj [])
(rx/subs!
(fn [_]
(api/update-shape-tiles)
(api/clear-drawing-cache)
(api/request-render "set-wasm-attrs-pending"))))
(do
(api/update-shape-tiles)
(api/request-render "set-wasm-attrs"))))))
(defn- impl-assoc
[self k v]
(when ^boolean shape/*wasm-sync*
(binding [shape/*wasm-sync* false]
(let [self (assoc self k v)]
(api/use-shape (:id self))
(let [pending (case k
:parent-id (api/set-parent-id v)
:type (api/set-shape-type v)
:bool-type (api/set-shape-bool-type v)
:selrect (api/set-shape-selrect v)
:show-content (if (= (:type self) :frame)
(api/set-shape-clip-content (not v))
(api/set-shape-clip-content false))
:rotation (api/set-shape-rotation v)
:transform (api/set-shape-transform v)
:fills (into [] (api/set-shape-fills v))
:strokes (into [] (api/set-shape-strokes v))
:blend-mode (api/set-shape-blend-mode v)
:opacity (api/set-shape-opacity v)
:hidden (api/set-shape-hidden v)
:shapes (api/set-shape-children v)
:blur (api/set-shape-blur v)
:shadow (api/set-shape-shadows v)
:constraints-h (api/set-constraints-h v)
:constraints-v (api/set-constraints-v v)
(set-wasm-attrs! self k v)))
:svg-attrs
(when (= (:type self) :path)
(api/set-shape-path-attrs v))
:masked-group
(when (and (= (:type self) :group) (:masked-group self))
(api/set-masked (:masked-group self)))
:content
(cond
(or (= (:type self) :path)
(= (:type self) :bool))
(api/set-shape-path-content v)
(= (:type self) :svg-raw)
(api/set-shape-svg-raw-content (api/get-static-markup self))
(= (:type self) :text)
(into [] (api/set-shape-text-content v)))
(:layout-item-margin
:layout-item-margin-type
:layout-item-h-sizing
:layout-item-v-sizing
:layout-item-max-h
:layout-item-min-h
:layout-item-max-w
:layout-item-min-w
:layout-item-absolute
:layout-item-z-index)
(api/set-layout-child self)
(:layout-grid-rows
:layout-grid-columns
:layout-grid-cells)
(when (ctl/grid-layout? self)
(api/set-grid-layout self))
(:layout
:layout-flex-dir
:layout-gap-type
:layout-gap
:layout-align-items
:layout-align-content
:layout-justify-items
:layout-justify-content
:layout-wrap-type
:layout-padding-type
:layout-padding)
(cond
(ctl/grid-layout? self)
(api/set-grid-layout self)
(ctl/flex-layout? self)
(api/set-flex-layout self))
nil)]
;; TODO: set-wasm-attrs is called twice with every set
(if (and pending (seq pending))
(->> (rx/from pending)
(rx/mapcat identity)
(rx/reduce conj [])
(rx/subs! (fn [_]
(api/update-shape-tiles)
(api/clear-drawing-cache)
(api/request-render "set-wasm-attrs-pending"))))
(do
(api/update-shape-tiles)
(api/request-render "set-wasm-attrs"))))))))
(defn- impl-assoc
[self k v]
(set-wasm-attrs self k v)
(case k
:id
(ShapeProxy. v
@ -228,7 +257,10 @@
(defn- impl-dissoc
[self k]
(set-wasm-attrs self k nil)
(when ^boolean shape/*wasm-sync*
(binding [shape/*wasm-sync* false]
(set-wasm-attrs! self k nil)))
(case k
:id
(ShapeProxy. nil