From b2e01cd52b3d756ad063bad51b340009ec518b7d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 13 May 2021 15:02:06 +0200 Subject: [PATCH 1/3] :zap: Performance improvements --- common/app/common/geom/shapes/intersect.cljc | 12 +- docker/devenv/files/nginx.conf | 2 +- frontend/src/app/main/data/workspace.cljs | 14 +- .../src/app/main/data/workspace/changes.cljs | 167 ++++++------------ .../app/main/data/workspace/transforms.cljs | 62 ++++--- .../app/main/ui/workspace/viewport/utils.cljs | 2 +- frontend/src/app/worker/selection.cljs | 2 +- 7 files changed, 122 insertions(+), 139 deletions(-) diff --git a/common/app/common/geom/shapes/intersect.cljc b/common/app/common/geom/shapes/intersect.cljc index 0b6fbcd6f5..2b55cb3392 100644 --- a/common/app/common/geom/shapes/intersect.cljc +++ b/common/app/common/geom/shapes/intersect.cljc @@ -174,9 +174,17 @@ "Checks if the given rect overlaps with the path in any point" [shape rect] - (let [rect-points (gpr/rect->points rect) + (let [;; If paths are too complex the intersection is too expensive + ;; we fallback to check its bounding box otherwise the performance penalty + ;; is too big + ;; TODO: Look for ways to optimize this operation + simple? (> (count (:content shape)) 100) + + rect-points (gpr/rect->points rect) rect-lines (points->lines rect-points) - path-lines (gpp/path->lines shape) + path-lines (if simple? + (points->lines (:points shape)) + (gpp/path->lines shape)) start-point (-> shape :content (first) :params (gpt/point))] (or (is-point-inside-nonzero? (first rect-points) path-lines) diff --git a/docker/devenv/files/nginx.conf b/docker/devenv/files/nginx.conf index eefd05cd09..ee7e37bb0b 100644 --- a/docker/devenv/files/nginx.conf +++ b/docker/devenv/files/nginx.conf @@ -46,7 +46,7 @@ http { listen 3449 default_server; server_name _; - client_max_body_size 5M; + client_max_body_size 20M; charset utf-8; proxy_http_version 1.1; diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 6a3ce495f4..53097aac68 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1164,11 +1164,15 @@ (ptk/reify ::update-shape-flags ptk/WatchEvent (watch [it state stream] - (letfn [(update-fn [obj] - (cond-> obj - (boolean? blocked) (assoc :blocked blocked) - (boolean? hidden) (assoc :hidden hidden)))] - (rx/of (dch/update-shapes-recursive [id] update-fn)))))) + (let [update-fn + (fn [obj] + (cond-> obj + (boolean? blocked) (assoc :blocked blocked) + (boolean? hidden) (assoc :hidden hidden))) + + objects (wsh/lookup-page-objects state) + ids (d/concat [id] (cp/get-children id objects))] + (rx/of (dch/update-shapes ids update-fn)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/changes.cljs b/frontend/src/app/main/data/workspace/changes.cljs index 56c918f385..b7be2c2eb9 100644 --- a/frontend/src/app/main/data/workspace/changes.cljs +++ b/frontend/src/app/main/data/workspace/changes.cljs @@ -11,6 +11,7 @@ [app.common.pages.spec :as spec] [app.common.spec :as us] [app.main.data.workspace.undo :as dwu] + [app.main.data.workspace.state-helpers :as wsh] [app.main.worker :as uw] [app.main.store :as st] [app.util.logging :as log] @@ -31,127 +32,75 @@ (def commit-changes? (ptk/type? ::commit-changes)) -(defn- generate-operations - ([ma mb] (generate-operations ma mb false)) - ([ma mb undo?] - (let [ops (let [ma-keys (set (keys ma)) - mb-keys (set (keys mb)) - added (set/difference mb-keys ma-keys) - removed (set/difference ma-keys mb-keys) - both (set/intersection ma-keys mb-keys)] - (d/concat - (mapv #(array-map :type :set :attr % :val (get mb %)) added) - (mapv #(array-map :type :set :attr % :val nil) removed) - (loop [items (seq both) - result []] - (if items - (let [k (first items) - vma (get ma k) - vmb (get mb k)] - (if (= vma vmb) - (recur (next items) result) - (recur (next items) - (conj result {:type :set - :attr k - :val vmb - :ignore-touched undo?})))) - result))))] - (if undo? - (conj ops {:type :set-touched :touched (:touched mb)}) - ops)))) +(defn- generate-operation + "Given an object old and new versions and an attribute will append into changes + the set and undo operations" + [changes attr old new] + (let [old-val (get old attr) + new-val (get new attr)] + (if (= old-val new-val) + changes + (-> changes + (update :rops conj {:type :set :attr attr :val new-val}) + (update :uops conj {:type :set :attr attr :val old-val :ignore-touched true}))))) + +(defn- update-shape-changes + "Calculate the changes and undos to be done when a function is applied to a + single object" + [changes page-id objects update-fn attrs id] + (let [old-obj (get objects id) + new-obj (update-fn old-obj) + + attrs (or attrs (d/concat #{} (keys old-obj) (keys new-obj))) + + {rops :rops uops :uops} + (reduce #(generate-operation %1 %2 old-obj new-obj) + {:rops [] :uops []} + attrs) + + uops (cond-> uops + (not (empty? uops)) + (conj {:type :set-touched :touched (:touched old-obj)})) + + change {:type :mod-obj :page-id page-id :id id}] + + (cond-> changes + (not (empty? rops)) + (update :rch conj (assoc change :operations rops)) + + (not (empty? uops)) + (update :uch conj (assoc change :operations uops))))) (defn update-shapes ([ids f] (update-shapes ids f nil)) - ([ids f {:keys [reg-objects? save-undo?] - :or {reg-objects? false save-undo? true}}] + ([ids f {:keys [reg-objects? save-undo? keys] + :or {reg-objects? false save-undo? true attrs nil}}] + (us/assert ::coll-of-uuid ids) (us/assert fn? f) + (ptk/reify ::update-shapes ptk/WatchEvent (watch [it state stream] (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data :pages-index page-id :objects]) - reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}] - (loop [ids (seq ids) - rch [] - uch []] - (if (nil? ids) - (rx/of (let [has-rch? (not (empty? rch)) - has-uch? (not (empty? uch)) - rch (cond-> rch (and has-rch? reg-objects?) (conj reg-objects)) - uch (cond-> uch (and has-rch? reg-objects?) (conj reg-objects))] - (when (and has-rch? has-uch?) - (commit-changes {:redo-changes rch - :undo-changes uch - :origin it - :save-undo? save-undo?})))) + objects (wsh/lookup-page-objects state) + reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)} - (let [id (first ids) - obj1 (get objects id) - obj2 (f obj1) - rch-operations (generate-operations obj1 obj2) - uch-operations (generate-operations obj2 obj1 true) - rchg {:type :mod-obj - :page-id page-id - :operations rch-operations - :id id} - uchg {:type :mod-obj - :page-id page-id - :operations uch-operations - :id id}] - (recur (next ids) - (if (empty? rch-operations) rch (conj rch rchg)) - (if (empty? uch-operations) uch (conj uch uchg))))))))))) + {redo-changes :rch undo-changes :uch} + (reduce #(update-shape-changes %1 page-id objects f keys %2) + {:rch [] :uch []} ids)] -(defn update-shapes-recursive - [ids f] - (us/assert ::coll-of-uuid ids) - (us/assert fn? f) - (letfn [(impl-get-children [objects id] - (cons id (cp/get-children id objects))) + (when-not (empty? redo-changes) + (let [redo-changes (cond-> redo-changes + reg-objects? (conj reg-objects)) - (impl-gen-changes [objects page-id ids] - (loop [sids (seq ids) - cids (seq (impl-get-children objects (first sids))) - rchanges [] - uchanges []] - (cond - (nil? sids) - [rchanges uchanges] + undo-changes (cond-> undo-changes + reg-objects? (conj reg-objects))] - (nil? cids) - (recur (next sids) - (seq (impl-get-children objects (first (next sids)))) - rchanges - uchanges) - - :else - (let [id (first cids) - obj1 (get objects id) - obj2 (f obj1) - rops (generate-operations obj1 obj2) - uops (generate-operations obj2 obj1 true) - rchg {:type :mod-obj - :page-id page-id - :operations rops - :id id} - uchg {:type :mod-obj - :page-id page-id - :operations uops - :id id}] - (recur sids - (next cids) - (conj rchanges rchg) - (conj uchanges uchg))))))] - (ptk/reify ::update-shapes-recursive - ptk/WatchEvent - (watch [it state stream] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data :pages-index page-id :objects]) - [rchanges uchanges] (impl-gen-changes objects page-id (seq ids))] - (rx/of (commit-changes {:redo-changes rchanges - :undo-changes uchanges - :origin it}))))))) + (rx/of (commit-changes {:redo-changes redo-changes + :undo-changes undo-changes + :origin it + :save-undo? save-undo?}))))))))) (defn update-indices [page-id changes] @@ -222,4 +171,4 @@ (when (and save-undo? (seq undo-changes)) (let [entry {:undo-changes undo-changes :redo-changes redo-changes}] - (rx/of (dwu/append-undo entry))))))))))) \ No newline at end of file + (rx/of (dwu/append-undo entry))))))))))) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index dd4171ab1f..e2b3b99b85 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -320,8 +320,7 @@ (rx/map snap/correct-snap-point) (rx/map start-local-displacement)) - (rx/of (set-modifiers ids) - (apply-modifiers ids) + (rx/of (apply-modifiers ids {:set-modifiers? true}) (calculate-frame-for-move ids) (finish-transform))))))))) @@ -390,8 +389,7 @@ (rx/map start-local-displacement)) (rx/of (move-selected direction shift?))) - (rx/of (set-modifiers selected) - (apply-modifiers selected) + (rx/of (apply-modifiers selected {:set-modifiers? true}) (finish-transform)))) (rx/empty)))))) @@ -469,22 +467,46 @@ (rx/of (apply-modifiers ids))))))) (defn apply-modifiers - [ids] - (us/verify (s/coll-of uuid?) ids) - (ptk/reify ::apply-modifiers - ptk/WatchEvent - (watch [it state stream] - (let [objects (wsh/lookup-page-objects state) - children-ids (->> ids (mapcat #(cp/get-children % objects))) - ids-with-children (d/concat [] children-ids ids) - object-modifiers (get state :workspace-modifiers)] - (rx/of (dwu/start-undo-transaction) - (dch/update-shapes ids-with-children (fn [shape] - (-> shape - (merge (get object-modifiers (:id shape))) - (gsh/transform-shape))) {:reg-objects? true}) - (clear-local-transform) - (dwu/commit-undo-transaction)))))) + ([ids] + (apply-modifiers ids nil)) + + ([ids {:keys [set-modifiers?] + :or {set-modifiers? false}}] + (us/verify (s/coll-of uuid?) ids) + (ptk/reify ::apply-modifiers + ptk/WatchEvent + (watch [it state stream] + (let [objects (wsh/lookup-page-objects state) + children-ids (->> ids (mapcat #(cp/get-children % objects))) + ids-with-children (d/concat [] children-ids ids) + + state (if set-modifiers? + (ptk/update (set-modifiers ids) state) + state) + object-modifiers (get state :workspace-modifiers)] + + (rx/of (dwu/start-undo-transaction) + (dch/update-shapes + ids-with-children + (fn [shape] + (-> shape + (merge (get object-modifiers (:id shape))) + (gsh/transform-shape))) + {:reg-objects? true + ;; Attributes that can change in the transform. This way we don't have to check + ;; all the attributes + :attrs [:selrect :points + :x :y + :width :height + :content + :transform + :transform-inverse + :rotation + :flip-x + :flip-y] + }) + (clear-local-transform) + (dwu/commit-undo-transaction))))))) ;; --- Update Dimensions diff --git a/frontend/src/app/main/ui/workspace/viewport/utils.cljs b/frontend/src/app/main/ui/workspace/viewport/utils.cljs index a1e6f6a83a..092da6bbce 100644 --- a/frontend/src/app/main/ui/workspace/viewport/utils.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/utils.cljs @@ -24,7 +24,7 @@ (.-parentNode shape-node) (and (some? thumb-node) (= :frame type)) - thumb-node + (.-parentNode thumb-node) :else shape-node)] diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index b78f3c7f17..21667849be 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -122,9 +122,9 @@ (into [] (comp (map #(unchecked-get % "data")) (filter match-criteria?) + (filter overlaps?) (filter (comp overlaps? :frame)) (filter (comp overlaps-masks? :masks)) - (filter overlaps?) (map add-z-index)) result) From 93d8c171bebde63448beb9a1addcf3d76c6f381b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 14 May 2021 15:38:04 +0200 Subject: [PATCH 2/3] :bug: Fix problems with snap index regeneration --- .../app/tests/test_common_geom_shapes.clj | 18 ++++---- common/app/common/geom/shapes/transforms.cljc | 44 +++++++++++-------- common/app/common/pages/helpers.cljc | 7 +-- .../main/data/workspace/state_helpers.cljs | 8 ++-- .../app/main/data/workspace/transforms.cljs | 26 +++++++++++ .../src/app/main/ui/workspace/shapes.cljs | 2 +- .../src/app/main/ui/workspace/viewport.cljs | 10 ++++- .../main/ui/workspace/viewport/outline.cljs | 10 ++--- .../main/ui/workspace/viewport/selection.cljs | 5 +-- .../ui/workspace/viewport/snap_points.cljs | 17 +++++-- frontend/src/app/util/geom/grid.cljs | 4 +- frontend/src/app/worker/snaps.cljs | 20 +++++++-- 12 files changed, 118 insertions(+), 53 deletions(-) diff --git a/backend/tests/app/tests/test_common_geom_shapes.clj b/backend/tests/app/tests/test_common_geom_shapes.clj index b53d3ebc59..8019da9940 100644 --- a/backend/tests/app/tests/test_common_geom_shapes.clj +++ b/backend/tests/app/tests/test_common_geom_shapes.clj @@ -52,7 +52,7 @@ (t/testing "Shape without modifiers should stay the same" (t/are [type] (let [shape-before (create-test-shape type) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (= shape-before shape-after)) :rect :path)) @@ -61,7 +61,7 @@ (t/are [type] (let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}] (let [shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/is (not= shape-before shape-after)) (t/is (close? (get-in shape-before [:selrect :x]) @@ -82,7 +82,7 @@ (t/are [type] (let [modifiers {:displacement (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/are [prop] (t/is (close? (get-in shape-before [:selrect prop]) (get-in shape-after [:selrect prop]))) @@ -95,7 +95,7 @@ :resize-vector (gpt/point 2 2) :resize-transform (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/is (not= shape-before shape-after)) (t/is (close? (get-in shape-before [:selrect :x]) @@ -117,7 +117,7 @@ :resize-vector (gpt/point 1 1) :resize-transform (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/are [prop] (t/is (close? (get-in shape-before [:selrect prop]) (get-in shape-after [:selrect prop]))) @@ -130,7 +130,7 @@ :resize-vector (gpt/point 0 0) :resize-transform (gmt/matrix)} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/is (> (get-in shape-before [:selrect :width]) (get-in shape-after [:selrect :width]))) (t/is (> (get-in shape-after [:selrect :width]) 0)) @@ -144,7 +144,7 @@ (t/are [type] (let [modifiers {:rotation 30} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/is (not= shape-before shape-after)) @@ -168,7 +168,7 @@ (t/are [type] (let [modifiers {:rotation 0} shape-before (create-test-shape type {:modifiers modifiers}) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (t/are [prop] (t/is (close? (get-in shape-before [:selrect prop]) (get-in shape-after [:selrect prop]))) @@ -180,7 +180,7 @@ (let [modifiers {:displacement (gmt/matrix)} shape-before (-> (create-test-shape type {:modifiers modifiers}) (assoc :selrect selrect)) - shape-after (gsh/transform-shape shape-before)] + shape-after (gsh/transform-shape shape-before {:round-coords? false})] (= (:selrect shape-before) (:selrect shape-after))) :rect {:x 0 :y 0 :width ##Inf :height ##Inf} diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index dcfdd31fcb..6929ed0576 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -266,7 +266,7 @@ (defn apply-transform "Given a new set of points transformed, set up the rectangle so it keeps its properties. We adjust de x,y,width,height and create a custom transform" - [shape transform] + [shape transform round-coords?] ;; (let [points (-> shape :points (transform-points transform)) center (gco/center-points points) @@ -283,6 +283,11 @@ center (:width points-temp-dim) (:height points-temp-dim)) + (cond-> round-coords? + (-> (update :x #(mth/precision % 0)) + (update :y #(mth/precision % 0)) + (update :width #(mth/precision % 0)) + (update :height #(mth/precision % 0)))) (update :width max 1) (update :height max 1)) @@ -297,11 +302,7 @@ :else (-> shape - (merge rect-shape) - (update :x #(mth/precision % 0)) - (update :y #(mth/precision % 0)) - (update :width #(mth/precision % 0)) - (update :height #(mth/precision % 0))))] + (merge rect-shape)))] (as-> shape $ (update $ :transform #(gmt/multiply (or % (gmt/matrix)) matrix)) (update $ :transform-inverse #(gmt/multiply matrix-inverse (or % (gmt/matrix)))) @@ -347,18 +348,23 @@ %))) shape)) -(defn transform-shape [shape] - (let [shape (apply-displacement shape) - center (gco/center-shape shape) - modifiers (:modifiers shape)] - (if (and modifiers center) - (let [transform (modifiers->transform center modifiers)] - (-> shape - (set-flip modifiers) - (apply-transform transform) - (apply-text-resize shape modifiers) - (dissoc :modifiers))) - shape))) +(defn transform-shape + ([shape] + (transform-shape shape nil)) + + ([shape {:keys [round-coords?] + :or {round-coords? true}}] + (let [shape (apply-displacement shape) + center (gco/center-shape shape) + modifiers (:modifiers shape)] + (if (and modifiers center) + (let [transform (modifiers->transform center modifiers)] + (-> shape + (set-flip modifiers) + (apply-transform transform round-coords?) + (apply-text-resize shape modifiers) + (dissoc :modifiers))) + shape)))) (defn update-group-viewbox "Updates the viewbox for groups imported from SVG's" @@ -407,5 +413,5 @@ ;; need to remove the flip flags (assoc :flip-x false) (assoc :flip-y false) - (apply-transform (gmt/matrix))))) + (apply-transform (gmt/matrix) true)))) diff --git a/common/app/common/pages/helpers.cljc b/common/app/common/pages/helpers.cljc index 1fce3111b0..87299b2a3d 100644 --- a/common/app/common/pages/helpers.cljc +++ b/common/app/common/pages/helpers.cljc @@ -461,8 +461,9 @@ (defn merge-modifiers [objects modifiers] - (let [set-modifier (fn [objects [id modifiers]] - (-> objects - (d/update-when id assoc :modifiers modifiers)))] + (let [set-modifier + (fn [objects [id modifiers]] + (-> objects + (d/update-when id merge modifiers)))] (->> modifiers (reduce set-modifier objects)))) diff --git a/frontend/src/app/main/data/workspace/state_helpers.cljs b/frontend/src/app/main/data/workspace/state_helpers.cljs index c7efb8627b..9ce4a3d3ff 100644 --- a/frontend/src/app/main/data/workspace/state_helpers.cljs +++ b/frontend/src/app/main/data/workspace/state_helpers.cljs @@ -6,7 +6,8 @@ (ns app.main.data.workspace.state-helpers (:require - [app.common.data :as d])) + [app.common.data :as d] + [app.common.pages :as cp])) (defn lookup-page-objects ([state] @@ -26,8 +27,9 @@ (defn lookup-selected [state] - (let [selected (get-in state [:workspace-local :selected]) - objects (lookup-page-objects state) + (let [objects (lookup-page-objects state) + selected (->> (get-in state [:workspace-local :selected]) + (cp/clean-loops objects)) is-present? (fn [id] (contains? objects id))] (into (d/ordered-set) (filter is-present?) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index e2b3b99b85..e2c0ad42f9 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -72,6 +72,27 @@ :bottom-left [ex sy])] (gpt/point x y))) +(defn- fix-init-point + "Fix the initial point so the resizes are accurate" + [initial handler shape] + (let [{:keys [x y width height]} (:selrect shape) + {:keys [rotation]} shape + rotation (or rotation 0)] + (if (= rotation 0) + (cond-> initial + (contains? #{:left :top-left :bottom-left} handler) + (assoc :x x) + + (contains? #{:right :top-right :bottom-right} handler) + (assoc :x (+ x width)) + + (contains? #{:top :top-right :top-left} handler) + (assoc :y y) + + (contains? #{:bottom :bottom-right :bottom-left} handler) + (assoc :y (+ y height))) + initial))) + (defn finish-transform [] (ptk/reify ::finish-transform ptk/UpdateEvent @@ -84,6 +105,10 @@ (letfn [(resize [shape initial resizing-shapes layout [point lock? point-snap]] (let [{:keys [width height]} (:selrect shape) {:keys [rotation]} shape + rotation (or rotation 0) + + initial (fix-init-point initial handler shape) + shapev (-> (gpt/point width height)) scale-text (:scale-text layout) @@ -253,6 +278,7 @@ frame-id (cp/frame-id-by-position objects position) moving-shapes (->> ids + (cp/clean-loops objects) (map #(get objects %)) (remove #(= (:frame-id %) frame-id))) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 9b30723fd4..48b6f00e86 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -72,7 +72,7 @@ [props] (let [shape (obj/get props "shape") frame (obj/get props "frame") - shape (-> (geom/transform-shape shape) + shape (-> (geom/transform-shape shape {:round-coords? false}) (geom/translate-to-frame frame)) opts #js {:shape shape :frame frame} diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 2adbe4189e..392232143e 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.workspace.viewport (:require [app.common.data :as d] + [app.common.pages :as cp] [app.common.geom.shapes :as gsh] [app.main.refs :as refs] [app.main.ui.context :as ctx] @@ -61,7 +62,9 @@ options (mf/deref refs/workspace-page-options) objects (mf/deref refs/workspace-page-objects) object-modifiers (mf/deref refs/workspace-modifiers) - objects (d/deep-merge objects object-modifiers) + objects (mf/use-memo + (mf/deps objects object-modifiers) + #(cp/merge-modifiers objects object-modifiers)) ;; STATE alt? (mf/use-state false) @@ -135,7 +138,9 @@ show-prototypes? (= options-mode :prototype) show-selection-handlers? (seq 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 (or (contains? layout :dynamic-alignment) + (contains? layout :snap-grid)) + (or drawing-obj transform)) show-selrect? (and selrect (empty? drawing)) show-measures? (and (not transform) (not path-editing?) show-distances?)] @@ -283,6 +288,7 @@ :zoom zoom :page-id page-id :selected selected + :objects objects :modifiers modifiers}]) (when show-snap-distance? diff --git a/frontend/src/app/main/ui/workspace/viewport/outline.cljs b/frontend/src/app/main/ui/workspace/viewport/outline.cljs index e292b16dcd..6c87337768 100644 --- a/frontend/src/app/main/ui/workspace/viewport/outline.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/outline.cljs @@ -29,7 +29,7 @@ (mf/deps shape) #(when path? (upf/format-path (:content shape)))) - {:keys [id x y width height]} shape + {:keys [id x y width height selrect]} shape outline-type (case (:type shape) :circle "ellipse" @@ -53,10 +53,10 @@ {:d path-data :transform nil} - {:x x - :y y - :width width - :height height})] + {:x (:x selrect) + :y (:y selrect) + :width (:width selrect) + :height (:height selrect)})] [:> outline-type (map->obj (merge common props))])) diff --git a/frontend/src/app/main/ui/workspace/viewport/selection.cljs b/frontend/src/app/main/ui/workspace/viewport/selection.cljs index fa23c720c5..85b91a8ffb 100644 --- a/frontend/src/app/main/ui/workspace/viewport/selection.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/selection.cljs @@ -241,8 +241,7 @@ disable-handlers (obj/get props "disable-handlers") current-transform (mf/deref refs/current-transform) - selrect (-> (:selrect shape) - minimum-selrect) + selrect (:selrect shape) transform (geom/transform-matrix shape {:no-flip true})] (when (not (#{:move :rotate} current-transform)) @@ -327,7 +326,7 @@ (mf/defc single-selection-handlers [{:keys [shape zoom color disable-handlers on-move-selected] :as props}] (let [shape-id (:id shape) - shape (geom/transform-shape shape) + shape (geom/transform-shape shape {:round-coords? false}) frame (mf/deref (refs/object-by-id (:frame-id shape))) frame (when-not (= (:id frame) uuid/zero) frame) 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 f9c4f18ca4..9dda3ac8fa 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs @@ -6,6 +6,7 @@ (ns app.main.ui.workspace.viewport.snap-points (:require + [app.common.pages :as cp] [app.common.math :as mth] [app.common.data :as d] [app.common.geom.point :as gpt] @@ -151,15 +152,25 @@ (mf/defc snap-points {::mf/wrap [mf/memo]} - [{:keys [layout zoom selected page-id drawing transform modifiers] :as props}] - (let [shapes (mf/deref (refs/objects-by-id selected)) - filter-shapes (mf/deref refs/selected-shapes-with-children) + [{:keys [layout zoom objects selected page-id drawing transform modifiers] :as props}] + + (let [;; shapes (mf/deref (refs/objects-by-id selected)) + ;; filter-shapes (mf/deref refs/selected-shapes-with-children) + + shapes (->> selected + (map #(get objects %)) + (filterv (comp not nil?))) + filter-shapes (into #{} + (mapcat #(cp/get-object-with-children % objects)) + selected) + filter-shapes (fn [id] (if (= id :layout) (or (not (contains? layout :display-grid)) (not (contains? layout :snap-grid))) (or (filter-shapes id) (not (contains? layout :dynamic-alignment))))) + shapes (if drawing [drawing] shapes)] (when (or drawing transform) [:& snap-feedback {:shapes shapes diff --git a/frontend/src/app/util/geom/grid.cljs b/frontend/src/app/util/geom/grid.cljs index c1f882204e..bd8f58bd19 100644 --- a/frontend/src/app/util/geom/grid.cljs +++ b/frontend/src/app/util/geom/grid.cljs @@ -88,7 +88,9 @@ (defn grid-snap-points "Returns the snap points for a given grid" - ([shape coord] (mapcat #(grid-snap-points shape % coord) (:grids shape))) + ([shape coord] + (mapcat #(grid-snap-points shape % coord) (:grids shape))) + ([shape {:keys [type display params] :as grid} coord] (when (:display grid) (case type diff --git a/frontend/src/app/worker/snaps.cljs b/frontend/src/app/worker/snaps.cljs index aa531dd4f1..a2c3954483 100644 --- a/frontend/src/app/worker/snaps.cljs +++ b/frontend/src/app/worker/snaps.cljs @@ -71,13 +71,23 @@ (fn [frame-id shapes] {:x (-> (rt/make-tree) (add-coord-data frame-id shapes :x)) :y (-> (rt/make-tree) (add-coord-data frame-id shapes :y))})] - (d/mapm create-index shapes-data))) +;; Attributes that will change the values of their snap +(def snap-attrs [:x :y :width :height :selrect :grids]) + (defn- update-snap-data [snap-data old-objects new-objects] - (let [changed? #(not= (get old-objects %) (get new-objects %)) + (let [changed? (fn [id] + (let [oldv (get old-objects id) + newv (get new-objects id)] + ;; Check first without select-keys because is faster if they are + ;; the same reference + (and (not= oldv newv) + (not= (select-keys oldv snap-attrs) + (select-keys newv snap-attrs))))) + is-deleted-frame? #(and (not= uuid/zero %) (contains? old-objects %) (not (contains? new-objects %)) @@ -119,9 +129,9 @@ :y (rt/make-tree)}))] (as-> snap-data $ + (reduce delete-data $ to-delete) (reduce add-frames $ frames-to-add) (reduce add-data $ to-add) - (reduce delete-data $ to-delete) (reduce delete-frames $ frames-to-delete)))) (defn- log-state @@ -160,8 +170,10 @@ (defmethod impl/handler :snaps/update-index [{:keys [page-id old-objects new-objects] :as message}] - ;; TODO: Check the difference and update the index acordingly (swap! state update-page page-id old-objects new-objects) + + ;; Uncomment this to regenerate the index everytime + #_(swap! state index-page page-id new-objects) ;; (log-state) nil) From ea22f3f81ce0d4576b39b0e4ad5efd052ddf34fd Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 17 May 2021 11:34:39 +0200 Subject: [PATCH 3/3] :bug: Fixes problem on shape creation --- frontend/src/app/main/data/workspace/drawing/common.cljs | 7 +++++-- frontend/src/app/main/ui/workspace/viewport/actions.cljs | 2 +- .../app/main/ui/workspace/viewport/thumbnail_renderer.cljs | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index f31d5be140..92db099600 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -28,7 +28,6 @@ (watch [_ state stream] (let [shape (get-in state [:workspace-drawing :object])] (rx/concat - (rx/of clear-drawing) (when (:initialized? shape) (let [page-id (:current-page-id state) shape-click-width (case (:type shape) @@ -65,4 +64,8 @@ :page-id page-id :rect (:selrect shape)}) (rx/map #(dwc/move-shapes-into-frame (:id shape) %))) - (rx/empty)))))))))) + (rx/empty))))) + + ;; Delay so the mouse event can read the drawing state + (->> (rx/of clear-drawing) + (rx/delay 0))))))) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index f7550428fb..2b6d7d25bf 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -142,7 +142,7 @@ (not selected?) (not edition) (not drawing-path?) - (not (#{:comments :path} drawing-tool))) + (not drawing-tool)) (st/emit! (dw/select-shape (:id @hover))))))))) (defn on-double-click diff --git a/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs b/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs index 92213c131d..79b41e0d3c 100644 --- a/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/thumbnail_renderer.cljs @@ -99,7 +99,8 @@ (timers/schedule (fn [] (st/emit! (dwc/update-shapes [@shape-id] - #(assoc % :thumbnail data))) + #(assoc % :thumbnail data) + {:save-undo? false})) (rx/push! next :next))))) on-frame-not-found