mirror of
https://github.com/penpot/penpot.git
synced 2025-02-03 04:49:03 -05:00
⚡ Add performance improvements to start-resize
This commit is contained in:
parent
1465ed3607
commit
36b5ca7313
1 changed files with 125 additions and 86 deletions
|
@ -45,17 +45,19 @@
|
||||||
;; For each of the 8 handlers gives the multiplier for resize
|
;; For each of the 8 handlers gives the multiplier for resize
|
||||||
;; for example, right will only grow in the x coordinate and left
|
;; for example, right will only grow in the x coordinate and left
|
||||||
;; will grow in the inverse of the x coordinate
|
;; will grow in the inverse of the x coordinate
|
||||||
(def ^:private handler-multipliers
|
(defn get-handler-multiplier
|
||||||
{:right [1 0]
|
[handler]
|
||||||
:bottom [0 1]
|
(case handler
|
||||||
:left [-1 0]
|
:right (gpt/point 1 0)
|
||||||
:top [0 -1]
|
:bottom (gpt/point 0 1)
|
||||||
:top-right [1 -1]
|
:left (gpt/point -1 0)
|
||||||
:top-left [-1 -1]
|
:top (gpt/point 0 -1)
|
||||||
:bottom-right [1 1]
|
:top-right (gpt/point 1 -1)
|
||||||
:bottom-left [-1 1]})
|
:top-left (gpt/point -1 -1)
|
||||||
|
:bottom-right (gpt/point 1 1)
|
||||||
|
:bottom-left (gpt/point -1 1)))
|
||||||
|
|
||||||
(defn- handler-resize-origin
|
(defn- get-handler-resize-origin
|
||||||
"Given a handler, return the coordinate origin for resizes.
|
"Given a handler, return the coordinate origin for resizes.
|
||||||
This is the opposite of the handler so for right we want the
|
This is the opposite of the handler so for right we want the
|
||||||
left side as origin of the resize.
|
left side as origin of the resize.
|
||||||
|
@ -64,39 +66,66 @@
|
||||||
mx, my => middle x/y
|
mx, my => middle x/y
|
||||||
ex, ey => end x/y
|
ex, ey => end x/y
|
||||||
"
|
"
|
||||||
[{sx :x sy :y :keys [width height]} handler]
|
[selrect handler]
|
||||||
(let [mx (+ sx (/ width 2))
|
(let [sx (dm/get-prop selrect :x)
|
||||||
my (+ sy (/ height 2))
|
sy (dm/get-prop selrect :y)
|
||||||
ex (+ sx width)
|
width (dm/get-prop selrect :width)
|
||||||
ey (+ sy height)
|
height (dm/get-prop selrect :height)
|
||||||
|
mx (+ sx (/ width 2))
|
||||||
[x y] (case handler
|
my (+ sy (/ height 2))
|
||||||
:right [sx my]
|
ex (+ sx width)
|
||||||
:bottom [mx sy]
|
ey (+ sy height)]
|
||||||
:left [ex my]
|
(case handler
|
||||||
:top [mx ey]
|
:right (gpt/point sx my)
|
||||||
:top-right [sx ey]
|
:bottom (gpt/point mx sy)
|
||||||
:top-left [ex ey]
|
:left (gpt/point ex my)
|
||||||
:bottom-right [sx sy]
|
:top (gpt/point mx ey)
|
||||||
:bottom-left [ex sy])]
|
:top-right (gpt/point sx ey)
|
||||||
(gpt/point x y)))
|
:top-left (gpt/point ex ey)
|
||||||
|
:bottom-right (gpt/point sx sy)
|
||||||
|
:bottom-left (gpt/point ex sy))))
|
||||||
|
|
||||||
(defn- fix-init-point
|
(defn- fix-init-point
|
||||||
"Fix the initial point so the resizes are accurate"
|
"Fix the initial point so the resizes are accurate"
|
||||||
[initial handler shape]
|
[initial handler shape]
|
||||||
(let [{:keys [x y width height]} (:selrect shape)]
|
(let [selrect (dm/get-prop shape :selrect)
|
||||||
(cond-> initial
|
x (dm/get-prop selrect :x)
|
||||||
(contains? #{:left :top-left :bottom-left} handler)
|
y (dm/get-prop selrect :y)
|
||||||
(assoc :x x)
|
width (dm/get-prop selrect :width)
|
||||||
|
height (dm/get-prop selrect :height)]
|
||||||
|
|
||||||
(contains? #{:right :top-right :bottom-right} handler)
|
(case handler
|
||||||
(assoc :x (+ x width))
|
:left
|
||||||
|
(assoc initial :x x)
|
||||||
|
|
||||||
(contains? #{:top :top-right :top-left} handler)
|
:top
|
||||||
(assoc :y y)
|
(assoc initial :y y)
|
||||||
|
|
||||||
(contains? #{:bottom :bottom-right :bottom-left} handler)
|
:top-left
|
||||||
(assoc :y (+ y height)))))
|
(-> initial
|
||||||
|
(assoc :x x)
|
||||||
|
(assoc :y y))
|
||||||
|
|
||||||
|
:bottom-left
|
||||||
|
(-> initial
|
||||||
|
(assoc :x x)
|
||||||
|
(assoc :y (+ y height)))
|
||||||
|
|
||||||
|
:right
|
||||||
|
(assoc initial :x (+ x width))
|
||||||
|
|
||||||
|
:top-right
|
||||||
|
(-> initial
|
||||||
|
(assoc :x (+ x width))
|
||||||
|
(assoc :y y))
|
||||||
|
|
||||||
|
:bottom-right
|
||||||
|
(-> initial
|
||||||
|
(assoc :x (+ x width))
|
||||||
|
(assoc :y (+ y height)))
|
||||||
|
|
||||||
|
:bottom
|
||||||
|
(assoc initial :y (+ y height)))))
|
||||||
|
|
||||||
(defn finish-transform []
|
(defn finish-transform []
|
||||||
(ptk/reify ::finish-transform
|
(ptk/reify ::finish-transform
|
||||||
|
@ -104,16 +133,16 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(update state :workspace-local dissoc :transform :duplicate-move-started? false))))
|
(update state :workspace-local dissoc :transform :duplicate-move-started? false))))
|
||||||
|
|
||||||
|
|
||||||
;; -- Resize --------------------------------------------------------
|
;; -- Resize --------------------------------------------------------
|
||||||
|
|
||||||
(defn start-resize
|
(defn start-resize
|
||||||
"Enter mouse resize mode, until mouse button is released."
|
"Enter mouse resize mode, until mouse button is released."
|
||||||
[handler ids shape]
|
[handler ids shape]
|
||||||
(letfn [(resize
|
(letfn [(resize [shape initial layout [point lock? center? point-snap]]
|
||||||
[shape initial layout [point lock? center? point-snap]]
|
(let [selrect (dm/get-prop shape :selrect)
|
||||||
(let [{:keys [width height]} (:selrect shape)
|
width (dm/get-prop selrect :width)
|
||||||
{:keys [rotation]} shape
|
height (dm/get-prop selrect :height)
|
||||||
|
rotation (dm/get-prop shape :rotation)
|
||||||
|
|
||||||
shape-center (gsh/shape->center shape)
|
shape-center (gsh/shape->center shape)
|
||||||
shape-transform (:transform shape)
|
shape-transform (:transform shape)
|
||||||
|
@ -129,78 +158,84 @@
|
||||||
|
|
||||||
shapev (-> (gpt/point width height))
|
shapev (-> (gpt/point width height))
|
||||||
|
|
||||||
scale-text (:scale-text layout)
|
scale-text (contains? layout :scale-text)
|
||||||
|
|
||||||
;; Force lock if the scale text mode is active
|
;; Force lock if the scale text mode is active
|
||||||
lock? (or lock? scale-text)
|
lock? (or ^boolean lock?
|
||||||
|
^boolean scale-text)
|
||||||
|
|
||||||
;; Vector modifiers depending on the handler
|
;; Difference between the origin point in the
|
||||||
handler-mult (let [[x y] (handler-multipliers handler)] (gpt/point x y))
|
;; coordinate system of the rotation
|
||||||
|
|
||||||
;; Difference between the origin point in the coordinate system of the rotation
|
|
||||||
deltav (-> (gpt/to-vec initial point)
|
deltav (-> (gpt/to-vec initial point)
|
||||||
(gpt/multiply handler-mult))
|
;; Vector modifiers depending on the handler
|
||||||
|
(gpt/multiply (get-handler-multiplier handler)))
|
||||||
|
|
||||||
;; Resize vector
|
;; Resize vector
|
||||||
scalev (-> (gpt/divide (gpt/add shapev deltav) shapev)
|
scalev (-> (gpt/divide (gpt/add shapev deltav) shapev)
|
||||||
(gpt/no-zeros))
|
(gpt/no-zeros))
|
||||||
|
|
||||||
scalev (if lock?
|
scalev (if ^boolean lock?
|
||||||
(let [v (cond
|
(let [v (cond
|
||||||
(#{:right :left} handler) (:x scalev)
|
(or (= handler :right)
|
||||||
(#{:top :bottom} handler) (:y scalev)
|
(= handler :left))
|
||||||
:else (max (:x scalev) (:y scalev)))]
|
(dm/get-prop scalev :x)
|
||||||
(gpt/point v v))
|
|
||||||
|
|
||||||
|
(or (= handler :top)
|
||||||
|
(= handler :bottom))
|
||||||
|
(dm/get-prop scalev :y)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(mth/max (dm/get-prop scalev :x)
|
||||||
|
(dm/get-prop scalev :y)))]
|
||||||
|
(gpt/point v v))
|
||||||
scalev)
|
scalev)
|
||||||
|
|
||||||
;; Resize origin point given the selected handler
|
;; Resize origin point given the selected handler
|
||||||
handler-origin (handler-resize-origin (:selrect shape) handler)
|
selrect (dm/get-prop shape :selrect)
|
||||||
|
handler-origin (get-handler-resize-origin selrect handler)
|
||||||
|
|
||||||
;; If we want resize from center, displace the shape
|
;; If we want resize from center, displace the shape
|
||||||
;; so it is still centered after resize.
|
;; so it is still centered after resize.
|
||||||
displacement
|
displacement (when ^boolean center?
|
||||||
(when center?
|
(-> shape-center
|
||||||
(-> shape-center
|
(gpt/subtract handler-origin)
|
||||||
(gpt/subtract handler-origin)
|
(gpt/multiply scalev)
|
||||||
(gpt/multiply scalev)
|
(gpt/add handler-origin)
|
||||||
(gpt/add handler-origin)
|
(gpt/subtract shape-center)
|
||||||
(gpt/subtract shape-center)
|
(gpt/multiply (gpt/point -1 -1))
|
||||||
(gpt/multiply (gpt/point -1 -1))
|
(gpt/transform shape-transform)))
|
||||||
(gpt/transform shape-transform)))
|
|
||||||
|
|
||||||
resize-origin
|
resize-origin (gmt/transform-point-center handler-origin shape-center shape-transform)
|
||||||
(cond-> (gmt/transform-point-center handler-origin shape-center shape-transform)
|
resize-origin (if (some? displacement)
|
||||||
(some? displacement)
|
(gpt/add resize-origin displacement)
|
||||||
(gpt/add displacement))
|
resize-origin)
|
||||||
|
|
||||||
;; When the horizontal/vertical scale a flex children with auto/fill
|
;; When the horizontal/vertical scale a flex children with auto/fill
|
||||||
;; we change it too fixed
|
;; we change it too fixed
|
||||||
set-fix-width?
|
set-fix-width?
|
||||||
(not (mth/close? (:x scalev) 1))
|
(not (mth/close? (dm/get-prop scalev :x) 1))
|
||||||
|
|
||||||
set-fix-height?
|
set-fix-height?
|
||||||
(not (mth/close? (:y scalev) 1))
|
(not (mth/close? (dm/get-prop scalev :y) 1))
|
||||||
|
|
||||||
modifiers
|
modifiers (cond-> (ctm/empty)
|
||||||
(-> (ctm/empty)
|
(some? displacement)
|
||||||
|
(ctm/move displacement)
|
||||||
|
|
||||||
(cond-> displacement
|
:always
|
||||||
(ctm/move displacement))
|
(ctm/resize scalev resize-origin shape-transform shape-transform-inverse)
|
||||||
|
|
||||||
(ctm/resize scalev resize-origin shape-transform shape-transform-inverse)
|
^boolean set-fix-width?
|
||||||
|
(ctm/change-property :layout-item-h-sizing :fix)
|
||||||
|
|
||||||
(cond-> set-fix-width?
|
^boolean set-fix-height?
|
||||||
(ctm/change-property :layout-item-h-sizing :fix))
|
(ctm/change-property :layout-item-v-sizing :fix)
|
||||||
|
|
||||||
(cond-> set-fix-height?
|
^boolean scale-text
|
||||||
(ctm/change-property :layout-item-v-sizing :fix))
|
(ctm/scale-content (dm/get-prop scalev :x)))
|
||||||
|
|
||||||
(cond-> scale-text
|
|
||||||
(ctm/scale-content (:x scalev))))
|
|
||||||
|
|
||||||
modif-tree (dwm/create-modif-tree ids modifiers)]
|
modif-tree (dwm/create-modif-tree ids modifiers)]
|
||||||
|
|
||||||
(rx/of (dwm/set-modifiers modif-tree scale-text))))
|
(rx/of (dwm/set-modifiers modif-tree scale-text))))
|
||||||
|
|
||||||
;; Unifies the instantaneous proportion lock modifier
|
;; Unifies the instantaneous proportion lock modifier
|
||||||
|
@ -208,7 +243,10 @@
|
||||||
;; lock flag that can be activated on element options.
|
;; lock flag that can be activated on element options.
|
||||||
(normalize-proportion-lock [[point shift? alt?]]
|
(normalize-proportion-lock [[point shift? alt?]]
|
||||||
(let [proportion-lock? (:proportion-lock shape)]
|
(let [proportion-lock? (:proportion-lock shape)]
|
||||||
[point (or proportion-lock? shift?) alt?]))]
|
[point
|
||||||
|
(or ^boolean proportion-lock?
|
||||||
|
^boolean shift?)
|
||||||
|
alt?]))]
|
||||||
(reify
|
(reify
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -218,15 +256,16 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [initial-position @ms/mouse-position
|
(let [initial-position @ms/mouse-position
|
||||||
|
|
||||||
stopper (->> stream
|
stopper (->> stream
|
||||||
(rx/filter mse/mouse-event?)
|
(rx/filter mse/mouse-event?)
|
||||||
(rx/filter mse/mouse-up-event?))
|
(rx/filter mse/mouse-up-event?))
|
||||||
layout (:workspace-layout state)
|
layout (:workspace-layout state)
|
||||||
page-id (:current-page-id state)
|
page-id (:current-page-id state)
|
||||||
focus (:workspace-focus-selected state)
|
focus (:workspace-focus-selected state)
|
||||||
zoom (get-in state [:workspace-local :zoom] 1)
|
zoom (dm/get-in state [:workspace-local :zoom] 1)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
resizing-shapes (map #(get objects %) ids)]
|
shapes (map (d/getf objects) ids)]
|
||||||
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
|
@ -234,7 +273,7 @@
|
||||||
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-alt)
|
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-alt)
|
||||||
(rx/map normalize-proportion-lock)
|
(rx/map normalize-proportion-lock)
|
||||||
(rx/switch-map (fn [[point _ _ :as current]]
|
(rx/switch-map (fn [[point _ _ :as current]]
|
||||||
(->> (snap/closest-snap-point page-id resizing-shapes objects layout zoom focus point)
|
(->> (snap/closest-snap-point page-id shapes objects layout zoom focus point)
|
||||||
(rx/map #(conj current %)))))
|
(rx/map #(conj current %)))))
|
||||||
(rx/mapcat (partial resize shape initial-position layout))
|
(rx/mapcat (partial resize shape initial-position layout))
|
||||||
(rx/take-until stopper))
|
(rx/take-until stopper))
|
||||||
|
|
Loading…
Add table
Reference in a new issue