Clip boolean selrects

This commit is contained in:
alonso.torres 2021-09-20 11:47:02 +02:00
parent c56f024a86
commit 56e2db22eb
8 changed files with 120 additions and 91 deletions

View file

@ -73,7 +73,7 @@
(d/export indices/update-z-index) (d/export indices/update-z-index)
(d/export indices/generate-child-all-parents-index) (d/export indices/generate-child-all-parents-index)
(d/export indices/generate-child-parent-index) (d/export indices/generate-child-parent-index)
(d/export indices/create-mask-index) (d/export indices/create-clip-index)
;; Process changes ;; Process changes
(d/export changes/process-changes) (d/export changes/process-changes)

View file

@ -95,16 +95,24 @@
(map #(vector (:id %) (shape->parents %))) (map #(vector (:id %) (shape->parents %)))
(into {}))))) (into {})))))
(defn create-mask-index (defn create-clip-index
"Retrieves the mask information for an object" "Retrieves the mask information for an object"
[objects parents-index] [objects parents-index]
(let [retrieve-masks (let [retrieve-clips
(fn [_ parents] (fn [_ parents]
;; TODO: use transducers? (let [lookup-object (fn [id] (get objects id))
(->> parents get-clip-parents
(map #(get objects %)) (fn [shape]
(filter #(:masked-group? %)) (cond-> []
;; Retrieve the masking element (:masked-group? shape)
(mapv #(get objects (->> % :shapes first)))))] (conj (get objects (->> shape :shapes first)))
(= :bool (:type shape))
(conj shape)))]
(into []
(comp (map lookup-object)
(mapcat get-clip-parents))
parents)))]
(->> parents-index (->> parents-index
(d/mapm retrieve-masks)))) (d/mapm retrieve-clips))))

View file

@ -12,6 +12,23 @@
[app.common.path.commands :as upc] [app.common.path.commands :as upc]
[app.common.path.subpaths :as ups])) [app.common.path.subpaths :as ups]))
(defn- reverse-command
"Reverses a single command"
[command]
(let [{old-x :x old-y :y} (:params command)
{:keys [x y]} (:prev command)
{:keys [c1x c1y c2x c2y]} (:params command)]
(-> command
(assoc :prev (gpt/point old-x old-y))
(update :params assoc :x x :y y)
(cond-> (= :curve-to (:command command))
(update :params assoc
:c1x c2x :c1y c2y
:c2x c1x :c2y c1y)))))
(defn- split-command (defn- split-command
[cmd values] [cmd values]
(case (:command cmd) (case (:command cmd)
@ -142,7 +159,12 @@
(d/concat (d/concat
[] []
(->> content-a-split (filter #(not (contains-segment? % content-b)))) (->> content-a-split (filter #(not (contains-segment? % content-b))))
(->> content-b-split (filter #(contains-segment? % content-a)))))
;; Reverse second content so we can have holes inside other shapes
(->> content-b-split
(reverse)
(mapv reverse-command)
(filter #(contains-segment? % content-a)))))
(defn create-intersection [content-a content-a-split content-b content-b-split] (defn create-intersection [content-a content-a-split content-b content-b-split]
;; Pick all segments in content-a that are inside content-b ;; Pick all segments in content-a that are inside content-b
@ -152,22 +174,6 @@
(->> content-a-split (filter #(contains-segment? % content-b))) (->> content-a-split (filter #(contains-segment? % content-b)))
(->> content-b-split (filter #(contains-segment? % content-a))))) (->> content-b-split (filter #(contains-segment? % content-a)))))
(defn reverse-command
"Reverses a single command"
[command]
(let [{old-x :x old-y :y} (:params command)
{:keys [x y]} (:prev command)
{:keys [c1x c1y c2x c2y]} (:params command)]
(-> command
(assoc :prev (gpt/point old-x old-y))
(update :params assoc :x x :y y)
(cond-> (= :curve-to (:command command))
(update :params assoc
:c1x c2x :c1y c2y
:c2x c1x :c2y c1y)))))
(defn create-exclusion [content-a content-b] (defn create-exclusion [content-a content-b]
;; Pick all segments but reverse content-b (so it makes an exclusion) ;; Pick all segments but reverse content-b (so it makes an exclusion)

View file

@ -180,7 +180,9 @@
(defn convert-to-path (defn convert-to-path
"Transforms the given shape to a path" "Transforms the given shape to a path"
[{:keys [type x y width height r1 r2 r3 r4 rx metadata] :as shape} objects] ([shape]
(convert-to-path shape {}))
([{:keys [type x y width height r1 r2 r3 r4 rx metadata] :as shape} objects]
(assert (map? objects)) (assert (map? objects))
(cond (cond
(= (:type shape) :group) (= (:type shape) :group)
@ -209,4 +211,4 @@
(d/without-keys dissoc-attrs))) (d/without-keys dissoc-attrs)))
:else :else
;; Do nothing if the shape is not of a correct type ;; Do nothing if the shape is not of a correct type
shape)) shape)))

View file

@ -98,7 +98,9 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (wsh/lookup-page-objects state)] (let [objects (wsh/lookup-page-objects state)]
(rx/of (dch/update-shapes [shape-id] #(group->bool % bool-type objects))))))) (let [change-to-bool
(fn [shape] (group->bool shape bool-type objects))]
(rx/of (dch/update-shapes [shape-id] change-to-bool {:reg-objects? true})))))))
(defn bool-to-group (defn bool-to-group
[shape-id] [shape-id]
@ -106,7 +108,9 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (wsh/lookup-page-objects state)] (let [objects (wsh/lookup-page-objects state)]
(rx/of (dch/update-shapes [shape-id] #(bool->group % objects))))))) (let [change-to-group
(fn [shape] (bool->group shape objects))]
(rx/of (dch/update-shapes [shape-id] change-to-group {:reg-objects? true})))))))
(defn change-bool-type (defn change-bool-type
@ -114,6 +118,6 @@
(ptk/reify ::change-bool-type (ptk/reify ::change-bool-type
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(rx/of (dch/update-shapes (let [change-type
[shape-id] (fn [shape] (assoc shape :bool-type bool-type))]
#(assoc % :bool-type bool-type)))))) (rx/of (dch/update-shapes [shape-id] change-type {:reg-objects? true}))))))

View file

@ -27,7 +27,7 @@
bool-content bool-content
(mf/use-memo (mf/use-memo
(mf/deps childs) (mf/deps shape childs)
(fn [] (fn []
(let [childs (d/mapm #(gsh/transform-shape %2) childs)] (let [childs (d/mapm #(gsh/transform-shape %2) childs)]
(->> (:shapes shape) (->> (:shapes shape)
@ -40,6 +40,3 @@
(assoc :type :path) (assoc :type :path)
(assoc :content bool-content)) (assoc :content bool-content))
:frame frame}]))) :frame frame}])))

View file

@ -92,6 +92,7 @@
(defn setup-hover-shapes [page-id move-stream objects transform selected ctrl? hover hover-ids hover-disabled? zoom] (defn setup-hover-shapes [page-id move-stream objects transform selected ctrl? hover hover-ids hover-disabled? zoom]
(let [;; We use ref so we don't recreate the stream on a change (let [;; We use ref so we don't recreate the stream on a change
zoom-ref (mf/use-ref zoom) zoom-ref (mf/use-ref zoom)
ctrl-ref (mf/use-ref @ctrl?)
transform-ref (mf/use-ref nil) transform-ref (mf/use-ref nil)
selected-ref (mf/use-ref selected) selected-ref (mf/use-ref selected)
hover-disabled-ref (mf/use-ref hover-disabled?) hover-disabled-ref (mf/use-ref hover-disabled?)
@ -101,6 +102,7 @@
(mf/deps page-id) (mf/deps page-id)
(fn [point] (fn [point]
(let [zoom (mf/ref-val zoom-ref) (let [zoom (mf/ref-val zoom-ref)
ctrl? (mf/ref-val ctrl-ref)
rect (gsh/center->rect point (/ 5 zoom) (/ 5 zoom))] rect (gsh/center->rect point (/ 5 zoom) (/ 5 zoom))]
(if (mf/ref-val hover-disabled-ref) (if (mf/ref-val hover-disabled-ref)
(rx/of nil) (rx/of nil)
@ -109,6 +111,7 @@
:page-id page-id :page-id page-id
:rect rect :rect rect
:include-frames? true :include-frames? true
:clip-children? (not ctrl?)
:reverse? true}))))) ;; we want the topmost shape to be selected first :reverse? true}))))) ;; we want the topmost shape to be selected first
over-shapes-stream over-shapes-stream
@ -120,7 +123,6 @@
(rx/switch-map query-point))))] (rx/switch-map query-point))))]
;; Refresh the refs on a value change ;; Refresh the refs on a value change
(mf/use-effect (mf/use-effect
(mf/deps transform) (mf/deps transform)
#(mf/set-ref-val! transform-ref transform)) #(mf/set-ref-val! transform-ref transform))
@ -129,6 +131,10 @@
(mf/deps zoom) (mf/deps zoom)
#(mf/set-ref-val! zoom-ref zoom)) #(mf/set-ref-val! zoom-ref zoom))
(mf/use-effect
(mf/deps @ctrl?)
#(mf/set-ref-val! ctrl-ref @ctrl?))
(mf/use-effect (mf/use-effect
(mf/deps selected) (mf/deps selected)
#(mf/set-ref-val! selected-ref selected)) #(mf/set-ref-val! selected-ref selected))
@ -143,10 +149,14 @@
(fn [ids] (fn [ids]
(let [selected (mf/ref-val selected-ref) (let [selected (mf/ref-val selected-ref)
remove-id? (into #{} (mapcat #(cp/get-parents % objects)) selected) remove-id? (into #{} (mapcat #(cp/get-parents % objects)) selected)
remove-id? (if @ctrl?
(d/concat remove-id? is-group?
(->> ids (fn [id]
(filterv #(= :group (get-in objects [% :type]))))) (contains? #{:group :bool} (get-in objects [id :type])))
remove-id?
(if @ctrl?
(d/concat remove-id? (filterv is-group? ids))
remove-id?) remove-id?)
ids (->> ids (filterv (comp not remove-id?)))] ids (->> ids (filterv (comp not remove-id?)))]
(reset! hover (get objects (first ids))) (reset! hover (get objects (first ids)))

View file

@ -18,13 +18,13 @@
(defonce state (l/atom {})) (defonce state (l/atom {}))
(defn index-shape (defn index-shape
[objects parents-index masks-index] [objects parents-index clip-parents-index]
(fn [index shape] (fn [index shape]
(let [{:keys [x y width height]} (gsh/points->selrect (:points shape)) (let [{:keys [x y width height]} (gsh/points->selrect (:points shape))
shape-bound #js {:x x :y y :width width :height height} shape-bound #js {:x x :y y :width width :height height}
parents (get parents-index (:id shape)) parents (get parents-index (:id shape))
masks (get masks-index (:id shape)) clip-parents (get clip-parents-index (:id shape))
frame (when (and (not= :frame (:type shape)) frame (when (and (not= :frame (:type shape))
(not= (:frame-id shape) uuid/zero)) (not= (:frame-id shape) uuid/zero))
@ -32,19 +32,22 @@
(qdt/insert index (qdt/insert index
(:id shape) (:id shape)
shape-bound shape-bound
(assoc shape :frame frame :masks masks :parents parents))))) (assoc shape
:frame frame
:clip-parents clip-parents
:parents parents)))))
(defn- create-index (defn- create-index
[objects] [objects]
(let [shapes (-> objects (dissoc uuid/zero) (vals)) (let [shapes (-> objects (dissoc uuid/zero) (vals))
parents-index (cp/generate-child-all-parents-index objects) parents-index (cp/generate-child-all-parents-index objects)
masks-index (cp/create-mask-index objects parents-index) clip-parents-index (cp/create-clip-index objects parents-index)
bounds #js {:x (int -0.5e7) bounds #js {:x (int -0.5e7)
:y (int -0.5e7) :y (int -0.5e7)
:width (int 1e7) :width (int 1e7)
:height (int 1e7)} :height (int 1e7)}
index (reduce (index-shape objects parents-index masks-index) index (reduce (index-shape objects parents-index clip-parents-index)
(qdt/create bounds) (qdt/create bounds)
shapes) shapes)
@ -68,11 +71,11 @@
shapes (->> changed-ids (mapv #(get new-objects %)) (filterv (comp not nil?))) shapes (->> changed-ids (mapv #(get new-objects %)) (filterv (comp not nil?)))
parents-index (cp/generate-child-all-parents-index new-objects shapes) parents-index (cp/generate-child-all-parents-index new-objects shapes)
masks-index (cp/create-mask-index new-objects parents-index) clip-parents-index (cp/create-clip-index new-objects parents-index)
new-index (qdt/remove-all index changed-ids) new-index (qdt/remove-all index changed-ids)
index (reduce (index-shape new-objects parents-index masks-index) index (reduce (index-shape new-objects parents-index clip-parents-index)
new-index new-index
shapes) shapes)
@ -84,7 +87,7 @@
(create-index new-objects))) (create-index new-objects)))
(defn- query-index (defn- query-index
[{index :index z-index :z-index} rect frame-id include-frames? full-frame? include-groups? reverse?] [{index :index z-index :z-index} rect frame-id full-frame? include-frames? clip-children? reverse?]
(let [result (-> (qdt/search index (clj->js rect)) (let [result (-> (qdt/search index (clj->js rect))
(es6-iterator-seq)) (es6-iterator-seq))
@ -96,7 +99,6 @@
(or (not frame-id) (= frame-id (:frame-id shape))) (or (not frame-id) (= frame-id (:frame-id shape)))
(case (:type shape) (case (:type shape)
:frame include-frames? :frame include-frames?
:group include-groups?
true) true)
(or (not full-frame?) (or (not full-frame?)
@ -107,11 +109,9 @@
(fn [shape] (fn [shape]
(gsh/overlaps? shape rect)) (gsh/overlaps? shape rect))
overlaps-masks? overlaps-parent?
(fn [masks] (fn [clip-parents]
(->> masks (->> clip-parents (some (comp not overlaps?)) not))
(some (comp not overlaps?))
not))
add-z-index add-z-index
(fn [{:keys [id frame-id] :as shape}] (fn [{:keys [id frame-id] :as shape}]
@ -125,7 +125,9 @@
(filter match-criteria?) (filter match-criteria?)
(filter overlaps?) (filter overlaps?)
(filter (comp overlaps? :frame)) (filter (comp overlaps? :frame))
(filter (comp overlaps-masks? :masks)) (filter (if clip-children?
(comp overlaps-parent? :clip-parents)
(constantly true)))
(map add-z-index)) (map add-z-index))
result) result)
@ -155,10 +157,10 @@
nil) nil)
(defmethod impl/handler :selection/query (defmethod impl/handler :selection/query
[{:keys [page-id rect frame-id include-frames? full-frame? include-groups? reverse?] [{:keys [page-id rect frame-id reverse? full-frame? include-frames? clip-children?]
:or {include-groups? true reverse? false include-frames? false full-frame? false} :as message}] :or {reverse? false full-frame? false include-frames? false include-booleans? true include-groups? true} :as message}]
(when-let [index (get @state page-id)] (when-let [index (get @state page-id)]
(query-index index rect frame-id include-frames? full-frame? include-groups? reverse?))) (query-index index rect frame-id full-frame? include-frames? clip-children? reverse?)))
(defmethod impl/handler :selection/query-z-index (defmethod impl/handler :selection/query-z-index
[{:keys [page-id objects ids]}] [{:keys [page-id objects ids]}]