Improve selection performance

This commit is contained in:
alonso.torres 2021-11-30 16:23:40 +01:00
parent b05908a760
commit fb9b023fae
6 changed files with 76 additions and 36 deletions

View file

@ -149,6 +149,7 @@
(d/export gpr/points->rect)
(d/export gpr/center->rect)
(d/export gpr/join-rects)
(d/export gpr/contains-selrect?)
(d/export gtr/move)
(d/export gtr/absolute-move)

View file

@ -121,3 +121,11 @@
(or (< px x2) (s= px x2))
(or (> py y1) (s= py y1))
(or (< py y2) (s= py y2)))))
(defn contains-selrect?
"Check if a selrect sr2 is contained inside sr1"
[sr1 sr2]
(and (>= (:x1 sr2) (:x1 sr1))
(<= (:x2 sr2) (:x2 sr1))
(>= (:y1 sr2) (:y1 sr1))
(<= (:y2 sr2) (:y2 sr1))))

View file

@ -120,7 +120,7 @@
(->> move-stream
;; When transforming shapes we stop querying the worker
(rx/filter #(not (some? (mf/ref-val transform-ref))))
(rx/switch-map query-point))
(rx/merge-map query-point))
(->> move-stream
;; When transforming shapes we stop querying the worker

View file

@ -90,6 +90,7 @@
"translate(" (* zoom x) ", " (* zoom y) ")")))
(mf/defc frame-title
{::mf/wrap [mf/memo]}
[{:keys [frame modifiers selected? zoom on-frame-enter on-frame-leave on-frame-select]}]
(let [{:keys [width x y]} (gsh/transform-shape frame)
label-pos (gpt/point x (- y (/ 10 zoom)))

View file

@ -35,6 +35,7 @@
(->> (:stream worker)
(rx/filter #(= (:reply-to %) sender-id))
(take-messages)
(rx/filter (complement :dropped))
(rx/map handle-response)))
(rx/empty)))))
@ -91,9 +92,8 @@
worker))
(defn- handle-response
[{:keys [payload error dropped]}]
(when-not dropped
[{:keys [payload error]}]
(if-let [{:keys [data message]} error]
(throw (ex-info message data))
payload)))
payload))

View file

@ -15,6 +15,8 @@
[clojure.set :as set]
[okulary.core :as l]))
(def ^:const padding-percent 0.10)
(defonce state (l/atom {}))
(defn index-shape
@ -37,28 +39,47 @@
:clip-parents clip-parents
:parents parents)))))
(defn objects-bounds
"Calculates the bounds of the quadtree given a objects map."
[objects]
(-> objects
(dissoc uuid/zero)
vals
gsh/selection-rect))
(defn add-padding-bounds
"Adds a padding to the bounds defined as a percent in the constant `padding-percent`.
For a value of 0.1 will add a 20% width increase (2 x padding)"
[bounds]
(let [width-pad (* (:width bounds) padding-percent)
height-pad (* (:height bounds) padding-percent)]
(-> bounds
(update :x - width-pad)
(update :x1 - width-pad)
(update :x2 + width-pad)
(update :y1 - height-pad)
(update :y2 + height-pad)
(update :width + width-pad width-pad)
(update :height + height-pad height-pad))))
(defn- create-index
[objects]
(let [shapes (-> objects (dissoc uuid/zero) (vals))
(let [shapes (-> objects (dissoc uuid/zero) vals)
parents-index (cp/generate-child-all-parents-index objects)
clip-parents-index (cp/create-clip-index objects parents-index)
bounds #js {:x (int -0.5e7)
:y (int -0.5e7)
:width (int 1e7)
:height (int 1e7)}
bounds (-> objects objects-bounds add-padding-bounds)
index (reduce (index-shape objects parents-index clip-parents-index)
(qdt/create bounds)
(qdt/create (clj->js bounds))
shapes)
z-index (cp/calculate-z-index objects)]
{:index index :z-index z-index}))
{:index index :z-index z-index :bounds bounds}))
(defn- update-index
[{index :index z-index :z-index :as data} old-objects new-objects]
(if (some? data)
(let [changes? (fn [id]
(not= (get old-objects id)
(get new-objects id)))
@ -82,10 +103,7 @@
z-index (cp/update-z-index z-index changed-ids old-objects new-objects)]
{:index index :z-index z-index})
;; If not previous data. We need to create from scratch
(create-index new-objects)))
(assoc data :index index :z-index z-index)))
(defn- query-index
[{index :index z-index :z-index} rect frame-id full-frame? include-frames? clip-children? reverse?]
@ -154,7 +172,19 @@
(defmethod impl/handler :selection/update-index
[{:keys [page-id old-objects new-objects] :as message}]
(swap! state update page-id update-index old-objects new-objects)
(let [update-page-index
(fn [index]
(let [old-bounds (:bounds index)
new-bounds (objects-bounds new-objects)]
;; If the new bounds are contained within the old bounds we can
;; update the index.
;; Otherwise we need to re-create it
(if (and (some? index)
(gsh/contains-selrect? old-bounds new-bounds))
(update-index index old-objects new-objects)
(create-index new-objects))))]
(swap! state update page-id update-page-index))
nil)
(defmethod impl/handler :selection/query