🐛 Fix synchronization of geometry changes

This commit is contained in:
Andrés Moya 2020-11-25 15:22:19 +01:00 committed by Andrey Antukh
parent 56861e8d01
commit 40240d294a
2 changed files with 48 additions and 49 deletions

View file

@ -294,8 +294,6 @@
:internal.shape/proportion-lock :internal.shape/proportion-lock
:internal.shape/rx :internal.shape/rx
:internal.shape/ry :internal.shape/ry
:internal.shape/cx
:internal.shape/cy
:internal.shape/x :internal.shape/x
:internal.shape/y :internal.shape/y
:internal.shape/exports :internal.shape/exports
@ -319,7 +317,7 @@
:fill-color-ref-file :fill-group :fill-color-ref-file :fill-group
:fill-color-ref-id :fill-group :fill-color-ref-id :fill-group
:fill-opacity :fill-group :fill-opacity :fill-group
:content :text-content-group :content :content-group
:font-family :text-font-group :font-family :text-font-group
:font-size :text-font-group :font-size :text-font-group
:font-style :text-font-group :font-style :text-font-group
@ -334,11 +332,19 @@
:stroke-style :stroke-group :stroke-style :stroke-group
:stroke-width :stroke-group :stroke-width :stroke-group
:stroke-alignment :stroke-group :stroke-alignment :stroke-group
:width :size-group :selrect :geometry-group
:height :size-group :points :geometry-group
:proportion :size-group :locked :geometry-group
:rx :radius-group :proportion :geometry-group
:ry :radius-group :proportion-lock :geometry-group
:rx :geometry-group
:ry :geometry-group
:x :geometry-group
:y :geometry-group
:width :geometry-group
:height :geometry-group
:transform :geometry-group
:transform-inverse :geometry-group
:masked-group? :mask-group}) :masked-group? :mask-group})
;; shapes-group is handled differently ;; shapes-group is handled differently
@ -1074,7 +1080,12 @@
group (get component-sync-attrs attr)] group (get component-sync-attrs attr)]
(cond-> shape (cond-> shape
(and shape-ref group (not ignore) (not= val (get shape attr))) (and shape-ref group (not ignore) (not= val (get shape attr))
;; FIXME: it's difficult to tell if the geometry changes affect
;; an individual shape inside the component, or are for
;; the whole component (in which case we shouldn't set
;; touched). For the moment we disable geometry touched.
(not= group :geometry-group))
(update :touched cph/set-touched-group group) (update :touched cph/set-touched-group group)
(nil? val) (nil? val)

View file

@ -14,6 +14,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.pages-helpers :as cph] [app.common.pages-helpers :as cph]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as geom]
[app.common.pages :as cp] [app.common.pages :as cp]
[app.util.logging :as log] [app.util.logging :as log]
[app.util.text :as ut])) [app.util.text :as ut]))
@ -50,7 +51,7 @@
(declare move-shape) (declare move-shape)
(declare change-touched) (declare change-touched)
(declare update-attrs) (declare update-attrs)
(declare calc-new-pos) (declare reposition-shape)
;; ---- Create a new component ---- ;; ---- Create a new component ----
@ -658,16 +659,13 @@
(cph/get-parents parent-shape (:objects container)))) (cph/get-parents parent-shape (:objects container))))
update-new-shape (fn [new-shape original-shape] update-new-shape (fn [new-shape original-shape]
(let [new-pos (calc-new-pos new-shape (let [new-shape (reposition-shape new-shape
original-shape root-master
root-instance root-instance)]
root-master)]
(cond-> new-shape (cond-> new-shape
true true
(assoc :shape-ref (:id original-shape) (assoc :shape-ref (:id original-shape)
:frame-id (:frame-id parent-shape) :frame-id (:frame-id parent-shape))
:x (:x new-pos)
:y (:y new-pos))
(:component-id original-shape) (:component-id original-shape)
(assoc :component-id (:component-id original-shape)) (assoc :component-id (:component-id original-shape))
@ -736,13 +734,9 @@
(cph/get-parents component-parent-shape (:objects component)))) (cph/get-parents component-parent-shape (:objects component))))
update-new-shape (fn [new-shape original-shape] update-new-shape (fn [new-shape original-shape]
(let [new-pos (calc-new-pos new-shape (reposition-shape new-shape
original-shape root-instance
root-master root-master))
root-instance)]
(assoc new-shape
:x (:x new-pos)
:y (:y new-pos))))
update-original-shape (fn [original-shape new-shape] update-original-shape (fn [original-shape new-shape]
(if-not (:shape-ref original-shape) (if-not (:shape-ref original-shape)
@ -966,23 +960,17 @@
(if (cph/page? container) "[P] " "[C] ") (if (cph/page? container) "[P] " "[C] ")
(:name dest-shape))) (:name dest-shape)))
(let [; The position attributes need a special sync algorith, because we do (let [; To synchronize geometry attributes we need to make a prior
; not synchronize the absolute position, but the position relative of ; operation, because coordinates are absolute, but we need to
; the container shape of the component. ; sync only the position relative to the origin of the component.
new-pos (calc-new-pos dest-shape origin-shape dest-root origin-root) ; We solve this by moving the origin shape so it is aligned with
; the dest root before syncing.
origin-shape (reposition-shape origin-shape origin-root dest-root)
touched (get dest-shape :touched #{})] touched (get dest-shape :touched #{})]
(loop [attrs (seq (keys (dissoc cp/component-sync-attrs :x :y))) (loop [attrs (seq (keys cp/component-sync-attrs))
roperations (if (or (not= (:x new-pos) (:x dest-shape)) roperations []
(not= (:y new-pos) (:y dest-shape))) uoperations []]
[{:type :set :attr :x :val (:x new-pos)}
{:type :set :attr :y :val (:y new-pos)}]
[])
uoperations (if (or (not= (:x new-pos) (:x dest-shape))
(not= (:y new-pos) (:y dest-shape)))
[{:type :set :attr :x :val (:x dest-shape)}
{:type :set :attr :y :val (:y dest-shape)}]
[])]
(let [attr (first attrs)] (let [attr (first attrs)]
(if (nil? attr) (if (nil? attr)
@ -1042,13 +1030,13 @@
(conj roperations roperation) (conj roperations roperation)
(conj uoperations uoperation)))))))))) (conj uoperations uoperation))))))))))
(defn- calc-new-pos (defn- reposition-shape
[dest-shape origin-shape dest-root origin-root] [shape origin-root dest-root]
(let [root-pos (gpt/point (:x dest-root) (:y dest-root)) (let [shape-pos (fn [shape]
origin-root-pos (gpt/point (:x origin-root) (:y origin-root)) (gpt/point (get-in shape [:selrect :x])
origin-pos (gpt/point (:x origin-shape) (:y origin-shape)) (get-in shape [:selrect :y])))
delta (gpt/subtract origin-pos origin-root-pos)
shape-pos (gpt/point (:x dest-shape) (:y dest-shape))
new-pos (gpt/add root-pos delta)]
new-pos))
origin-root-pos (shape-pos origin-root)
dest-root-pos (shape-pos dest-root)
delta (gpt/subtract dest-root-pos origin-root-pos)]
(geom/move shape delta)))