diff --git a/common/src/app/common/geom/bounds_map.cljc b/common/src/app/common/geom/bounds_map.cljc index aa8f11d17..eebf4dd63 100644 --- a/common/src/app/common/geom/bounds_map.cljc +++ b/common/src/app/common/geom/bounds_map.cljc @@ -56,24 +56,55 @@ (not (ctm/empty? modifiers)) (gtr/transform-bounds modifiers)))))) +#?(:clj + (defn- resolve-modif-tree-ids + [objects modif-tree] + ;; These are the new bounds calculated. Are the "modified" plus any groups they belong to + (let [ids (keys modif-tree)] + (into (set ids) + (mapcat #(->> (cph/get-parent-ids-seq objects %) + (take-while (partial cph/group-like-shape? objects)))) + ids))) + + :cljs + ;; More performant version using javascript mutable sets + (defn- resolve-modif-tree-ids + [objects modif-tree] + + (let [base-ids (keys modif-tree) + ids (js/Set. base-ids)] + (loop [base-ids (seq base-ids)] + (when (some? base-ids) + (let [cid (first base-ids)] + (loop [new-ids + (->> (cph/get-parent-seq objects cid) + (take-while #(and (cph/group-like-shape? %) + (not (.has ids %)))) + (seq))] + (when (some? new-ids) + (.add ids (first new-ids)) + (recur (next new-ids)))) + (recur (next base-ids))))) + ids))) + (defn transform-bounds-map - [bounds-map objects modif-tree] - ;; We use the volatile in order to solve the dependencies problem. We want the groups to reference the new - ;; bounds instead of the old ones. The current as last parameter is to fix a possible infinite loop - ;; with self-references - (let [bm-holder (volatile! nil) + ([bounds-map objects modif-tree] + (transform-bounds-map bounds-map objects modif-tree nil)) + ([bounds-map objects modif-tree ids] + ;; We use the volatile in order to solve the dependencies problem. We want the groups to reference the new + ;; bounds instead of the old ones. The current as last parameter is to fix a possible infinite loop + ;; with self-references + (let [bm-holder (volatile! nil) - ;; These are the new bounds calculated. Are the "modified" plus any groups they belong to - ids (keys modif-tree) - ids (into (set ids) - (mapcat #(->> (cph/get-parent-ids-seq objects %) - (take-while (partial cph/group-like-shape? objects)))) - ids) + ids (or ids (resolve-modif-tree-ids objects modif-tree)) - new-bounds-map - (->> ids - (reduce - (fn [tr-bounds-map shape-id] + new-bounds-map + (loop [tr-bounds-map (transient bounds-map) + ids (seq ids)] + (if (not ids) + (persistent! tr-bounds-map) + (let [shape-id (first ids)] + (recur (cond-> tr-bounds-map (not= uuid/zero shape-id) (assoc! shape-id @@ -81,11 +112,10 @@ @bm-holder objects modif-tree - (get bounds-map shape-id)))))) - (transient bounds-map)) - (persistent!))] - (vreset! bm-holder new-bounds-map) - new-bounds-map)) + (get bounds-map shape-id))))) + (next ids)))))] + (vreset! bm-holder new-bounds-map) + new-bounds-map))) ;; Tool for debugging (defn bounds-map diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index a9c888f82..40727cf44 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -55,7 +55,11 @@ (if-let [child (get objects child-id)] (let [child-bounds @(get bounds child-id) child-modifiers - (gct/calc-child-modifiers parent child modifiers ignore-constraints child-bounds parent-bounds transformed-parent-bounds)] + (gct/calc-child-modifiers + parent child modifiers ignore-constraints + child-bounds + parent-bounds transformed-parent-bounds)] + (cgt/add-modifiers modif-tree child-id child-modifiers)) modif-tree)) modif-tree)))))) @@ -73,7 +77,7 @@ (gcfl/layout-child-modifiers parent transformed-parent-bounds child child-bounds layout-line)] [layout-line (cgt/add-modifiers modif-tree (:id child) modifiers)]))] - (let [bounds (cgb/transform-bounds-map bounds objects modif-tree) + (let [bounds (cgb/transform-bounds-map bounds objects modif-tree children) children (->> children @@ -113,7 +117,7 @@ (gcgl/child-modifiers parent transformed-parent-bounds child child-bounds grid-data cell-data)] (cgt/add-modifiers modif-tree (:id child) modifiers)))] - (let [bounds (cgb/transform-bounds-map bounds objects modif-tree) + (let [bounds (cgb/transform-bounds-map bounds objects modif-tree (:shapes parent)) children (->> (cph/get-immediate-children objects (:id parent) {:remove-hidden true})