Apply modifiers changes into data

This commit is contained in:
alonso.torres 2025-04-29 14:18:38 +02:00
parent 7eab6a2f1d
commit 88e5209856
7 changed files with 361 additions and 163 deletions

View file

@ -371,8 +371,14 @@
"Given a new set of points transformed, set up the rectangle so it keeps
its properties. We adjust de x,y,width,height and create a custom transform"
[shape transform-mtx]
(if ^boolean (gmt/move? transform-mtx)
(cond
(nil? transform-mtx)
shape
^boolean (gmt/move? transform-mtx)
(apply-transform-move shape transform-mtx)
:else
(apply-transform-generic shape transform-mtx)))
(defn- update-group-viewbox

View file

@ -10,6 +10,7 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.geom.matrix :as gmt]
[app.common.geom.modifiers :as gm]
[app.common.geom.point :as gpt]
[app.common.geom.rect :as grc]
@ -484,9 +485,13 @@
[]
(keep
(fn [[id data]]
(when (ctm/has-geometry? (:modifiers data))
(if (ctm/has-geometry? (:modifiers data))
{:id id
:transform (ctm/modifiers->transform (:modifiers data))})))
:transform (ctm/modifiers->transform (:modifiers data))}
;; Unit matrix is used for reflowing
{:id id
:transform (gmt/matrix)})))
modif-tree))
(defn- extract-property-changes
@ -498,17 +503,11 @@
(filter (fn [[_ {:keys [type]}]]
(= type :change-property)))))
#_:clj-kondo/ignore
(defn set-wasm-modifiers
([modif-tree]
(set-wasm-modifiers modif-tree false))
([modif-tree ignore-constraints]
(set-wasm-modifiers modif-tree ignore-constraints false))
([modif-tree ignore-constraints ignore-snap-pixel]
(set-wasm-modifiers modif-tree ignore-constraints ignore-snap-pixel nil))
([modif-tree _ignore-constraints _ignore-snap-pixel _params]
[modif-tree & {:keys [ignore-constraints ignore-snap-pixel]
:or {ignore-constraints false ignore-snap-pixel false}
:as params}]
(ptk/reify ::set-wasm-modifiers
ptk/UpdateEvent
(update [_ state]
@ -531,10 +530,42 @@
(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 [geometry-entries (parse-geometry-modifiers modif-tree)]
(wasm.api/propagate-apply geometry-entries)))))))
#_:clj-kondo/ignore
(defn apply-wasm-modifiers
[modif-tree & {:keys [ignore-constraints ignore-snap-pixel snap-ignore-axis undo-group]
:or {ignore-constraints false ignore-snap-pixel false snap-ignore-axis nil undo-group nil}
:as params}]
(ptk/reify ::apply-wasm-modifiesr
ptk/WatchEvent
(watch [_ _ _]
(let [geometry-entries
(parse-geometry-modifiers modif-tree)
transforms
(into
{}
(map (fn [{:keys [id transform]}] [id transform]))
(wasm.api/propagate-modifiers geometry-entries))
ids
(into (set (keys modif-tree)) (keys transforms))
update-shape
(fn [shape]
(let [shape-id (dm/get-prop shape :id)
transform (get transforms shape-id)
modifiers (dm/get-in modif-tree [shape-id :modifiers])]
(-> shape
(gsh/apply-transform transform)
(ctm/apply-structure-modifiers modifiers))))]
(rx/of
(clear-local-transform)
(dwsh/update-shapes ids update-shape))))))
(defn set-selrect-transform
[modifiers]

View file

@ -29,6 +29,7 @@
[app.main.data.workspace.selection :as dwse]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.undo :as dwu]
[app.main.features :as features]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@ -101,13 +102,17 @@
(ptk/reify ::update-layout-positions
ptk/WatchEvent
(watch [_ state _]
(prn ">update-layout-positions")
(let [objects (dsh/lookup-page-objects state)
ids (->> ids (filter #(contains? objects %)))]
(if (d/not-empty? ids)
(let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))]
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modif-tree :stack-undo? true :undo-group undo-group))
(rx/of (dwm/apply-modifiers {:modifiers modif-tree
:stack-undo? true
:undo-group undo-group})))
:undo-group undo-group}))))
(rx/empty))))))
(defn initialize-shape-layout

View file

@ -24,6 +24,7 @@
[app.common.types.container :as ctn]
[app.common.types.modifiers :as ctm]
[app.common.types.shape-tree :as ctst]
[app.common.types.shape.attrs :refer [editable-attrs]]
[app.common.types.shape.layout :as ctl]
[app.common.uuid :as uuid]
[app.main.data.changes :as dch]
@ -279,28 +280,35 @@
modifiers-stream
(if (features/active-feature? state "render-wasm/v1")
(rx/merge
(->> resize-events-stream
(rx/mapcat
(fn [modifiers]
(let [modif-tree (dwm/create-modif-tree ids modifiers)]
(if (features/active-feature? state "render-wasm/v1")
(rx/of
(dwm/set-selrect-transform modifiers)
(dwm/set-wasm-modifiers modif-tree (contains? layout :scale-text)))
(rx/of (dwm/set-modifiers modif-tree (contains? layout :scale-text)))))))
(dwm/set-wasm-modifiers
modif-tree
:ignore-constraints (contains? layout :scale-text))))))
(rx/take-until stopper))
;; The last event we need to use the old method so the elements are correctly positioned until
;; all the logic is implemented in wasm
(if (features/active-feature? state "render-wasm/v1")
(->> resize-events-stream
(rx/take-until stopper)
(rx/last)
(rx/map #(dwm/apply-modifiers {:modifiers (dwm/create-modif-tree ids %)
:ignore-constraints (contains? layout :scale-text)})))
(rx/empty)))]
(rx/map
#(dwm/apply-wasm-modifiers
(dwm/create-modif-tree ids %)
:ignore-constraints (contains? layout :scale-text)))))
(->> resize-events-stream
(rx/mapcat
(fn [modifiers]
(let [modif-tree (dwm/create-modif-tree ids modifiers)]
(rx/of (dwm/set-modifiers modif-tree (contains? layout :scale-text))))))
(rx/take-until stopper)))]
(rx/concat
;; This initial stream waits for some pixels to be move before making the resize
@ -313,11 +321,13 @@
(rx/take-until stopper)
(rx/mapcat (fn [] modifiers-stream)))
(rx/of
(if (features/active-feature? state "render-wasm/v1")
(dwm/clear-local-transform)
(dwm/apply-modifiers))
(finish-transform))))))))
(rx/of
(finish-transform))
(rx/of
(dwm/apply-modifiers)
(finish-transform)))))))))
(defn trigger-bounding-box-cloaking
"Trigger the bounding box cloaking (with default timer of 1sec)
@ -368,7 +378,9 @@
(-> (dwm/build-modif-tree ids objects get-modifier)
(gm/set-objects-modifiers objects))]
(rx/of (dwm/apply-modifiers* objects modif-tree nil options)))))))
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modif-tree))
(rx/of (dwm/apply-modifiers* objects modif-tree nil options))))))))
(defn change-orientation
"Change orientation of shapes, from the sidebar options form.
@ -384,6 +396,8 @@
(ptk/reify ::change-orientation
ptk/UpdateEvent
(update [_ state]
(if (features/active-feature? state "render-wasm/v1")
state
(let [objects (dsh/lookup-page-objects state)
get-modifier
@ -393,14 +407,34 @@
(-> (dwm/build-modif-tree ids objects get-modifier)
(gm/set-objects-modifiers objects))]
(assoc state :workspace-modifiers modif-tree)))
(assoc state :workspace-modifiers modif-tree))))
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwm/apply-modifiers)))))
(watch [_ state _]
(if (features/active-feature? state "render-wasm/v1")
(let [objects (dsh/lookup-page-objects state)
get-modifier
(fn [shape] (ctm/change-orientation-modifiers shape orientation))
modif-tree
(-> (dwm/build-modif-tree ids objects get-modifier)
(gm/set-objects-modifiers objects))]
(rx/of (dwm/apply-wasm-modifiers modif-tree)))
(rx/of (dwm/apply-modifiers))))))
;; -- Rotate --------------------------------------------------------
(defn rotation-modifiers
[angle shapes center]
(into {}
(comp
(remove #(get % :blocked false))
(filter #(:rotation (get editable-attrs (:type %))))
(map #(vector (:id %) {:modifiers (ctm/rotation-modifiers % center angle)})))
shapes))
(defn start-rotate
"Enter mouse rotate mode, until mouse button is released."
[shapes]
@ -439,31 +473,51 @@
(fn [[pos mod? shift?]]
(calculate-angle pos mod? shift?)))
(rx/share))]
(if (features/active-feature? state "render-wasm/v1")
(rx/concat
(rx/merge
(->> angle-stream
(rx/map #(dwm/set-wasm-modifiers (rotation-modifiers % shapes group-center)))
(rx/take-until stopper))
(->> angle-stream
(rx/take-until stopper)
(rx/last)
(rx/map #(dwm/apply-wasm-modifiers (rotation-modifiers % shapes group-center)))))
(rx/of (finish-transform)))
(rx/concat
(rx/merge
(->> angle-stream
(rx/map
#(if (features/active-feature? state "render-wasm/v1")
(dwm/set-wasm-rotation-modifiers % shapes group-center)
(dwm/set-rotation-modifiers % shapes group-center)))
(rx/take-until stopper))
(if (features/active-feature? state "render-wasm/v1")
(->> angle-stream
(rx/take-until stopper)
(rx/last)
(rx/map #(dwm/set-rotation-modifiers % shapes group-center)))
(rx/empty)))
#(dwm/set-rotation-modifiers % shapes group-center))
(rx/take-until stopper)))
(rx/of (dwm/apply-modifiers)
(finish-transform)))))))
(finish-transform))))))))
(defn increase-rotation
"Rotate shapes a fixed angle, from a keyboard action."
([ids rotation]
(increase-rotation ids rotation nil))
([ids rotation params & {:as options}]
([ids rotation {:keys [center delta?] :as params} & {:as options}]
(ptk/reify ::increase-rotation
ptk/WatchEvent
(watch [_ state _]
(if (features/active-feature? state "render-wasm/v1")
(let [objects (dsh/lookup-page-objects state)
get-modifier
(fn [shape]
(let [delta (if delta? rotation (- rotation (:rotation shape)))
center (or center (gsh/shape->center shape))]
(ctm/rotation-modifiers shape center delta)))
modif-tree
(dwm/build-modif-tree ids objects get-modifier)]
(rx/of (dwm/apply-wasm-modifiers modif-tree)))
(let [page-id (or (:page-id options)
(:current-page-id state))
objects (dsh/lookup-page-objects state page-id)
@ -471,7 +525,7 @@
options (assoc options :page-id page-id)]
(rx/concat
(rx/of (dwm/set-delta-rotation-modifiers rotation shapes (assoc params :page-id page-id)))
(rx/of (dwm/apply-modifiers options))))))))
(rx/of (dwm/apply-modifiers options)))))))))
;; -- Move ----------------------------------------------------------
(declare start-move)
@ -648,22 +702,47 @@
snap-ignore-axis])))
(rx/share))]
(if (features/active-feature? state "render-wasm/v1")
(rx/merge
;; Temporary modifiers stream
(->> modifiers-stream
(rx/map
(fn [[modifiers snap-ignore-axis]]
(if (features/active-feature? state "render-wasm/v1")
(dwm/set-wasm-modifiers modifiers false false {:snap-ignore-axis snap-ignore-axis})
(dwm/set-modifiers modifiers false false {:snap-ignore-axis snap-ignore-axis})))))
(dwm/set-wasm-modifiers modifiers :snap-ignore-axis snap-ignore-axis))))
(if (features/active-feature? state "render-wasm/v1")
(->> modifiers-stream
(rx/last)
(rx/map
(fn [[modifiers snap-ignore-axis]]
(dwm/apply-wasm-modifiers modifiers :snap-ignore-axis snap-ignore-axis))))
(->> move-stream
(rx/with-latest-from ms/mouse-position-alt)
(rx/filter (fn [[_ alt?]] alt?))
(rx/take 1)
(rx/mapcat
(fn [[_ alt?]]
(if (and (not duplicate-move-started?) alt?)
(rx/of (start-move-duplicate from-position)
(dws/duplicate-selected false true))
(rx/empty)))))
;; Last event will write the modifiers creating the changes
(->> move-stream
(rx/last)
(rx/mapcat
(fn [[_ target-frame drop-index drop-cell]]
(let [undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id)
;; (dwm/apply-modifiers {:undo-transation? false})
(move-shapes-to-frame ids target-frame drop-index drop-cell)
(finish-transform)
(dwu/commit-undo-transaction undo-id)))))))
(rx/merge
(->> modifiers-stream
(rx/map
(fn [[modifiers snap-ignore-axis]]
(dwm/set-modifiers modifiers false false {:snap-ignore-axis snap-ignore-axis}))))
(rx/empty))
(->> move-stream
(rx/with-latest-from ms/mouse-position-alt)
@ -689,7 +768,7 @@
(dwm/apply-modifiers {:undo-transation? false})
(move-shapes-to-frame ids target-frame drop-index drop-cell)
(finish-transform)
(dwu/commit-undo-transaction undo-id))))))))))))))
(dwu/commit-undo-transaction undo-id)))))))))))))))
(def valid-directions
#{:up :down :right :left})
@ -828,6 +907,23 @@
scale (if shift? (gpt/point (or (:big nudge) 10)) (gpt/point (or (:small nudge) 1)))
mov-vec (gpt/multiply (get-displacement direction) scale)]
(if (features/active-feature? state "render-wasm/v1")
(let [modif-stream
(->> move-events
(rx/scan #(gpt/add %1 mov-vec) (gpt/point 0 0))
(rx/map #(dwm/create-modif-tree selected (ctm/move-modifiers %)))
(rx/take-until stopper))]
(rx/concat
(rx/merge
(rx/of (nudge-selected-shapes direction shift?))
(->> modif-stream
(rx/map #(dwm/set-wasm-modifiers % {:ignore-snap-pixel true})))
(->> modif-stream
(rx/last)
(rx/map #(dwm/apply-wasm-modifiers % {:ignore-snap-pixel true}))))
(rx/of (finish-transform))))
(rx/concat
(rx/merge
(->> move-events
@ -838,7 +934,7 @@
(rx/of (nudge-selected-shapes direction shift?)))
(rx/of (dwm/apply-modifiers)
(finish-transform))))
(finish-transform)))))
(rx/empty))))))
(defn move-selected
@ -896,11 +992,18 @@
delta (calculate-delta position bbox frame)
modifiers (dwm/create-modif-tree [id] (ctm/move-modifiers delta))]
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modifiers
{:ignore-constraints false
:ignore-touched (:ignore-touched options)
:ignore-snap-pixel true}))
(rx/of (dwm/apply-modifiers {:modifiers modifiers
:page-id page-id
:ignore-constraints false
:ignore-touched (:ignore-touched options)
:ignore-snap-pixel true})))))))
:ignore-snap-pixel true}))))))))
(defn position-shapes
[shapes]
@ -920,9 +1023,14 @@
opos (-> oshape :points first gpt/point)]
(ctm/move-modifiers (gpt/subtract opos cpos)))))]
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modif-tree
{:ignore-constraints false
:ignore-snap-pixel true}))
(rx/of (dwm/apply-modifiers {:modifiers modif-tree
:ignore-constraints false
:ignore-snap-pixel true}))))))
:ignore-snap-pixel true})))))))
(defn- cleanup-invalid-moving-shapes [ids objects frame-id]
(let [lookup (d/getf objects)
@ -1000,7 +1108,11 @@
selrect (gsh/shapes->rect shapes)
center (grc/rect->center selrect)
modifiers (dwm/create-modif-tree selected (ctm/resize-modifiers (gpt/point -1.0 1.0) center))]
(rx/of (dwm/apply-modifiers {:modifiers modifiers :ignore-snap-pixel true})))))))
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modifiers {:ignore-snap-pixel true}))
(rx/of (dwm/apply-modifiers {:modifiers modifiers :ignore-snap-pixel true}))))))))
(defn flip-vertical-selected
([]
@ -1018,7 +1130,9 @@
selrect (gsh/shapes->rect shapes)
center (grc/rect->center selrect)
modifiers (dwm/create-modif-tree selected (ctm/resize-modifiers (gpt/point 1.0 -1.0) center))]
(rx/of (dwm/apply-modifiers {:modifiers modifiers :ignore-snap-pixel true})))))))
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modifiers {:ignore-snap-pixel true}))
(rx/of (dwm/apply-modifiers {:modifiers modifiers :ignore-snap-pixel true}))))))))
(defn fit-layout-modifiers
[objects frame]
@ -1051,4 +1165,7 @@
(some? new-modif)
(assoc (:id frame) {:modifiers new-modif})))))
{}))]
(rx/of (dwm/apply-modifiers {:modifiers modifiers :undo-group undo-group}))))))
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modifiers {:undo-group undo-group}))
(rx/of (dwm/apply-modifiers {:modifiers modifiers :undo-group undo-group})))))))

