mirror of
https://github.com/penpot/penpot.git
synced 2025-04-13 15:31:26 -05:00
✨ Adds path new-point edition
This commit is contained in:
parent
f7712f2b40
commit
e2cf3a5a98
6 changed files with 74 additions and 44 deletions
|
@ -233,7 +233,9 @@
|
|||
(loop [t1 0
|
||||
t2 1]
|
||||
(if (<= (mth/abs (- t1 t2)) path-closest-point-accuracy)
|
||||
(curve-values start end h1 h2 t1)
|
||||
(-> (curve-values start end h1 h2 t1)
|
||||
;; store the segment info
|
||||
(with-meta {:t t1 :from-p start :to-p end}))
|
||||
|
||||
(let [ht (+ t1 (/ (- t2 t1) 2))
|
||||
ht1 (+ t1 (/ (- t2 t1) 4))
|
||||
|
@ -260,21 +262,18 @@
|
|||
"Point on line"
|
||||
[position from-p to-p]
|
||||
|
||||
(let [{v1x :x v1y :y} from-p
|
||||
{v2x :x v2y :y} to-p
|
||||
{px :x py :y} position
|
||||
|
||||
e1 (gpt/point (- v2x v1x) (- v2y v1y))
|
||||
e2 (gpt/point (- px v1x) (- py v1y))
|
||||
(let [e1 (gpt/to-vec from-p to-p )
|
||||
e2 (gpt/to-vec from-p position)
|
||||
|
||||
len2 (+ (mth/sq (:x e1)) (mth/sq (:y e1)))
|
||||
val-dp (/ (gpt/dot e1 e2) len2)]
|
||||
t (/ (gpt/dot e1 e2) len2)]
|
||||
|
||||
(if (and (>= t 0) (<= t 1) (not (mth/almost-zero? len2)))
|
||||
(-> (gpt/add from-p (gpt/scale e1 t))
|
||||
(with-meta {:t t
|
||||
:from-p from-p
|
||||
:to-p to-p}))
|
||||
|
||||
(if (and (>= val-dp 0)
|
||||
(<= val-dp 1)
|
||||
(not (mth/almost-zero? len2)))
|
||||
(gpt/point (+ v1x (* val-dp (:x e1)))
|
||||
(+ v1y (* val-dp (:y e1))))
|
||||
;; There is no perpendicular projection in the line so the closest
|
||||
;; point will be one of the extremes
|
||||
(if (<= (gpt/distance position from-p) (gpt/distance position to-p))
|
||||
|
@ -286,20 +285,20 @@
|
|||
[shape position]
|
||||
|
||||
(let [point+distance (fn [[cur-cmd prev-cmd]]
|
||||
(let [point
|
||||
(let [from-p (command->point prev-cmd)
|
||||
to-p (command->point cur-cmd)
|
||||
h1 (gpt/point (get-in cur-cmd [:params :c1x])
|
||||
(get-in cur-cmd [:params :c1y]))
|
||||
h2 (gpt/point (get-in cur-cmd [:params :c2x])
|
||||
(get-in cur-cmd [:params :c2y]))
|
||||
point
|
||||
(case (:command cur-cmd)
|
||||
:line-to (line-closest-point
|
||||
position
|
||||
(command->point prev-cmd)
|
||||
(command->point cur-cmd))
|
||||
:curve-to (curve-closest-point
|
||||
position
|
||||
(command->point prev-cmd)
|
||||
(command->point cur-cmd)
|
||||
(gpt/point (get-in cur-cmd [:params :c1x])
|
||||
(get-in cur-cmd [:params :c1y]))
|
||||
(gpt/point (get-in cur-cmd [:params :c2x])
|
||||
(get-in cur-cmd [:params :c2y])))
|
||||
:line-to
|
||||
(line-closest-point position from-p to-p)
|
||||
|
||||
:curve-to
|
||||
(curve-closest-point position from-p to-p h1 h2)
|
||||
|
||||
nil)]
|
||||
(when point
|
||||
[point (gpt/distance point position)])))
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
(d/export edition/start-move-handler)
|
||||
(d/export edition/start-move-path-point)
|
||||
(d/export edition/start-path-edit)
|
||||
(d/export edition/create-node-at-position)
|
||||
|
||||
;; Selection
|
||||
(d/export selection/handle-selection)
|
||||
|
|
|
@ -234,3 +234,15 @@
|
|||
(update [_ state]
|
||||
(let [id (get-in state [:workspace-local :edition])]
|
||||
(update state :workspace-local dissoc :edit-path id)))))
|
||||
|
||||
(defn create-node-at-position
|
||||
[{:keys [from-p to-p t]}]
|
||||
(ptk/reify ::create-node-at-position
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (st/get-path-id state)]
|
||||
(update-in state (st/get-path state :content) ugp/split-segments #{from-p to-p} t)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (changes/save-path-content)))))
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}]
|
||||
(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p? new-point?]}]
|
||||
(let [{:keys [x y]} position
|
||||
|
||||
on-enter
|
||||
|
@ -40,6 +40,9 @@
|
|||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
|
||||
(when (and new-point? (some? (meta position)))
|
||||
(st/emit! (drp/create-node-at-position (meta position))))
|
||||
|
||||
(let [shift? (kbd/shift? event)]
|
||||
(cond
|
||||
(= edit-mode :move)
|
||||
|
@ -190,6 +193,8 @@
|
|||
last-p (->> content last ugp/command->point)
|
||||
handlers (ugp/content->handlers content)
|
||||
|
||||
start-p? (not (some? last-point))
|
||||
|
||||
[snap-selected snap-points]
|
||||
(cond
|
||||
(some? drag-handler) [#{drag-handler} points]
|
||||
|
@ -199,7 +204,9 @@
|
|||
[(->> selected-points (map base->point) (into #{}))
|
||||
(->> points (remove selected-points) (into #{}))])
|
||||
|
||||
show-snap? (and snap-toggled (or (some? drag-handler) (some? preview) (some? moving-handler) moving-nodes))
|
||||
show-snap? (and snap-toggled
|
||||
(empty? hover-points)
|
||||
(or (some? drag-handler) (some? preview) (some? moving-handler) moving-nodes))
|
||||
|
||||
handle-double-click-outside
|
||||
(fn [event]
|
||||
|
@ -213,6 +220,13 @@
|
|||
#(doseq [key keys]
|
||||
(events/unlistenByKey key)))))
|
||||
|
||||
(hooks/use-stream
|
||||
ms/mouse-position
|
||||
(mf/deps shape zoom)
|
||||
(fn [position]
|
||||
(when-let [point (gshp/path-closest-point shape position)]
|
||||
(reset! hover-point (when (< (gpt/distance position point) (/ 10 zoom)) point)))))
|
||||
|
||||
[:g.path-editor {:ref editor-ref}
|
||||
(when (and preview (not drag-handler))
|
||||
[:& path-preview {:command preview
|
||||
|
@ -228,13 +242,15 @@
|
|||
(when @hover-point
|
||||
[:g.hover-point
|
||||
[:& path-point {:position @hover-point
|
||||
:edit-mode edit-mode
|
||||
:new-point? true
|
||||
:start-path? start-p?
|
||||
:zoom zoom}]])
|
||||
|
||||
(for [position points]
|
||||
(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))]
|
||||
last-p? (= last-point (get point->base position))]
|
||||
|
||||
[:g.path-node
|
||||
[:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")}
|
||||
|
|
|
@ -98,6 +98,7 @@
|
|||
drawing-path? (or (and edition (= :draw (get-in edit-path [edition :edit-mode])))
|
||||
(and (some? drawing-obj) (= :path (:type drawing-obj))))
|
||||
text-editing? (and edition (= :text (get-in objects [edition :type])))
|
||||
path-editing? (and edition (= :path (get-in objects [edition :type])))
|
||||
|
||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool)
|
||||
on-context-menu (actions/on-context-menu hover)
|
||||
|
@ -132,11 +133,12 @@
|
|||
show-snap-distance? (and (contains? layout :dynamic-alignment) (= transform :move) (not (empty? selected)))
|
||||
show-snap-points? (and (contains? layout :dynamic-alignment) (or drawing-obj transform))
|
||||
show-selrect? (and selrect (empty? drawing))
|
||||
show-measures? (and (not transform) (not path-editing?) show-distances?)
|
||||
]
|
||||
|
||||
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
|
||||
(hooks/setup-viewport-size viewport-ref)
|
||||
(hooks/setup-cursor cursor alt? panning drawing-tool drawing-path?)
|
||||
(hooks/setup-cursor cursor alt? panning drawing-tool drawing-path? path-editing?)
|
||||
(hooks/setup-resize layout viewport-ref)
|
||||
(hooks/setup-keyboard alt? ctrl?)
|
||||
(hooks/setup-hover-shapes page-id move-stream selected objects transform selected ctrl? hover hover-ids)
|
||||
|
@ -224,7 +226,7 @@
|
|||
:disable-handlers (or drawing-tool edition)
|
||||
:on-move-selected on-move-selected}])
|
||||
|
||||
(when (and (not transform) show-distances?)
|
||||
(when show-measures?
|
||||
[:& msr/measurement
|
||||
{:bounds vbox
|
||||
:selected-shapes selected-shapes
|
||||
|
|
|
@ -58,23 +58,23 @@
|
|||
;; We schedule the event so it fires after `initialize-page` event
|
||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
||||
|
||||
(defn setup-cursor [cursor alt? panning drawing-tool drawing-path?]
|
||||
(defn setup-cursor [cursor alt? panning drawing-tool drawing-path? path-editing?]
|
||||
(mf/use-effect
|
||||
(mf/deps @cursor @alt? panning drawing-tool drawing-path?)
|
||||
(mf/deps @cursor @alt? panning drawing-tool drawing-path? path-editing?)
|
||||
(fn []
|
||||
(let [new-cursor
|
||||
(cond
|
||||
panning (utils/get-cursor :hand)
|
||||
(= drawing-tool :comments) (utils/get-cursor :comments)
|
||||
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
||||
(= drawing-tool :rect) (utils/get-cursor :create-rectangle)
|
||||
(= drawing-tool :circle) (utils/get-cursor :create-ellipse)
|
||||
panning (utils/get-cursor :hand)
|
||||
(= drawing-tool :comments) (utils/get-cursor :comments)
|
||||
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
||||
(= drawing-tool :rect) (utils/get-cursor :create-rectangle)
|
||||
(= drawing-tool :circle) (utils/get-cursor :create-ellipse)
|
||||
(or (= drawing-tool :path)
|
||||
drawing-path?) (utils/get-cursor :pen)
|
||||
(= drawing-tool :curve) (utils/get-cursor :pencil)
|
||||
drawing-tool (utils/get-cursor :create-shape)
|
||||
@alt? (utils/get-cursor :duplicate)
|
||||
:else (utils/get-cursor :pointer-inner))]
|
||||
drawing-path?) (utils/get-cursor :pen)
|
||||
(= drawing-tool :curve) (utils/get-cursor :pencil)
|
||||
drawing-tool (utils/get-cursor :create-shape)
|
||||
(and @alt? (not path-editing?)) (utils/get-cursor :duplicate)
|
||||
:else (utils/get-cursor :pointer-inner))]
|
||||
|
||||
(when (not= @cursor new-cursor)
|
||||
(reset! cursor new-cursor))))))
|
||||
|
|
Loading…
Add table
Reference in a new issue