0
Fork 0
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:
alonso.torres 2020-04-24 09:33:24 +02:00
parent 8886db7453
commit e6855fd9b3
5 changed files with 91 additions and 196 deletions

View file

@ -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

View file

@ -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))))))

View file

@ -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

View file

@ -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

View file

@ -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)