0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 00:58:26 -05:00

Snap for moving path nodes and handlers

This commit is contained in:
alonso.torres 2021-04-13 17:44:26 +02:00 committed by Andrés Moya
parent de8207c5a6
commit f396ef4fa0
7 changed files with 83 additions and 75 deletions

View file

@ -24,8 +24,8 @@
(d/export edition/start-path-edit)
;; Selection
(d/export selection/select-handler)
(d/export selection/handle-selection)
(d/export selection/select-node)
(d/export selection/path-handler-enter)
(d/export selection/path-handler-leave)
(d/export selection/path-pointer-enter)

View file

@ -35,17 +35,20 @@
:x dx :y dy :c2x dx :c2y dy))))))
(defn modify-handler [id index prefix dx dy match-opposite?]
(ptk/reify ::modify-point
(ptk/reify ::modify-handler
ptk/UpdateEvent
(update [_ state]
(let [content (get-in state (st/get-path state :content))
[cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y])
[ocx ocy] (if (= prefix :c1) [:c2x :c2y] [:c1x :c1y])
point (gpt/point (+ (get-in content [index :params cx]) dx)
(+ (get-in content [index :params cy]) dy))
opposite-index (ugp/opposite-index content index prefix)]
(cond-> state
:always
(update-in [:workspace-local :edit-path id :content-modifiers index] assoc
cx dx cy dy)
(-> (update-in [:workspace-local :edit-path id :content-modifiers index] assoc
cx dx cy dy)
(assoc-in [:workspace-local :edit-path id :moving-handler] point))
(and match-opposite? opposite-index)
(update-in [:workspace-local :edit-path id :content-modifiers opposite-index] assoc
@ -63,7 +66,7 @@
[rch uch] (changes/generate-path-changes page-id shape (:content shape) new-content)]
(rx/of (dwc/commit-changes rch uch {:commit-local? true})
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers)))))))
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler)))))))
(defn move-selected-path-point [from-point to-point]
(letfn [(modify-content-point [content {dx :x dy :y} modifiers point]
@ -101,7 +104,9 @@
modifiers (->> points
(reduce modifiers-reducer {}))]
(assoc-in state [:workspace-local :edit-path id :content-modifiers] modifiers))))))
(-> state
(assoc-in [:workspace-local :edit-path id :moving-nodes] true)
(assoc-in [:workspace-local :edit-path id :content-modifiers] modifiers)))))))
(defn start-move-path-point
[position shift?]
@ -120,11 +125,6 @@
mouse-drag-stream
(rx/concat
;; If we're dragging a selected item we don't change the selection
(if selected?
(rx/empty)
(rx/of (selection/select-node position shift?)))
;; This stream checks the consecutive mouse positions to do the draging
(->> points
(streams/move-points-stream start-position selected-points)

View file

@ -28,15 +28,6 @@
(let [id (st/get-path-id state)]
(update-in state [:workspace-local :edit-path id :hover-points] disj position)))))
(defn select-handler [index type]
(ptk/reify ::select-handler
ptk/UpdateEvent
(update [_ state]
(let [id (get-in state [:workspace-local :edition])]
(-> state
(update-in [:workspace-local :edit-path id :selected-handlers] (fnil conj #{}) [index type]))))))
(defn path-handler-enter [index prefix]
(ptk/reify ::path-handler-enter
ptk/UpdateEvent
@ -115,7 +106,6 @@
(update [_ state]
(let [id (st/get-path-id state)]
(-> state
(assoc-in [:workspace-local :edit-path id :selected-handlers] #{})
(assoc-in [:workspace-local :edit-path id :selected-points] #{}))))))
(defn update-area-selection

View file

@ -58,36 +58,39 @@
[start-point selected-points points]
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
ranges (snap/create-ranges selected-points points)
d-pos (/ snap/snap-accuracy zoom)]
ranges (snap/create-ranges points selected-points)
d-pos (/ snap/snap-path-accuracy zoom)
check-path-snap
(fn [position]
(let [delta (gpt/subtract position start-point)
moved-points (->> selected-points (mapv #(gpt/add % delta)))
snap (snap/get-snap-delta moved-points ranges d-pos)]
(gpt/add position snap)))]
(->> ms/mouse-position
(rx/map (fn [position]
(let [delta (gpt/subtract position start-point)
moved-points (->> selected-points (mapv #(gpt/add % delta)))]
(gpt/add
position
(snap/get-snap-delta moved-points ranges d-pos)))))))
)
(rx/map check-path-snap))))
(defn move-handler-stream
[start-point handler points]
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
ranges (snap/create-ranges points)
d-pos (/ snap/snap-accuracy zoom)]
d-pos (/ snap/snap-path-accuracy zoom)
check-path-snap
(fn [position]
(let [delta (gpt/subtract position start-point)
handler-position (gpt/add handler delta)
snap (snap/get-snap-delta [handler-position] ranges d-pos)]
(gpt/add position snap)))]
(->> ms/mouse-position
(rx/map (fn [position]
(let [delta (gpt/subtract position start-point)
handler-position (gpt/add handler delta)]
(gpt/add
position
(snap/get-snap-delta [handler-position] ranges d-pos))))))))
(rx/map check-path-snap))))
(defn position-stream
[points]
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
;; ranges (snap/create-ranges points)
d-pos (/ snap/snap-accuracy zoom)
d-pos (/ snap/snap-path-accuracy zoom)
get-content (fn [state] (get-in state (state/get-path state :content)))
content-stream
@ -103,9 +106,7 @@
(rx/with-latest vector ranges-stream)
(rx/map (fn [[position ranges]]
(let [snap (snap/get-snap-delta [position] ranges d-pos)]
#_(prn ">>>" snap)
(gpt/add position snap))
))
(gpt/add position snap))))
(rx/with-latest merge (->> ms/mouse-position-shift (rx/map #(hash-map :shift? %))))
(rx/with-latest merge (->> ms/mouse-position-alt (rx/map #(hash-map :alt? %)))))))

View file

@ -20,6 +20,7 @@
[clojure.set :as set]))
(defonce ^:private snap-accuracy 5)
(defonce ^:private snap-path-accuracy 10)
(defonce ^:private snap-distance-accuracy 10)
(defn- remove-from-snap-points
@ -272,9 +273,8 @@
(->> (rt/range-query (get ranges coord) (- pval precision) (+ pval precision))
;; We save the distance to the point and add the matching point to the points
(mapv (fn [[value points]]
[(mth/abs (- value pval))
[(- value pval)
(->> points (mapv #(vector point %)))])))))]
{:x (query-coord point :x)
:y (query-coord point :y)}))
@ -301,7 +301,7 @@
[default matches]
(let [get-min
(fn [[cur-val :as current] [other-val :as other]]
(if (< cur-val other-val)
(if (< (mth/abs cur-val) (mth/abs other-val))
current
other))

View file

@ -19,6 +19,7 @@
[app.util.dom :as dom]
[app.util.geom.path :as ugp]
[app.util.keyboard :as kbd]
[clojure.set :refer [map-invert]]
[goog.events :as events]
[rumext.alpha :as mf])
(:import goog.events.EventType))
@ -42,7 +43,10 @@
(let [shift? (kbd/shift? event)]
(cond
(= edit-mode :move)
(st/emit! (drp/start-move-path-point position shift?))
;; If we're dragging a selected item we don't change the selection
(do (when (not selected?)
(st/emit! (drp/select-node position shift?)))
(st/emit! (drp/start-move-path-point position shift?)))
(and (= edit-mode :draw) start-path?)
(st/emit! (drp/start-path-from-point position))
@ -84,14 +88,6 @@
(fn [event]
(st/emit! (drp/path-handler-leave index prefix)))
on-click
(fn [event]
(dom/stop-propagation event)
(dom/prevent-default event)
(cond
(= edit-mode :move)
(drp/select-handler index prefix)))
on-mouse-down
(fn [event]
(dom/stop-propagation event)
@ -123,7 +119,6 @@
[:circle {:cx x
:cy y
:r (/ 10 zoom)
:on-click on-click
:on-mouse-down on-mouse-down
:on-mouse-enter on-enter
:on-mouse-leave on-leave
@ -145,7 +140,7 @@
:preview? true
:zoom zoom}]])
(mf/defc snap-points [{:keys [selected points zoom]}]
(mf/defc path-snap [{:keys [selected points zoom]}]
(let [ranges (mf/use-memo (mf/deps selected points) #(snap/create-ranges points selected))
snap-matches (snap/get-snap-delta-match selected ranges (/ 1 zoom))
matches (d/concat [] (second (:x snap-matches)) (second (:y snap-matches)))]
@ -172,19 +167,41 @@
preview
content-modifiers
last-point
selected-handlers
selected-points
moving-nodes
moving-handler
hover-handlers
hover-points]
:as edit-path} (mf/deref edit-path-ref)
{base-content :content} shape
selected-points (or selected-points #{})
base-content (:content shape)
base-points (mf/use-memo (mf/deps base-content) #(->> base-content ugp/content->points))
content (ugp/apply-content-modifiers base-content content-modifiers)
points (mf/use-memo (mf/deps content) #(->> content ugp/content->points (into #{})))
content-points (mf/use-memo (mf/deps content) #(->> content ugp/content->points))
point->base (->> (map hash-map content-points base-points) (reduce merge))
base->point (map-invert point->base)
points (into #{} content-points)
last-command (last content)
last-p (->> content last ugp/command->point)
handlers (ugp/content->handlers content)
[snap-selected snap-points]
(cond
(some? drag-handler) [#{drag-handler} points]
(some? preview) [#{(ugp/command->point preview)} points]
(some? moving-handler) [#{moving-handler} points]
:else
[(->> selected-points (map base->point) (into #{}))
(->> points (remove selected-points) (into #{}))])
show-snap? (or (some? drag-handler) (some? preview) (some? moving-handler) moving-nodes)
handle-double-click-outside
(fn [event]
(when (= edit-mode :move)
@ -199,13 +216,14 @@
[:g.path-editor {:ref editor-ref}
(when (and preview (not drag-handler))
[:*
[:& snap-points {:selected #{(ugp/command->point preview)}
:points points
:zoom zoom}]
[:& path-preview {:command preview
:from last-p
:zoom zoom}])
[:& path-preview {:command preview
:from last-p
(when drag-handler
[:g.drag-handler {:pointer-events "none"}
[:& path-handler {:point last-p
:handler drag-handler
:zoom zoom}]])
(when @hover-point
@ -214,10 +232,11 @@
:zoom zoom}]])
(for [position points]
(let [point-selected? (contains? selected-points position)
point-hover? (contains? hover-points position)
last-p? (= last-point position)
(let [point-selected? (contains? selected-points (get point->base position))
point-hover? (contains? hover-points (get point->base position))
last-p? (= last-point (get point->base position))
start-p? (not (some? last-point))]
[:g.path-node
[:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")}
(for [[index prefix] (get handlers position)]
@ -225,7 +244,6 @@
x (get-in command [:params (d/prefix-keyword prefix :x)])
y (get-in command [:params (d/prefix-keyword prefix :y)])
handler-position (gpt/point x y)
handler-selected? (contains? selected-handlers [index prefix])
handler-hover? (contains? hover-handlers [index prefix])]
(when (not= position handler-position)
[:& path-handler {:point position
@ -233,7 +251,6 @@
:index index
:prefix prefix
:zoom zoom
:selected? handler-selected?
:hover? handler-hover?
:edit-mode edit-mode}])))]
[:& path-point {:position position
@ -250,9 +267,9 @@
:handler prev-handler
:zoom zoom}]])
(when drag-handler
[:g.drag-handler {:pointer-events "none"}
[:& path-handler {:point last-p
:handler drag-handler
:zoom zoom}]])]))
(when show-snap?
[:g.path-snap {:pointer-events "none"}
[:& path-snap {:selected snap-selected
:points snap-points
:zoom zoom}]])]))

View file

@ -59,7 +59,7 @@
(when (and (not= edition id) text-editing?)
(st/emit! dw/clear-edition-mode))
(when (and (or (not edition) (not= edition id))
(when (and (not text-editing?)
(not blocked)
(not hidden)
(not (#{:comments :path} drawing-tool))