mirror of
https://github.com/penpot/penpot.git
synced 2025-05-21 04:36:13 +02: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
|
(loop [t1 0
|
||||||
t2 1]
|
t2 1]
|
||||||
(if (<= (mth/abs (- t1 t2)) path-closest-point-accuracy)
|
(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))
|
(let [ht (+ t1 (/ (- t2 t1) 2))
|
||||||
ht1 (+ t1 (/ (- t2 t1) 4))
|
ht1 (+ t1 (/ (- t2 t1) 4))
|
||||||
|
@ -260,21 +262,18 @@
|
||||||
"Point on line"
|
"Point on line"
|
||||||
[position from-p to-p]
|
[position from-p to-p]
|
||||||
|
|
||||||
(let [{v1x :x v1y :y} from-p
|
(let [e1 (gpt/to-vec from-p to-p )
|
||||||
{v2x :x v2y :y} to-p
|
e2 (gpt/to-vec from-p position)
|
||||||
{px :x py :y} position
|
|
||||||
|
|
||||||
e1 (gpt/point (- v2x v1x) (- v2y v1y))
|
|
||||||
e2 (gpt/point (- px v1x) (- py v1y))
|
|
||||||
|
|
||||||
len2 (+ (mth/sq (:x e1)) (mth/sq (:y e1)))
|
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
|
;; There is no perpendicular projection in the line so the closest
|
||||||
;; point will be one of the extremes
|
;; point will be one of the extremes
|
||||||
(if (<= (gpt/distance position from-p) (gpt/distance position to-p))
|
(if (<= (gpt/distance position from-p) (gpt/distance position to-p))
|
||||||
|
@ -286,20 +285,20 @@
|
||||||
[shape position]
|
[shape position]
|
||||||
|
|
||||||
(let [point+distance (fn [[cur-cmd prev-cmd]]
|
(let [point+distance (fn [[cur-cmd prev-cmd]]
|
||||||
(let [point
|
(let [from-p (command->point prev-cmd)
|
||||||
(case (:command cur-cmd)
|
to-p (command->point cur-cmd)
|
||||||
:line-to (line-closest-point
|
h1 (gpt/point (get-in cur-cmd [:params :c1x])
|
||||||
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]))
|
(get-in cur-cmd [:params :c1y]))
|
||||||
(gpt/point (get-in cur-cmd [:params :c2x])
|
h2 (gpt/point (get-in cur-cmd [:params :c2x])
|
||||||
(get-in cur-cmd [:params :c2y])))
|
(get-in cur-cmd [:params :c2y]))
|
||||||
|
point
|
||||||
|
(case (:command cur-cmd)
|
||||||
|
:line-to
|
||||||
|
(line-closest-point position from-p to-p)
|
||||||
|
|
||||||
|
:curve-to
|
||||||
|
(curve-closest-point position from-p to-p h1 h2)
|
||||||
|
|
||||||
nil)]
|
nil)]
|
||||||
(when point
|
(when point
|
||||||
[point (gpt/distance point position)])))
|
[point (gpt/distance point position)])))
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
(d/export edition/start-move-handler)
|
(d/export edition/start-move-handler)
|
||||||
(d/export edition/start-move-path-point)
|
(d/export edition/start-move-path-point)
|
||||||
(d/export edition/start-path-edit)
|
(d/export edition/start-path-edit)
|
||||||
|
(d/export edition/create-node-at-position)
|
||||||
|
|
||||||
;; Selection
|
;; Selection
|
||||||
(d/export selection/handle-selection)
|
(d/export selection/handle-selection)
|
||||||
|
|
|
@ -234,3 +234,15 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [id (get-in state [:workspace-local :edition])]
|
(let [id (get-in state [:workspace-local :edition])]
|
||||||
(update state :workspace-local dissoc :edit-path id)))))
|
(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])
|
[rumext.alpha :as mf])
|
||||||
(:import goog.events.EventType))
|
(: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
|
(let [{:keys [x y]} position
|
||||||
|
|
||||||
on-enter
|
on-enter
|
||||||
|
@ -40,6 +40,9 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default 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)]
|
(let [shift? (kbd/shift? event)]
|
||||||
(cond
|
(cond
|
||||||
(= edit-mode :move)
|
(= edit-mode :move)
|
||||||
|
@ -190,6 +193,8 @@
|
||||||
last-p (->> content last ugp/command->point)
|
last-p (->> content last ugp/command->point)
|
||||||
handlers (ugp/content->handlers content)
|
handlers (ugp/content->handlers content)
|
||||||
|
|
||||||
|
start-p? (not (some? last-point))
|
||||||
|
|
||||||
[snap-selected snap-points]
|
[snap-selected snap-points]
|
||||||
(cond
|
(cond
|
||||||
(some? drag-handler) [#{drag-handler} points]
|
(some? drag-handler) [#{drag-handler} points]
|
||||||
|
@ -199,7 +204,9 @@
|
||||||
[(->> selected-points (map base->point) (into #{}))
|
[(->> selected-points (map base->point) (into #{}))
|
||||||
(->> points (remove selected-points) (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
|
handle-double-click-outside
|
||||||
(fn [event]
|
(fn [event]
|
||||||
|
@ -213,6 +220,13 @@
|
||||||
#(doseq [key keys]
|
#(doseq [key keys]
|
||||||
(events/unlistenByKey key)))))
|
(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}
|
[:g.path-editor {:ref editor-ref}
|
||||||
(when (and preview (not drag-handler))
|
(when (and preview (not drag-handler))
|
||||||
[:& path-preview {:command preview
|
[:& path-preview {:command preview
|
||||||
|
@ -228,13 +242,15 @@
|
||||||
(when @hover-point
|
(when @hover-point
|
||||||
[:g.hover-point
|
[:g.hover-point
|
||||||
[:& path-point {:position @hover-point
|
[:& path-point {:position @hover-point
|
||||||
|
:edit-mode edit-mode
|
||||||
|
:new-point? true
|
||||||
|
:start-path? start-p?
|
||||||
:zoom zoom}]])
|
:zoom zoom}]])
|
||||||
|
|
||||||
(for [position points]
|
(for [position points]
|
||||||
(let [point-selected? (contains? selected-points (get point->base position))
|
(let [point-selected? (contains? selected-points (get point->base position))
|
||||||
point-hover? (contains? hover-points (get point->base position))
|
point-hover? (contains? hover-points (get point->base position))
|
||||||
last-p? (= last-point (get point->base position))
|
last-p? (= last-point (get point->base position))]
|
||||||
start-p? (not (some? last-point))]
|
|
||||||
|
|
||||||
[:g.path-node
|
[:g.path-node
|
||||||
[:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")}
|
[: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])))
|
drawing-path? (or (and edition (= :draw (get-in edit-path [edition :edit-mode])))
|
||||||
(and (some? drawing-obj) (= :path (:type drawing-obj))))
|
(and (some? drawing-obj) (= :path (:type drawing-obj))))
|
||||||
text-editing? (and edition (= :text (get-in objects [edition :type])))
|
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-click (actions/on-click hover selected edition drawing-path? drawing-tool)
|
||||||
on-context-menu (actions/on-context-menu hover)
|
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-distance? (and (contains? layout :dynamic-alignment) (= transform :move) (not (empty? selected)))
|
||||||
show-snap-points? (and (contains? layout :dynamic-alignment) (or drawing-obj transform))
|
show-snap-points? (and (contains? layout :dynamic-alignment) (or drawing-obj transform))
|
||||||
show-selrect? (and selrect (empty? drawing))
|
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-dom-events viewport-ref zoom disable-paste in-viewport?)
|
||||||
(hooks/setup-viewport-size viewport-ref)
|
(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-resize layout viewport-ref)
|
||||||
(hooks/setup-keyboard alt? ctrl?)
|
(hooks/setup-keyboard alt? ctrl?)
|
||||||
(hooks/setup-hover-shapes page-id move-stream selected objects transform selected ctrl? hover hover-ids)
|
(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)
|
:disable-handlers (or drawing-tool edition)
|
||||||
:on-move-selected on-move-selected}])
|
:on-move-selected on-move-selected}])
|
||||||
|
|
||||||
(when (and (not transform) show-distances?)
|
(when show-measures?
|
||||||
[:& msr/measurement
|
[:& msr/measurement
|
||||||
{:bounds vbox
|
{:bounds vbox
|
||||||
:selected-shapes selected-shapes
|
:selected-shapes selected-shapes
|
||||||
|
|
|
@ -58,9 +58,9 @@
|
||||||
;; We schedule the event so it fires after `initialize-page` event
|
;; We schedule the event so it fires after `initialize-page` event
|
||||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
(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/use-effect
|
||||||
(mf/deps @cursor @alt? panning drawing-tool drawing-path?)
|
(mf/deps @cursor @alt? panning drawing-tool drawing-path? path-editing?)
|
||||||
(fn []
|
(fn []
|
||||||
(let [new-cursor
|
(let [new-cursor
|
||||||
(cond
|
(cond
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
drawing-path?) (utils/get-cursor :pen)
|
drawing-path?) (utils/get-cursor :pen)
|
||||||
(= drawing-tool :curve) (utils/get-cursor :pencil)
|
(= drawing-tool :curve) (utils/get-cursor :pencil)
|
||||||
drawing-tool (utils/get-cursor :create-shape)
|
drawing-tool (utils/get-cursor :create-shape)
|
||||||
@alt? (utils/get-cursor :duplicate)
|
(and @alt? (not path-editing?)) (utils/get-cursor :duplicate)
|
||||||
:else (utils/get-cursor :pointer-inner))]
|
:else (utils/get-cursor :pointer-inner))]
|
||||||
|
|
||||||
(when (not= @cursor new-cursor)
|
(when (not= @cursor new-cursor)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue