diff --git a/frontend/shadow-cljs.edn b/frontend/shadow-cljs.edn index f8268a0aa1..746574064d 100644 --- a/frontend/shadow-cljs.edn +++ b/frontend/shadow-cljs.edn @@ -14,7 +14,7 @@ [danlentz/clj-uuid "0.1.9"] [frankiesardo/linked "1.3.0"] - [funcool/beicon "2021.04.12-1"] + [funcool/beicon "2021.04.27-2"] [funcool/cuerdas "2020.03.26-3"] [funcool/okulary "2020.04.14-0"] [funcool/potok "3.2.0"] diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 65756a5d3e..279682c2f4 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -7,6 +7,7 @@ (ns app.main.data.workspace.transforms "Events related with shapes transformations" (:require + [app.common.math :as mth] [app.common.data :as d] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] @@ -70,8 +71,11 @@ :bottom-left [ex sy])] (gpt/point x y))) -(defn finish-transform [state] - (update state :workspace-local dissoc :transform)) +(defn finish-transform [] + (ptk/reify ::finish-transform + ptk/UpdateEvent + (update [_ state] + (update state :workspace-local dissoc :transform)))) ;; -- RESIZE (defn start-resize @@ -152,7 +156,7 @@ (rx/mapcat (partial resize shape initial-position resizing-shapes)) (rx/take-until stoper)) (rx/of (apply-modifiers ids) - finish-transform))))))) + (finish-transform)))))))) (defn start-rotate @@ -190,7 +194,7 @@ (set-rotation delta-angle shapes group-center)))) (rx/take-until stoper)) (rx/of (apply-modifiers (map :id shapes)) - finish-transform)))))) + (finish-transform))))))) ;; -- MOVE @@ -291,19 +295,23 @@ (rx/map #(gpt/to-vec from-position %))) snap-delta (->> position - (rx/switch-map #(snap/closest-snap-move page-id shapes objects layout zoom %)))] + (rx/throttle 20) + (rx/switch-map + (fn [pos] + (->> (snap/closest-snap-move page-id shapes objects layout zoom pos) + (rx/map #(vector pos %))))))] (if (empty? shapes) (rx/empty) (rx/concat - (->> snap-delta - (rx/with-latest vector position) - (rx/map (fn [[delta pos]] (-> (gpt/add pos delta) (gpt/round 0)))) + (->> position + (rx/with-latest vector snap-delta) + (rx/map snap/correct-snap-point) (rx/map start-local-displacement)) (rx/of (set-modifiers ids) (apply-modifiers ids) (calculate-frame-for-move ids) - finish-transform)))))))) + (finish-transform))))))))) (defn- get-displacement-with-grid "Retrieve the correct displacement delta point for the @@ -372,7 +380,7 @@ (rx/of (set-modifiers selected) (apply-modifiers selected) - finish-transform))) + (finish-transform)))) (rx/empty)))))) diff --git a/frontend/src/app/main/snap.cljs b/frontend/src/app/main/snap.cljs index 3e7ebd8709..e73f4c7779 100644 --- a/frontend/src/app/main/snap.cljs +++ b/frontend/src/app/main/snap.cljs @@ -19,7 +19,7 @@ [beicon.core :as rx] [clojure.set :as set])) -(defonce ^:private snap-accuracy 5) +(defonce ^:private snap-accuracy 10) (defonce ^:private snap-path-accuracy 10) (defonce ^:private snap-distance-accuracy 10) @@ -84,7 +84,7 @@ (rx/map (remove-from-snap-points filter-shapes)) (rx/map (get-min-distance-snap points coord))))) -(defn snap->vector [[from-x to-x] [from-y to-y]] +(defn snap->vector [[[from-x to-x] [from-y to-y]]] (when (or from-x to-x from-y to-y) (let [from (gpt/point (or from-x 0) (or from-y 0)) to (gpt/point (or to-x 0) (or to-y 0))] @@ -94,8 +94,9 @@ [page-id frame-id points filter-shapes zoom] (let [snap-x (search-snap page-id frame-id points :x filter-shapes zoom) snap-y (search-snap page-id frame-id points :y filter-shapes zoom)] - ;; snap-x is the second parameter because is the "source" to combine - (rx/combine-latest snap->vector snap-y snap-x))) + (->> (rx/combine-latest snap-x snap-y) + (rx/map snap->vector)))) + (defn sr-distance [coord sr1 sr2] (let [c1 (if (= coord :x) :x1 :y1) @@ -174,8 +175,7 @@ (if (mth/finite? min-snap) [0 min-snap] nil))) (defn search-snap-distance [selrect coord shapes-lt shapes-gt zoom] - (->> shapes-lt - (rx/combine-latest vector shapes-gt) + (->> (rx/combine-latest shapes-lt shapes-gt) (rx/map (fn [[shapes-lt shapes-gt]] (calculate-snap coord selrect shapes-lt shapes-gt zoom))))) @@ -203,7 +203,8 @@ (d/mapm #(select-shapes-area page-id shapes objects %2))) snap-x (search-snap-distance selrect :x (:left areas) (:right areas) zoom) snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas) zoom)] - (rx/combine-latest snap->vector snap-y snap-x))))))) + (rx/combine-latest snap-x snap-y)))) + (rx/map snap->vector)))) (defn closest-snap-point [page-id shapes layout zoom point] @@ -331,3 +332,18 @@ (update :y first) (gpt/point))) + +(defn correct-snap-point + "Snaps a position given an old snap to a different position. We use this to provide a temporal + snap while the new is being processed." + [[position [snap-pos snap-delta]]] + (let [dx (if (not= 0 (:x snap-delta)) + (- (+ (:x snap-pos) (:x snap-delta)) (:x position)) + 0) + dy (if (not= 0 (:y snap-delta)) + (- (+ (:y snap-pos) (:y snap-delta)) (:y position)) + 0)] + + (cond-> position + (<= (mth/abs dx) snap-accuracy) (update :x + dx) + (<= (mth/abs dy) snap-accuracy) (update :y + dy)))) diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs index b940e886f6..ae6c809ad3 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_distances.cljs @@ -233,9 +233,8 @@ (rx/map #(set/difference % selected)) (rx/map #(->> % (map (partial get @refs/workspace-page-objects))))) (rx/of nil))))] - - (->> (query-side lt-side) - (rx/combine-latest vector (query-side gt-side))))) + (rx/combine-latest (query-side lt-side) + (query-side gt-side)))) [lt-shapes gt-shapes] @to-measure diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs index 00ea590834..9f7e24b278 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs @@ -120,10 +120,10 @@ (mf/use-effect (fn [] (let [sub (->> subject - (rx/switch-map #(rx/combine-latest - d/concat - (get-snap :y %) - (get-snap :x %))) + (rx/switch-map #(rx/combine-latest (get-snap :x %) + (get-snap :y %))) + (rx/map (fn [result] + (apply d/concat (seq result)))) (rx/subs #(let [rs (filter (fn [[_ snaps _]] (> (count snaps) 0)) %)] (reset! state rs))))]