mirror of
https://github.com/penpot/penpot.git
synced 2025-04-06 20:11:29 -05:00
♻️ Refactor to transforms actions
This commit is contained in:
parent
8886db7453
commit
e6855fd9b3
5 changed files with 91 additions and 196 deletions
|
@ -1730,8 +1730,8 @@
|
|||
(def start-move-selected transforms/start-move-selected)
|
||||
(def move-selected transforms/move-selected)
|
||||
|
||||
(def apply-displacement-in-bulk transforms/apply-displacement-in-bulk)
|
||||
(def materialize-displacement-in-bulk transforms/materialize-displacement-in-bulk)
|
||||
(def set-modifiers transforms/set-modifiers)
|
||||
(def apply-modifiers transforms/apply-modifiers)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Shortcuts
|
||||
|
|
|
@ -14,20 +14,14 @@
|
|||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.main.data.helpers :as helpers]
|
||||
[uxbox.main.data.workspace.common :refer [IBatchedChange IUpdateGroup] :as common]))
|
||||
;; -- Specs
|
||||
|
||||
(s/def ::set-of-uuid
|
||||
(s/every uuid? :kind set?))
|
||||
|
||||
;; -- Declarations
|
||||
|
||||
(declare assoc-resize-modifier-in-bulk)
|
||||
(declare apply-displacement-in-bulk)
|
||||
(declare apply-rotation)
|
||||
(declare set-modifiers)
|
||||
(declare set-rotation)
|
||||
(declare apply-modifiers)
|
||||
|
||||
(declare materialize-resize-modifier-in-bulk)
|
||||
(declare materialize-displacement-in-bulk)
|
||||
(declare materialize-rotation)
|
||||
;; -- Helpers
|
||||
|
||||
(defn- apply-zoom
|
||||
[point]
|
||||
|
@ -71,7 +65,7 @@
|
|||
|
||||
;; -- RESIZE
|
||||
(defn start-resize
|
||||
[vid ids shape objects]
|
||||
[handler ids shape objects]
|
||||
(letfn [(resize [shape initial [point lock?]]
|
||||
(let [frame (get objects (:frame-id shape))
|
||||
{:keys [width height rotation]} shape
|
||||
|
@ -80,7 +74,7 @@
|
|||
shapev (-> (gpt/point width height))
|
||||
|
||||
;; Vector modifiers depending on the handler
|
||||
handler-modif (let [[x y] (handler-modifiers vid)] (gpt/point x y))
|
||||
handler-modif (let [[x y] (handler-modifiers handler)] (gpt/point x y))
|
||||
|
||||
;; Difference between the origin point in the coordinate system of the rotation
|
||||
deltav (-> (gpt/subtract point initial)
|
||||
|
@ -94,13 +88,13 @@
|
|||
shape-transform-inverse (:transform-inverse shape (gmt/matrix))
|
||||
|
||||
;; Resize origin point given the selected handler
|
||||
origin (-> (handler-resize-origin shape vid)
|
||||
origin (-> (handler-resize-origin shape handler)
|
||||
(geom/transform-shape-point shape shape-transform))]
|
||||
|
||||
(rx/of (assoc-resize-modifier-in-bulk ids {:resize-modifier-vector scalev
|
||||
:resize-modifier-origin origin
|
||||
:resize-modifier-transform shape-transform
|
||||
:resize-modifier-transform-inverse shape-transform-inverse}))))
|
||||
(rx/of (set-modifiers ids {:resize-vector scalev
|
||||
:resize-origin origin
|
||||
:resize-transform shape-transform
|
||||
:resize-transform-inverse shape-transform-inverse}))))
|
||||
|
||||
;; Unifies the instantaneous proportion lock modifier
|
||||
;; activated by Ctrl key and the shapes own proportion
|
||||
|
@ -130,64 +124,7 @@
|
|||
(rx/map normalize-proportion-lock)
|
||||
(rx/mapcat (partial resize shape initial))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (materialize-resize-modifier-in-bulk ids))))))))
|
||||
|
||||
(defn assoc-resize-modifier-in-bulk
|
||||
[ids modifiers]
|
||||
(us/verify ::set-of-uuid ids)
|
||||
;; (us/verify gmt/matrix? resize-matrix)
|
||||
;; (us/verify gmt/matrix? displacement-matrix)
|
||||
(ptk/reify ::assoc-resize-modifier-in-bulk
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
rfn #(-> %1
|
||||
(update-in [:workspace-data page-id :objects %2] (fn [item] (merge item modifiers))))
|
||||
|
||||
not-frame-id? (fn [shape-id] (not (= :frame (:type (get objects shape-id)))))
|
||||
|
||||
;; TODO: REMOVE FRAMES FROM IDS TO PROPAGATE
|
||||
ids-with-children (concat ids (mapcat #(helpers/get-children % objects) (filter not-frame-id? ids)))]
|
||||
(reduce rfn state ids-with-children)))))
|
||||
|
||||
(defn materialize-resize-modifier-in-bulk
|
||||
[ids]
|
||||
(ptk/reify ::materialize-resize-modifier-in-bulk
|
||||
|
||||
IUpdateGroup
|
||||
(get-ids [_] ids)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
|
||||
;; Updates the resize data for a single shape
|
||||
materialize-shape
|
||||
(fn [state id]
|
||||
(update-in state [:workspace-data page-id :objects id] geom/transform-shape))
|
||||
|
||||
;; Applies materialize-shape over shape children
|
||||
materialize-children
|
||||
(fn [state id]
|
||||
(reduce materialize-shape state (helpers/get-children id objects)))
|
||||
|
||||
;; For each shape makes permanent the displacemnt
|
||||
update-shapes
|
||||
(fn [state id]
|
||||
(let [shape (-> (get objects id) geom/transform-shape)]
|
||||
(-> state
|
||||
(materialize-shape id)
|
||||
(materialize-children id))))]
|
||||
|
||||
(reduce update-shapes state ids)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(rx/of (common/diff-and-commit-changes page-id)
|
||||
(common/rehash-shape-frame-relationship ids))))))
|
||||
(rx/of (apply-modifiers ids))))))))
|
||||
|
||||
|
||||
;; -- ROTATE
|
||||
|
@ -219,12 +156,9 @@
|
|||
(rx/with-latest vector ms/mouse-position-ctrl)
|
||||
(rx/map (fn [[pos ctrl?]]
|
||||
(let [delta-angle (calculate-angle pos ctrl?)]
|
||||
(apply-rotation delta-angle shapes))))
|
||||
|
||||
|
||||
(set-rotation delta-angle shapes))))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (materialize-rotation shapes))
|
||||
)))))
|
||||
(rx/of (apply-modifiers (map :id shapes))))))))
|
||||
|
||||
;; -- MOVE
|
||||
|
||||
|
@ -235,13 +169,16 @@
|
|||
(let [selected (get-in state [:workspace-local :selected])
|
||||
stoper (rx/filter ms/mouse-up? stream)
|
||||
zero-point? #(= % (gpt/point 0 0))
|
||||
initial (apply-zoom @ms/mouse-position)
|
||||
position @ms/mouse-position]
|
||||
(rx/concat
|
||||
(->> (ms/mouse-position-deltas position)
|
||||
(->> ms/mouse-position
|
||||
(rx/map apply-zoom)
|
||||
(rx/filter (complement zero-point?))
|
||||
(rx/map #(apply-displacement-in-bulk selected %))
|
||||
(rx/map #(gpt/subtract % initial))
|
||||
(rx/map #(set-modifiers selected {:displacement (gmt/translate-matrix %)}))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (materialize-displacement-in-bulk selected)))))))
|
||||
(rx/of (apply-modifiers selected)))))))
|
||||
|
||||
(defn- get-displacement-with-grid
|
||||
"Retrieve the correct displacement delta point for the
|
||||
|
@ -283,81 +220,40 @@
|
|||
displacement (if align?
|
||||
(get-displacement-with-grid shape direction options)
|
||||
(get-displacement shape direction))]
|
||||
(rx/of (apply-displacement-in-bulk selected displacement)
|
||||
(materialize-displacement-in-bulk selected))))))
|
||||
(rx/of (set-modifiers selected displacement)
|
||||
(apply-modifiers selected))))))
|
||||
|
||||
|
||||
;; -- Apply modifiers
|
||||
(defn apply-displacement-in-bulk
|
||||
"Apply the same displacement delta to all shapes identified by the set
|
||||
if ids."
|
||||
[ids delta]
|
||||
(us/verify ::set-of-uuid ids)
|
||||
(us/verify gpt/point? delta)
|
||||
(ptk/reify ::apply-displacement-in-bulk
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
rfn (fn [state id]
|
||||
(let [path [:workspace-data page-id :objects id]
|
||||
shape (get-in state path)
|
||||
prev (:displacement-modifier shape (gmt/matrix))
|
||||
curr (gmt/translate prev delta)]
|
||||
(update-in state path #(assoc % :displacement-modifier curr))))
|
||||
ids-with-children (concat ids (mapcat #(helpers/get-children % objects) ids))]
|
||||
(reduce rfn state ids-with-children)))))
|
||||
|
||||
(defn set-modifiers
|
||||
([ids modifiers] (set-modifiers ids modifiers true))
|
||||
([ids modifiers recurse-frames?]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::set-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
not-frame-id? (fn [shape-id]
|
||||
(let [shape (get objects shape-id)]
|
||||
(or recurse-frames? (not (= :frame (:type shape))))))
|
||||
|
||||
(defn materialize-displacement-in-bulk
|
||||
[ids]
|
||||
(ptk/reify ::materialize-displacement-in-bulk
|
||||
IBatchedChange
|
||||
|
||||
IUpdateGroup
|
||||
(get-ids [_] ids)
|
||||
;; ID's + Children but remove frame children if the flag is set to false
|
||||
ids-with-children (concat ids (mapcat #(helpers/get-children % objects) (filter not-frame-id? ids)))
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
;; For each shape updates the modifiers given as arguments
|
||||
update-shape (fn [state shape-id]
|
||||
(update-in
|
||||
state
|
||||
[:workspace-data page-id :objects shape-id :modifiers]
|
||||
#(merge % modifiers)))]
|
||||
(reduce update-shape state ids-with-children))))))
|
||||
|
||||
;; Updates the displacement data for a single shape
|
||||
materialize-shape
|
||||
(fn [state id mtx]
|
||||
(update-in
|
||||
state
|
||||
[:workspace-data page-id :objects id]
|
||||
#(-> %
|
||||
(dissoc :displacement-modifier)
|
||||
(geom/transform mtx))))
|
||||
|
||||
;; Applies materialize-shape over shape children
|
||||
materialize-children
|
||||
(fn [state id mtx]
|
||||
(reduce #(materialize-shape %1 %2 mtx) state (helpers/get-children id objects)))
|
||||
|
||||
;; For each shape makes permanent the resize
|
||||
update-shapes
|
||||
(fn [state id]
|
||||
(let [shape (get objects id)
|
||||
mtx (:displacement-modifier shape (gmt/matrix))]
|
||||
(-> state
|
||||
(materialize-shape id mtx)
|
||||
(materialize-children id mtx))))]
|
||||
|
||||
(as-> state $
|
||||
(reduce update-shapes $ ids))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(rx/of (common/diff-and-commit-changes page-id)
|
||||
(common/rehash-shape-frame-relationship ids))))))
|
||||
|
||||
(defn apply-rotation
|
||||
;; Set-rotation is custom because applies different modifiers to each shape adjusting their position
|
||||
(defn set-rotation
|
||||
[delta-rotation shapes]
|
||||
(ptk/reify ::apply-rotation
|
||||
(ptk/reify ::set-rotation
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)]
|
||||
|
@ -369,11 +265,11 @@
|
|||
|
||||
(rotate-shape [state angle shape center]
|
||||
(let [objects (get-in state [:workspace-data page-id :objects])
|
||||
path [:workspace-data page-id :objects (:id shape)]
|
||||
path [:workspace-data page-id :objects (:id shape) :modifiers]
|
||||
ds (calculate-displacement shape angle center)]
|
||||
(-> state
|
||||
(assoc-in (conj path :rotation-modifier) angle)
|
||||
(assoc-in (conj path :displacement-modifier) ds))))
|
||||
(assoc-in (conj path :rotation) angle)
|
||||
(assoc-in (conj path :displacement) ds))))
|
||||
|
||||
|
||||
(rotate-around-center [state angle center shapes]
|
||||
|
@ -386,25 +282,30 @@
|
|||
shapes (concat shapes (mapcat get-children shapes))]
|
||||
(rotate-around-center state delta-rotation center shapes)))))))
|
||||
|
||||
(defn materialize-rotation
|
||||
[shapes]
|
||||
(ptk/reify ::materialize-rotation
|
||||
IBatchedChange
|
||||
(defn apply-modifiers
|
||||
[ids]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::apply-modifiers
|
||||
IUpdateGroup
|
||||
(get-ids [_] (map :id shapes))
|
||||
(get-ids [_] ids)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(letfn
|
||||
[(materialize-shape [state shape]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
path [:workspace-data page-id :objects (:id shape)]]
|
||||
(as-> state $
|
||||
(update-in $ path geom/transform-shape)
|
||||
(reduce materialize-shape $ (map #(get objects %) (:shapes shape))))))]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data page-id :objects])
|
||||
|
||||
(reduce materialize-shape state shapes)))))
|
||||
;; ID's + Children
|
||||
ids-with-children (concat ids (mapcat #(helpers/get-children % objects) ids))
|
||||
|
||||
;; For each shape applies the modifiers by transforming the objects
|
||||
update-shape
|
||||
(fn [state shape-id]
|
||||
(update-in state [:workspace-data page-id :objects shape-id] geom/transform-shape))]
|
||||
|
||||
(reduce update-shape state ids-with-children)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(rx/of (common/diff-and-commit-changes page-id)
|
||||
(common/rehash-shape-frame-relationship ids))))))
|
||||
|
|
|
@ -679,12 +679,13 @@
|
|||
|
||||
(defn- transform-apply-modifiers
|
||||
[shape]
|
||||
(let [ds-modifier (:displacement-modifier shape (gmt/matrix))
|
||||
resize (:resize-modifier-vector shape (gpt/point 1 1))
|
||||
origin (:resize-modifier-origin shape (gpt/point 0 0))
|
||||
resize-transform (:resize-modifier-transform shape (gmt/matrix))
|
||||
resize-transform-inverse (:resize-modifier-transform-inverse shape (gmt/matrix))
|
||||
rt-modif (:rotation-modifier shape 0)
|
||||
(let [modifiers (:modifiers shape)
|
||||
ds-modifier (:displacement modifiers (gmt/matrix))
|
||||
resize (:resize-vector modifiers (gpt/point 1 1))
|
||||
origin (:resize-origin modifiers (gpt/point 0 0))
|
||||
resize-transform (:resize-transform modifiers (gmt/matrix))
|
||||
resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix))
|
||||
rt-modif (:rotation modifiers 0)
|
||||
|
||||
shape (-> shape
|
||||
(transform ds-modifier))
|
||||
|
@ -734,15 +735,6 @@
|
|||
(translate-to-frame frame)
|
||||
(shape->rect-shape)))
|
||||
|
||||
(defn dissoc-modifiers [shape]
|
||||
(-> shape
|
||||
(dissoc :rotation-modifier)
|
||||
(dissoc :displacement-modifier)
|
||||
(dissoc :resize-modifier)
|
||||
(dissoc :resize-modifier-vector)
|
||||
(dissoc :resize-modifier-origin)
|
||||
(dissoc :resize-modifier-rotation)))
|
||||
|
||||
(defn transform-rect-shape
|
||||
[shape]
|
||||
(let [;; Apply modifiers to the rect as a path so we have the end shape expected
|
||||
|
@ -813,8 +805,8 @@
|
|||
(transform-rect-shape shape))]
|
||||
(-> new-shape
|
||||
(translate-to-frame frame)
|
||||
(update :rotation #(mod (+ % (:rotation-modifier shape)) 360))
|
||||
(dissoc-modifiers)))))
|
||||
(update :rotation #(mod (+ % (get-in shape [:modifiers :rotation] 0)) 360))
|
||||
(dissoc :modifiers)))))
|
||||
|
||||
|
||||
(defn transform-matrix
|
||||
|
|
|
@ -123,9 +123,9 @@
|
|||
scalev (gpt/divide (gpt/add shapev deltav) shapev)]
|
||||
|
||||
(-> shape
|
||||
(assoc :resize-modifier-vector scalev)
|
||||
(assoc :resize-modifier-origin (gpt/point x y))
|
||||
(assoc :resize-modifier-rotation 0))))
|
||||
(assoc-in [:modifiers :resize-vector] scalev)
|
||||
(assoc-in [:modifiers :resize-origin] (gpt/point x y))
|
||||
(assoc-in [:modifiers :resize-rotation] 0))))
|
||||
|
||||
(update-drawing [state initial point lock?]
|
||||
(update-in state [:workspace-local :drawing] resize-shape initial point lock?))]
|
||||
|
@ -273,11 +273,11 @@
|
|||
(rx/of dw/clear-drawing)
|
||||
(when (::initialized? shape)
|
||||
(let [shape (-> shape
|
||||
(geom/transform-shape)
|
||||
(dissoc shape ::initialized?))]
|
||||
;; Add & select the created shape to the workspace
|
||||
(rx/of dw/deselect-all
|
||||
(dw/add-shape shape)))))))))
|
||||
(geom/transform-shape)
|
||||
(dissoc shape ::initialized?))]
|
||||
;; Add & select the created shape to the workspace
|
||||
(rx/of dw/deselect-all
|
||||
(dw/add-shape shape)))))))))
|
||||
|
||||
(def close-drawing-path
|
||||
(ptk/reify ::close-drawing-path
|
||||
|
|
|
@ -64,8 +64,10 @@
|
|||
delta (if (= attr :x)
|
||||
(gpt/point (math/neg (- pval cval)) 0)
|
||||
(gpt/point 0 (math/neg (- pval cval))))]
|
||||
(st/emit! (udw/apply-displacement-in-bulk #{(:id shape)} delta)
|
||||
(udw/materialize-displacement-in-bulk #{(:id shape)}))))
|
||||
|
||||
;; TODO: Change so not apply the modifiers until blur
|
||||
(st/emit! (udw/set-modifiers #{(:id shape)} {:displacement delta})
|
||||
(udw/apply-modifiers #{(:id shape)}))))
|
||||
|
||||
on-width-change #(on-size-change % :width)
|
||||
on-height-change #(on-size-change % :height)
|
||||
|
|
Loading…
Add table
Reference in a new issue