View file

@ -767,6 +767,7 @@
(defn propagate-modifiers
[entries]
(when (d/not-empty? entries)
(let [offset (mem/alloc-bytes-32 (modifier-get-entries-size entries))
heapf32 (mem/get-heap-f32)
heapu32 (mem/get-heap-u32)]
@ -788,7 +789,24 @@
(mapv #(dr/heap32->entry heapu32 heapf32 (mem/ptr8->ptr32 (+ result-offset 4 (* % MODIFIER-ENTRY-SIZE))))))]
(h/call wasm/internal-module "_free_bytes")
result)))
result))))
(defn propagate-apply
[entries]
(when (d/not-empty? entries)
(let [offset (mem/alloc-bytes-32 (modifier-get-entries-size entries))
heapf32 (mem/get-heap-f32)
heapu32 (mem/get-heap-u32)]
(loop [entries (seq entries)
current-offset offset]
(when-not (empty? entries)
(let [{:keys [id transform]} (first entries)]
(sr/heapu32-set-uuid id heapu32 current-offset)
(sr/heapf32-set-matrix transform heapf32 (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-TRANSFORM-OFFSET)))
(recur (rest entries) (+ current-offset (mem/ptr8->ptr32 MODIFIER-ENTRY-SIZE))))))
(h/call wasm/internal-module "_propagate_apply")
(request-render "set-modifiers"))))
(defn set-canvas-background
[background]

View file

@ -395,6 +395,27 @@ pub extern "C" fn propagate_modifiers() -> *mut u8 {
})
}
#[no_mangle]
pub extern "C" fn propagate_apply() {
let bytes = mem::bytes();
let entries: Vec<_> = bytes
.chunks(size_of::<<TransformEntry as SerializableResult>::BytesType>())
.map(|data| TransformEntry::from_bytes(data.try_into().unwrap()))
.collect();
with_state!(state, {
let result = shapes::propagate_modifiers(state, entries);
for entry in result {
state.modifiers.insert(entry.id, entry.transform);
}
state.rebuild_modifier_tiles();
});
mem::free_bytes();
}
#[no_mangle]
pub extern "C" fn set_structure_modifiers() {
let bytes = mem::bytes();

View file

@ -334,9 +334,9 @@ fn set_fr_value(
layout_size: f32,
) {
let tot_gap: f32 = if column {
layout_data.column_gap * (tracks.len() - 1) as f32
layout_data.column_gap * (tracks.len() as f32 - 1.0)
} else {
layout_data.row_gap * (tracks.len() - 1) as f32
layout_data.row_gap * (tracks.len() as f32 - 1.0)
};
// Total size already used