0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-15 01:01:30 -05:00

♻️ Refactor drawing effects

This commit is contained in:
alonso.torres 2020-11-05 10:09:02 +01:00
parent 67ed1d89ac
commit 10a24d68c9
5 changed files with 187 additions and 164 deletions

View file

@ -57,13 +57,13 @@
(watch [_ state stream] (watch [_ state stream]
(rx/of (case type (rx/of (case type
:path :path
path/handle-drawing-path (path/handle-drawing-path)
:curve :curve
curve/handle-drawing-curve (curve/handle-drawing-curve)
;; default ;; default
box/handle-drawing-box))))) (box/handle-drawing-box))))))
;; Export ;; Export
(def close-drawing-path path/close-drawing-path) (def close-drawing-path path/close-drawing-path)

View file

@ -20,72 +20,72 @@
[app.main.streams :as ms] [app.main.streams :as ms]
[app.main.data.workspace.drawing.common :as common])) [app.main.data.workspace.drawing.common :as common]))
(def handle-drawing-box (defn resize-shape [{:keys [x y width height] :as shape} point lock? point-snap]
(letfn [(resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] (let [;; The new shape behaves like a resize on the bottom-right corner
(let [;; The new shape behaves like a resize on the bottom-right corner initial (gpt/point (+ x width) (+ y height))
initial (gpt/point (+ x width) (+ y height)) shapev (gpt/point width height)
shapev (gpt/point width height) deltav (gpt/to-vec initial point-snap)
deltav (gpt/to-vec initial point-snap) scalev (gpt/divide (gpt/add shapev deltav) shapev)
scalev (gpt/divide (gpt/add shapev deltav) shapev) scalev (if lock?
scalev (if lock? (let [v (max (:x scalev) (:y scalev))]
(let [v (max (:x scalev) (:y scalev))] (gpt/point v v))
(gpt/point v v)) scalev)]
scalev)] (-> shape
(-> shape (assoc :click-draw? false)
(assoc :click-draw? false) (assoc-in [:modifiers :resize-vector] scalev)
(assoc-in [:modifiers :resize-vector] scalev) (assoc-in [:modifiers :resize-origin] (gpt/point x y))
(assoc-in [:modifiers :resize-origin] (gpt/point x y)) (assoc-in [:modifiers :resize-rotation] 0))))
(assoc-in [:modifiers :resize-rotation] 0))))
(update-drawing [state point lock? point-snap] (defn update-drawing [state point lock? point-snap]
(update-in state [:workspace-drawing :object] resize-shape point lock? point-snap))] (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap))
(ptk/reify ::handle-drawing-box (defn handle-drawing-box []
ptk/WatchEvent (ptk/reify ::handle-drawing-box
(watch [_ state stream] ptk/WatchEvent
(let [{:keys [flags]} (:workspace-local state) (watch [_ state stream]
(let [{:keys [flags]} (:workspace-local state)
stoper? #(or (ms/mouse-up? %) (= % :interrupt)) stoper? #(or (ms/mouse-up? %) (= % :interrupt))
stoper (rx/filter stoper? stream) stoper (rx/filter stoper? stream)
initial @ms/mouse-position initial @ms/mouse-position
page-id (:current-page-id state) page-id (:current-page-id state)
objects (dwc/lookup-page-objects state page-id) objects (dwc/lookup-page-objects state page-id)
layout (get state :workspace-layout) layout (get state :workspace-layout)
frames (cph/select-frames objects) frames (cph/select-frames objects)
fid (or (->> frames fid (or (->> frames
(filter #(gsh/has-point? % initial)) (filter #(gsh/has-point? % initial))
first first
:id) :id)
uuid/zero) uuid/zero)
shape (-> state shape (-> state
(get-in [:workspace-drawing :object]) (get-in [:workspace-drawing :object])
(gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1})
(assoc :frame-id fid) (assoc :frame-id fid)
(assoc :initialized? true) (assoc :initialized? true)
(assoc :click-draw? true))] (assoc :click-draw? true))]
(rx/concat (rx/concat
;; Add shape to drawing state ;; Add shape to drawing state
(rx/of #(assoc-in state [:workspace-drawing :object] shape)) (rx/of #(assoc-in state [:workspace-drawing :object] shape))
;; Initial SNAP ;; Initial SNAP
(->> (snap/closest-snap-point page-id [shape] layout initial) (->> (snap/closest-snap-point page-id [shape] layout initial)
(rx/map (fn [{:keys [x y]}] (rx/map (fn [{:keys [x y]}]
#(update-in % [:workspace-drawing :object] assoc :x x :y y)))) #(update-in % [:workspace-drawing :object] assoc :x x :y y))))
(->> ms/mouse-position (->> ms/mouse-position
(rx/filter #(> (gpt/distance % initial) 2)) (rx/filter #(> (gpt/distance % initial) 2))
(rx/with-latest vector ms/mouse-position-ctrl) (rx/with-latest vector ms/mouse-position-ctrl)
(rx/switch-map (rx/switch-map
(fn [[point :as current]] (fn [[point :as current]]
(->> (snap/closest-snap-point page-id [shape] layout point) (->> (snap/closest-snap-point page-id [shape] layout point)
(rx/map #(conj current %))))) (rx/map #(conj current %)))))
(rx/map (rx/map
(fn [[pt ctrl? point-snap]] (fn [[pt ctrl? point-snap]]
#(update-drawing % pt ctrl? point-snap))) #(update-drawing % pt ctrl? point-snap)))
(rx/take-until stoper)) (rx/take-until stoper))
(rx/of common/handle-finish-drawing))))))) (rx/of common/handle-finish-drawing))))))

View file

@ -18,34 +18,34 @@
(def simplify-tolerance 0.3) (def simplify-tolerance 0.3)
(def handle-drawing-curve (defn stoper-event? [{:keys [type shift] :as event}]
(letfn [(stoper-event? [{:keys [type shift] :as event}] (ms/mouse-event? event) (= type :up))
(ms/mouse-event? event) (= type :up))
(initialize-drawing [state] (defn initialize-drawing [state]
(assoc-in state [:workspace-drawing :object :initialized?] true)) (assoc-in state [:workspace-drawing :object :initialized?] true))
(insert-point-segment [state point] (defn insert-point-segment [state point]
(update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) (update-in state [:workspace-drawing :object :segments] (fnil conj []) point))
(finish-drawing-curve [state] (defn finish-drawing-curve [state]
(update-in (update-in
state [:workspace-drawing :object] state [:workspace-drawing :object]
(fn [shape] (fn [shape]
(-> shape (-> shape
(update :segments #(path/simplify % simplify-tolerance)) (update :segments #(path/simplify % simplify-tolerance))
(gsh/update-path-selrect)))))] (gsh/update-path-selrect)))))
(ptk/reify ::handle-drawing-curve (defn handle-drawing-curve []
ptk/WatchEvent (ptk/reify ::handle-drawing-curve
(watch [_ state stream] ptk/WatchEvent
(let [{:keys [flags]} (:workspace-local state) (watch [_ state stream]
stoper (rx/filter stoper-event? stream) (let [{:keys [flags]} (:workspace-local state)
mouse (rx/sample 10 ms/mouse-position)] stoper (rx/filter stoper-event? stream)
(rx/concat mouse (rx/sample 10 ms/mouse-position)]
(rx/of initialize-drawing) (rx/concat
(->> mouse (rx/of initialize-drawing)
(rx/map (fn [pt] #(insert-point-segment % pt))) (->> mouse
(rx/take-until stoper)) (rx/map (fn [pt] #(insert-point-segment % pt)))
(rx/of finish-drawing-curve (rx/take-until stoper))
common/handle-finish-drawing))))))) (rx/of finish-drawing-curve
common/handle-finish-drawing))))))

View file

@ -17,97 +17,115 @@
[app.util.geom.path :as path] [app.util.geom.path :as path]
[app.main.data.workspace.drawing.common :as common])) [app.main.data.workspace.drawing.common :as common]))
(def handle-drawing-path (defn stoper-event? [{:keys [type shift] :as event}]
(letfn [(stoper-event? [{:keys [type shift] :as event}] (or (= event ::end-path-drawing)
(or (= event ::end-path-drawing) (= event :interrupt)
(= event :interrupt) (and (ms/mouse-event? event)
(and (ms/mouse-event? event) (or (= type :double-click)
(or (= type :double-click) (= type :context-menu)))
(= type :context-menu))) (and (ms/keyboard-event? event)
(and (ms/keyboard-event? event) (= type :down)
(= type :down) (= 13 (:key event)))))
(= 13 (:key event)))))
(initialize-drawing [state point] (defn init-path []
(-> state (fn [state]
(assoc-in [:workspace-drawing :object :segments] [point point]) (update-in state [:workspace-drawing :object]
(assoc-in [:workspace-drawing :object :initialized?] true))) assoc :content []
:initialized? true)))
(insert-point-segment [state point] (defn add-path-command [command]
(-> state (fn [state]
(update-in [:workspace-drawing :object :segments] (fnil conj []) point))) (update-in state [:workspace-drawing :object :content] conj command)))
(update-point-segment [state index point] #_(defn update-point-segment [state index point]
(let [segments (count (get-in state [:workspace-drawing :object :segments])) (let [segments (count (get-in state [:workspace-drawing :object :segments]))
exists? (< -1 index segments)] exists? (< -1 index segments)]
(cond-> state (cond-> state
exists? (assoc-in [:workspace-drawing :object :segments index] point)))) exists? (assoc-in [:workspace-drawing :object :segments index] point))))
(finish-drawing-path [state] (defn finish-drawing-path []
(update-in (fn [state]
state [:workspace-drawing :object] (update-in
(fn [shape] (-> shape state [:workspace-drawing :object]
(update :segments #(vec (butlast %))) (fn [shape] (-> shape
(gsh/update-path-selrect)))))] (update :segments #(vec (butlast %)))
(gsh/update-path-selrect))))))
(ptk/reify ::handle-drawing-path
ptk/WatchEvent
(watch [_ state stream]
(let [{:keys [flags]} (:workspace-local state)
last-point (volatile! @ms/mouse-position) (defn handle-drawing-path []
stoper (->> (rx/filter stoper-event? stream) (ptk/reify ::handle-drawing-path
(rx/share)) ptk/WatchEvent
(watch [_ state stream]
mouse (rx/sample 10 ms/mouse-position) ;; clicks stream<[MouseEvent, Position]>
clicks (->> stream
(rx/filter ms/mouse-click?)
(rx/with-latest vector ms/mouse-position))
points (->> stream
(rx/filter ms/mouse-click?)
(rx/filter #(false? (:shift %)))
(rx/with-latest vector mouse)
(rx/map second))
counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1))
stream' (->> mouse )))
(rx/with-latest vector ms/mouse-position-ctrl)
(rx/with-latest vector counter)
(rx/map flatten))
imm-transform #(vector (- % 7) (+ % 7) %) #_(def handle-drawing-path
immanted-zones (vec (concat (ptk/reify ::handle-drawing-path
(map imm-transform (range 0 181 15)) ptk/WatchEvent
(map (comp imm-transform -) (range 0 181 15)))) (watch [_ state stream]
(let [{:keys [flags]} (:workspace-local state)
align-position (fn [angle pos] last-point (volatile! @ms/mouse-position)
(reduce (fn [pos [a1 a2 v]]
(if (< a1 angle a2)
(reduced (gpt/update-angle pos v))
pos))
pos
immanted-zones))]
(rx/merge stoper (->> (rx/filter stoper-event? stream)
(rx/of #(initialize-drawing % @last-point)) (rx/share))
(->> points mouse (rx/sample 10 ms/mouse-position)
(rx/take-until stoper)
(rx/map (fn [pt] #(insert-point-segment % pt))))
(rx/concat points (->> stream
(->> stream' (rx/filter ms/mouse-click?)
(rx/take-until stoper) (rx/filter #(false? (:shift %)))
(rx/map (fn [[point ctrl? index :as xxx]] (rx/with-latest vector mouse)
(let [point (if ctrl? (rx/map second))
(as-> point $
(gpt/subtract $ @last-point) counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1))
(align-position (gpt/angle $) $)
(gpt/add $ @last-point)) stream' (->> mouse
point)] (rx/with-latest vector ms/mouse-position-ctrl)
#(update-point-segment % index point))))) (rx/with-latest vector counter)
(rx/of finish-drawing-path (rx/map flatten))
common/handle-finish-drawing))))))))
imm-transform #(vector (- % 7) (+ % 7) %)
immanted-zones (vec (concat
(map imm-transform (range 0 181 15))
(map (comp imm-transform -) (range 0 181 15))))
align-position (fn [angle pos]
(reduce (fn [pos [a1 a2 v]]
(if (< a1 angle a2)
(reduced (gpt/update-angle pos v))
pos))
pos
immanted-zones))]
(rx/merge
(rx/of #(initialize-drawing % @last-point))
(->> points
(rx/take-until stoper)
(rx/map (fn [pt] #(insert-point-segment % pt))))
(rx/concat
(->> stream'
(rx/take-until stoper)
(rx/map (fn [[point ctrl? index :as xxx]]
(let [point (if ctrl?
(as-> point $
(gpt/subtract $ @last-point)
(align-position (gpt/angle $) $)
(gpt/add $ @last-point))
point)]
#(update-point-segment % index point)))))
(rx/of finish-drawing-path
common/handle-finish-drawing)))))))
(defn close-drawing-path [] (defn close-drawing-path []
(ptk/reify ::close-drawing-path (ptk/reify ::close-drawing-path

View file

@ -26,6 +26,11 @@
[v] [v]
(instance? MouseEvent v)) (instance? MouseEvent v))
(defn mouse-down?
[v]
(and (mouse-event? v)
(= :down (:type v))))
(defn mouse-up? (defn mouse-up?
[v] [v]
(and (mouse-event? v) (and (mouse-event? v)