mirror of
https://github.com/penpot/penpot.git
synced 2025-05-12 17:16:39 +02:00
✨ Path-point calculation
This commit is contained in:
parent
fc383664c7
commit
6db144e5ed
7 changed files with 212 additions and 27 deletions
|
@ -133,8 +133,11 @@
|
|||
(->> stream (rx/filter #(or (helpers/end-path-event? %)
|
||||
(ms/mouse-up? %))))
|
||||
|
||||
content (get-in state (st/get-path state :content))
|
||||
points (ugp/content->points content)
|
||||
|
||||
drag-events-stream
|
||||
(->> (streams/position-stream)
|
||||
(->> (streams/position-stream points)
|
||||
(rx/take-until stop-stream)
|
||||
(rx/map #(drag-handler %)))]
|
||||
|
||||
|
@ -163,7 +166,10 @@
|
|||
zoom (get-in state [:workspace-local :zoom])
|
||||
mouse-up (->> stream (rx/filter #(or (helpers/end-path-event? %)
|
||||
(ms/mouse-up? %))))
|
||||
drag-events (->> (streams/position-stream)
|
||||
content (get-in state (st/get-path state :content))
|
||||
points (ugp/content->points content)
|
||||
|
||||
drag-events (->> (streams/position-stream points)
|
||||
(rx/take-until mouse-up)
|
||||
(rx/map #(drag-handler %)))]
|
||||
|
||||
|
@ -183,10 +189,10 @@
|
|||
(rx/merge-map #(rx/empty))))
|
||||
|
||||
(defn make-drag-stream
|
||||
[stream down-event zoom]
|
||||
[stream down-event zoom points]
|
||||
(let [mouse-up (->> stream (rx/filter #(or (helpers/end-path-event? %)
|
||||
(ms/mouse-up? %))))
|
||||
drag-events (->> (streams/position-stream)
|
||||
drag-events (->> (streams/position-stream points)
|
||||
(rx/take-until mouse-up)
|
||||
(rx/map #(drag-handler %)))]
|
||||
|
||||
|
@ -213,9 +219,12 @@
|
|||
mouse-down (->> stream (rx/filter ms/mouse-down?))
|
||||
end-path-events (->> stream (rx/filter helpers/end-path-event?))
|
||||
|
||||
content (get-in state (st/get-path state :content))
|
||||
points (ugp/content->points content)
|
||||
|
||||
;; Mouse move preview
|
||||
mousemove-events
|
||||
(->> (streams/position-stream)
|
||||
(->> (streams/position-stream points)
|
||||
(rx/take-until end-path-events)
|
||||
(rx/map #(preview-next-point %)))
|
||||
|
||||
|
@ -223,12 +232,12 @@
|
|||
mousedown-events
|
||||
(->> mouse-down
|
||||
(rx/take-until end-path-events)
|
||||
(rx/with-latest merge (streams/position-stream))
|
||||
(rx/with-latest merge (streams/position-stream points))
|
||||
|
||||
;; We change to the stream that emits the first event
|
||||
(rx/switch-map
|
||||
#(rx/race (make-node-events-stream stream)
|
||||
(make-drag-stream stream % zoom))))]
|
||||
(make-drag-stream stream % zoom points))))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (common/init-path))
|
||||
|
@ -269,6 +278,12 @@
|
|||
"Creates a new path shape"
|
||||
[]
|
||||
(ptk/reify ::handle-new-shape
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (st/get-path-id state)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path id :snap-toggled] true))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [shape-id (get-in state [:workspace-drawing :object :id])]
|
||||
|
|
|
@ -118,6 +118,9 @@
|
|||
selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
selected? (contains? selected-points position)
|
||||
|
||||
content (get-in state (st/get-path state :content))
|
||||
points (ugp/content->points content)
|
||||
|
||||
mouse-drag-stream
|
||||
(rx/concat
|
||||
;; If we're dragging a selected item we don't change the selection
|
||||
|
@ -126,7 +129,7 @@
|
|||
(rx/of (selection/select-node position shift?)))
|
||||
|
||||
;; This stream checks the consecutive mouse positions to do the draging
|
||||
(->> (streams/position-stream)
|
||||
(->> (streams/position-stream points)
|
||||
(rx/take-until stopper)
|
||||
(rx/map #(move-selected-path-point start-position %)))
|
||||
(rx/of (apply-content-modifiers)))
|
||||
|
@ -151,6 +154,8 @@
|
|||
start-delta-y (get-in modifiers [index cy] 0)
|
||||
|
||||
content (get-in state (st/get-path state :content))
|
||||
points (ugp/content->points content)
|
||||
|
||||
opposite-index (ugp/opposite-index content index prefix)
|
||||
opposite-prefix (if (= prefix :c1) :c2 :c1)
|
||||
opposite-handler (-> content (get opposite-index) (ugp/get-handler opposite-prefix))
|
||||
|
@ -163,7 +168,7 @@
|
|||
|
||||
(streams/drag-stream
|
||||
(rx/concat
|
||||
(->> (streams/position-stream)
|
||||
(->> (streams/position-stream points)
|
||||
(rx/take-until (->> stream (rx/filter ms/mouse-up?)))
|
||||
(rx/map
|
||||
(fn [{:keys [x y alt? shift?]}]
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
[app.main.streams :as ms]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]
|
||||
[app.common.math :as mth]))
|
||||
[app.common.math :as mth]
|
||||
[app.main.snap :as snap]))
|
||||
|
||||
(defonce drag-threshold 5)
|
||||
|
||||
|
@ -53,11 +54,17 @@
|
|||
(let [k 50]
|
||||
(* (mth/floor (/ num k)) k)))
|
||||
|
||||
(defn position-stream []
|
||||
(->> ms/mouse-position
|
||||
;; TODO: Prueba para el snap
|
||||
#_(rx/map #(-> %
|
||||
(update :x to-dec)
|
||||
(update :y to-dec)))
|
||||
(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? %))))))
|
||||
(defn position-stream
|
||||
([points]
|
||||
(position-stream points #{}))
|
||||
|
||||
([points selected-points]
|
||||
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)]
|
||||
(->> (snap/path-snap ms/mouse-position points selected-points zoom)
|
||||
(rx/with-latest vector ms/mouse-position)
|
||||
(rx/map (fn [[{[x] :x [y] :y} position]]
|
||||
(cond-> position
|
||||
(some? x) (assoc :x x)
|
||||
(some? y) (assoc :y y))))
|
||||
(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? %))))))))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.geom.snap-points :as sp]
|
||||
[app.util.range-tree :as rt]
|
||||
[beicon.core :as rx]
|
||||
[clojure.set :as set]))
|
||||
|
||||
|
@ -240,3 +241,32 @@
|
|||
(rx/reduce gpt/min)
|
||||
(rx/map #(or % (gpt/point 0 0))))))
|
||||
|
||||
(defn path-snap [position-stream points selected-points zoom]
|
||||
(let [selected-points (or selected-points #{})
|
||||
into-tree (fn [coord]
|
||||
(fn [tree point]
|
||||
(rt/insert tree (get point coord) point)))
|
||||
|
||||
ranges-x (->> points
|
||||
(filter (comp not selected-points))
|
||||
(reduce (into-tree :x) (rt/make-tree)))
|
||||
|
||||
ranges-y (->> points
|
||||
(filter (comp not selected-points))
|
||||
(reduce (into-tree :y) (rt/make-tree)))
|
||||
|
||||
min-match (fn [matches]
|
||||
(->> matches
|
||||
(reduce (fn [[cur-val :as current] [other-val :as other]]
|
||||
(if (< cur-val other-val)
|
||||
current
|
||||
other)))))]
|
||||
|
||||
(->> position-stream
|
||||
(rx/map
|
||||
(fn [{:keys [x y]}]
|
||||
(let [d-pos (/ snap-accuracy zoom)
|
||||
x-match (rt/range-query ranges-x (- x d-pos) (+ x d-pos))
|
||||
y-match (rt/range-query ranges-y (- y d-pos) (+ y d-pos))]
|
||||
{:x (min-match x-match)
|
||||
:y (min-match y-match)}))))))
|
||||
|
|
|
@ -8,16 +8,19 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.path :as gshp]
|
||||
[app.main.data.workspace.path :as drp]
|
||||
[app.main.snap :as snap]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.ui.cursors :as cur]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.shapes.path.common :as pc]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.geom.path :as ugp]
|
||||
[app.util.keyboard :as kbd]
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf]
|
||||
|
||||
[app.util.keyboard :as kbd])
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}]
|
||||
|
@ -131,8 +134,9 @@
|
|||
[:g.preview {:style {:pointer-events "none"}}
|
||||
(when (not= :move-to (:command command))
|
||||
[:path {:style {:fill "transparent"
|
||||
:stroke pc/secondary-color
|
||||
:stroke-width (/ 1 zoom)}
|
||||
:stroke pc/black-color
|
||||
:stroke-width (/ 1 zoom)
|
||||
:stroke-dasharray (/ 4 zoom)}
|
||||
:d (ugp/content->path [{:command :move-to
|
||||
:params {:x (:x from)
|
||||
:y (:y from)}}
|
||||
|
@ -141,11 +145,23 @@
|
|||
:preview? true
|
||||
:zoom zoom}]])
|
||||
|
||||
(mf/defc snap-path-points [{:keys [snaps zoom]}]
|
||||
[:g.snap-paths
|
||||
(for [[from to] snaps]
|
||||
[:line {:x1 (:x from)
|
||||
:y1 (:y from)
|
||||
:x2 (:x to)
|
||||
:y2 (:y to)
|
||||
:style {:stroke pc/secondary-color
|
||||
:stroke-width (/ 1 zoom)}}])])
|
||||
|
||||
(mf/defc path-editor
|
||||
[{:keys [shape zoom]}]
|
||||
|
||||
(let [editor-ref (mf/use-ref nil)
|
||||
edit-path-ref (pc/make-edit-path-ref (:id shape))
|
||||
hover-point (mf/use-state nil)
|
||||
|
||||
{:keys [edit-mode
|
||||
drag-handler
|
||||
prev-handler
|
||||
|
@ -158,9 +174,9 @@
|
|||
hover-points]
|
||||
:as edit-path} (mf/deref edit-path-ref)
|
||||
|
||||
{:keys [content]} shape
|
||||
content (ugp/apply-content-modifiers content content-modifiers)
|
||||
points (->> content ugp/content->points (into #{}))
|
||||
{base-content :content} shape
|
||||
content (ugp/apply-content-modifiers base-content content-modifiers)
|
||||
points (mf/use-memo (mf/deps content) #(->> content ugp/content->points (into #{})))
|
||||
last-command (last content)
|
||||
last-p (->> content last ugp/command->point)
|
||||
handlers (ugp/content->handlers content)
|
||||
|
@ -177,12 +193,34 @@
|
|||
#(doseq [key keys]
|
||||
(events/unlistenByKey key)))))
|
||||
|
||||
#_(hooks/use-stream
|
||||
ms/mouse-position
|
||||
(mf/deps shape)
|
||||
(fn [position]
|
||||
(reset! hover-point (gshp/path-closest-point shape position))))
|
||||
|
||||
(hooks/use-stream
|
||||
(mf/use-memo
|
||||
(mf/deps base-content selected-points zoom)
|
||||
#(snap/path-snap ms/mouse-position points selected-points zoom))
|
||||
|
||||
(fn [result]
|
||||
(prn "??" result)))
|
||||
|
||||
[:g.path-editor {:ref editor-ref}
|
||||
#_[:& snap-points {}]
|
||||
|
||||
|
||||
(when (and preview (not drag-handler))
|
||||
[:& path-preview {:command preview
|
||||
:from last-p
|
||||
:zoom zoom}])
|
||||
|
||||
(when @hover-point
|
||||
[:g.hover-point
|
||||
[:& path-point {:position @hover-point
|
||||
:zoom zoom}]])
|
||||
|
||||
(for [position points]
|
||||
(let [point-selected? (contains? selected-points position)
|
||||
point-hover? (contains? hover-points position)
|
||||
|
|
|
@ -171,7 +171,8 @@
|
|||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:view-box (utils/format-viewbox vbox)
|
||||
:style {:background-color (get options :background "#E8E9EA")}}
|
||||
:style {:background-color (get options :background "#E8E9EA")
|
||||
:pointer-events "none"}}
|
||||
|
||||
[:& (mf/provider muc/embed-ctx) {:value true}
|
||||
;; Render root shape
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue