🎉 Show transient changes in component copies (old algorithm)

This commit is contained in:
Andrés Moya 2022-09-07 15:32:47 +02:00
parent 5d3eadc6db
commit 0e88398dc2
16 changed files with 341 additions and 129 deletions

View File

@ -59,6 +59,11 @@
[shape] [shape]
(or (:y shape) (:y (:selrect shape)))) ; Paths don't have :y attribute (or (:y shape) (:y (:selrect shape)))) ; Paths don't have :y attribute
(defn orig-pos
"Return the top left point of the shape wrapper BEFORE applying transformations."
[shape]
(gpt/point (left-bound shape) (top-bound shape)))
(defn fully-contained? (defn fully-contained?
"Checks if one rect is fully inside the other" "Checks if one rect is fully inside the other"
[rect other] [rect other]
@ -182,6 +187,7 @@
(dm/export gtr/modifiers->transform) (dm/export gtr/modifiers->transform)
(dm/export gtr/empty-modifiers?) (dm/export gtr/empty-modifiers?)
(dm/export gtr/move-position-data) (dm/export gtr/move-position-data)
(dm/export gtr/apply-modifiers)
(dm/export gtr/apply-transform) (dm/export gtr/apply-transform)
;; Constratins ;; Constratins

View File

@ -16,6 +16,7 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.pages.changes-spec :as pcs] [app.common.pages.changes-spec :as pcs]
[app.common.types.component :as ctk]
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.common.types.container :as ctn] [app.common.types.container :as ctn]
[app.common.types.colors-list :as ctcl] [app.common.types.colors-list :as ctcl]
@ -103,7 +104,7 @@
(cond-> parent (cond-> parent
(and (:shape-ref parent) (and (:shape-ref parent)
(not ignore-touched)) (not ignore-touched))
(-> (update :touched cph/set-touched-group :shapes-group) (-> (update :touched ctk/set-touched-group :shapes-group)
(dissoc :remote-synced?))))) (dissoc :remote-synced?)))))
(delete-from-objects [objects] (delete-from-objects [objects]
@ -208,7 +209,7 @@
(update :shapes d/vec-without-nils))] (update :shapes d/vec-without-nils))]
(cond-> parent (cond-> parent
(and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched))
(-> (update :touched cph/set-touched-group :shapes-group) (-> (update :touched ctk/set-touched-group :shapes-group)
(dissoc :remote-synced?))))) (dissoc :remote-synced?)))))
(remove-from-old-parent [cpindex objects shape-id] (remove-from-old-parent [cpindex objects shape-id]
@ -228,7 +229,7 @@
(d/update-in-when [pid :shapes] without-obj sid) (d/update-in-when [pid :shapes] without-obj sid)
(d/update-in-when [pid :shapes] d/vec-without-nils) (d/update-in-when [pid :shapes] d/vec-without-nils)
(cond-> component? (d/update-when pid #(-> % (cond-> component? (d/update-when pid #(-> %
(update :touched cph/set-touched-group :shapes-group) (update :touched ctk/set-touched-group :shapes-group)
(dissoc :remote-synced?))))))))) (dissoc :remote-synced?)))))))))
(update-parent-id [objects id] (update-parent-id [objects id]
@ -429,7 +430,7 @@
(not root-name?) (not root-name?)
(not (and ignore-geometry is-geometry?))) (not (and ignore-geometry is-geometry?)))
(-> (->
(update :touched cph/set-touched-group group) (update :touched ctk/set-touched-group group)
(dissoc :remote-synced?)) (dissoc :remote-synced?))
(nil? val) (nil? val)

View File

@ -16,6 +16,7 @@
[app.common.math :as mth] [app.common.math :as mth]
[app.common.pages :as cp] [app.common.pages :as cp]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.types.container :as ctn]
[app.common.types.file :as ctf] [app.common.types.file :as ctf]
[app.common.uuid :as uuid])) [app.common.uuid :as uuid]))
@ -44,7 +45,7 @@
(defn with-container (defn with-container
[changes container] [changes container]
(if (cph/page? container) (if (ctn/page? container)
(vary-meta changes assoc ::page-id (:id container)) (vary-meta changes assoc ::page-id (:id container))
(vary-meta changes assoc ::component-id (:id container)))) (vary-meta changes assoc ::component-id (:id container))))

View File

@ -168,71 +168,6 @@
:else :else
(recur (get-in objects [current-id :parent-id]))))) (recur (get-in objects [current-id :parent-id])))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMPONENTS HELPERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn set-touched-group
[touched group]
(conj (or touched #{}) group))
(defn touched-group?
[shape group]
((or (:touched shape) #{}) group))
(defn get-component
"Retrieve a component from libraries, if no library-id is provided, we
iterate over all libraries and find the component on it."
([libraries component-id]
(some #(-> % :data :components (get component-id)) (vals libraries)))
([libraries library-id component-id]
(get-in libraries [library-id :data :components component-id])))
(defn get-component-shape
"Get the parent shape linked to a component for this shape, if any"
[objects shape]
(if-not (:shape-ref shape)
nil
(if (:component-id shape)
shape
(if-let [parent-id (:parent-id shape)]
(get-component-shape objects (get objects parent-id))
nil))))
(defn get-root-shape
"Get the root shape linked to a component for this shape, if any."
[objects shape]
(cond
(some? (:component-root? shape))
shape
(some? (:shape-ref shape))
(recur objects (get objects (:parent-id shape)))))
(defn make-container
[page-or-component type]
(assoc page-or-component :type type))
(defn page?
[container]
(= (:type container) :page))
(defn component?
[container]
(= (:type container) :component))
(defn get-container
[file type id]
(us/assert map? file)
(us/assert keyword? type)
(us/assert uuid? id)
(-> (if (= type :page)
(get-in file [:pages-index id])
(get-in file [:components id]))
(assoc :type type)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ALGORITHMS & TRANSFORMATIONS FOR SHAPES ;; ALGORITHMS & TRANSFORMATIONS FOR SHAPES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -7,10 +7,23 @@
(ns app.common.types.component) (ns app.common.types.component)
(defn instance-root? (defn instance-root?
"Check if the shape is the root of an instance or a subinstance."
[shape] [shape]
(some? (:component-id shape))) (some? (:component-id shape)))
(defn instance-tree-root?
"Check if the shape is the root of an instance that is no
subinstance of a higher one."
[shape]
(:component-root? shape))
(defn instance-shape?
"Check if the shape is part of any instance."
[shape]
(some? (:shape-ref shape)))
(defn instance-of? (defn instance-of?
"Check if the shape is the root of a near instance of the component."
[shape file-id component-id] [shape file-id component-id]
(and (some? (:component-id shape)) (and (some? (:component-id shape))
(some? (:component-file shape)) (some? (:component-file shape))
@ -18,23 +31,38 @@
(= (:component-file shape) file-id))) (= (:component-file shape) file-id)))
(defn is-main-of? (defn is-main-of?
"Check if the first shape is the near main of the second one."
[shape-main shape-inst] [shape-main shape-inst]
(and (:shape-ref shape-inst) (and (not= shape-main shape-inst)
(:shape-ref shape-inst)
(or (= (:shape-ref shape-inst) (:id shape-main)) (or (= (:shape-ref shape-inst) (:id shape-main))
(= (:shape-ref shape-inst) (:shape-ref shape-main))))) (= (:shape-ref shape-inst) (:shape-ref shape-main)))))
(defn is-main-instance? (defn is-main-instance?
"Check if the shape is the root of the main instance of the component."
[shape-id page-id component] [shape-id page-id component]
(and (= shape-id (:main-instance-id component)) (and (= shape-id (:main-instance-id component))
(= page-id (:main-instance-page component)))) (= page-id (:main-instance-page component))))
(defn get-component-root (defn get-component-root
"Get the root shape of the component."
[component] [component]
(get-in component [:objects (:id component)])) (get-in component [:objects (:id component)]))
(defn uses-library-components? (defn uses-library-components?
"Check if the shape uses any component in the given library." "Check if the shape is the root of an instance of any component in
the given library."
[shape library-id] [shape library-id]
(and (some? (:component-id shape)) (and (some? (:component-id shape))
(= (:component-file shape) library-id))) (= (:component-file shape) library-id)))
(defn set-touched-group
"Add a group to the touched flags."
[touched group]
(conj (or touched #{}) group))
(defn touched-group?
"Check if the touched flags contain the given group."
[shape group]
((or (:touched shape) #{}) group))

View File

@ -9,6 +9,7 @@
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.component :as ctk]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
@ -34,17 +35,6 @@
[container] [container]
(= (:type container) :component)) (= (:type container) :component))
(defn get-container
[file type id]
(us/assert map? file)
(us/assert ::type type)
(us/assert uuid? id)
(-> (if (= type :page)
(get-in file [:pages-index id])
(get-in file [:components id]))
(assoc :type type)))
(defn get-shape (defn get-shape
[container shape-id] [container shape-id]
(us/assert ::container container) (us/assert ::container container)
@ -61,6 +51,40 @@
[container shape-id f] [container shape-id f]
(update-in container [:objects shape-id] f)) (update-in container [:objects shape-id] f))
(defn get-component-shape
"Get the root shape of an instance, the one that is linked to the component.
If this is a subinstance, get the most direct root."
[objects shape]
(if-not (:shape-ref shape)
nil
(if (:component-id shape)
shape
(if-let [parent-id (:parent-id shape)]
(get-component-shape objects (get objects parent-id))
nil))))
(defn get-root-shape
"Get the topmost root shape of an instance, the one that is linked to the
component and without any container instance upwards."
[objects shape]
(cond
(some? (:component-root? shape))
shape
(some? (:shape-ref shape))
(recur objects (get objects (:parent-id shape)))))
(defn get-instances
"Get all shapes in the objects list that are near instances of the given one
---------------------------------------------------------------------------
TODO: Warning!!! this is a slow operation, since it needs to walk the whole
objects list. Perhaps there is a way of indexing this someway.
---------------------------------------------------------------------------"
[objects main-shape]
(filter #(ctk/is-main-of? main-shape %)
(vals objects)))
(defn make-component-shape (defn make-component-shape
"Clone the shape and all children. Generate new ids and detach "Clone the shape and all children. Generate new ids and detach
from parent and frame. Update the original shapes to have links from parent and frame. Update the original shapes to have links

View File

@ -6,6 +6,7 @@
(ns app.common.types.file (ns app.common.types.file
(:require (:require
[app.common.pprint :refer [pprint]]
[app.common.data :as d] [app.common.data :as d]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
@ -111,6 +112,17 @@
(concat (map #(ctn/make-container % :page) (ctpl/pages-seq file-data)) (concat (map #(ctn/make-container % :page) (ctpl/pages-seq file-data))
(map #(ctn/make-container % :component) (ctkl/components-seq file-data)))) (map #(ctn/make-container % :component) (ctkl/components-seq file-data))))
(defn get-container
[file type id]
(us/assert map? file)
(us/assert :app.common.types.container/type type)
(us/assert uuid? id)
(-> (if (= type :page)
(get-in file [:pages-index id])
(get-in file [:components id]))
(assoc :type type)))
(defn update-container (defn update-container
"Update a container inside the file, it can be a page or a component" "Update a container inside the file, it can be a page or a component"
[file-data container f] [file-data container f]
@ -512,7 +524,7 @@
(show-component [shape objects] (show-component [shape objects]
(if (nil? (:shape-ref shape)) (if (nil? (:shape-ref shape))
"" ""
(let [root-shape (cph/get-component-shape objects shape) (let [root-shape (ctn/get-component-shape objects shape)
component-id (when root-shape (:component-id root-shape)) component-id (when root-shape (:component-id root-shape))
component-file-id (when root-shape (:component-file root-shape)) component-file-id (when root-shape (:component-file root-shape))
component-file (when component-file-id (get libraries component-file-id nil)) component-file (when component-file-id (get libraries component-file-id nil))

View File

@ -13,6 +13,7 @@
[app.common.math :as mth] [app.common.math :as mth]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.component :as ctk]
[app.common.types.shape :as cts] [app.common.types.shape :as cts]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
@ -45,7 +46,7 @@
(cond-> (and (:shape-ref parent) (cond-> (and (:shape-ref parent)
(not= (:id parent) frame-id) (not= (:id parent) frame-id)
(not ignore-touched)) (not ignore-touched))
(-> (update :touched cph/set-touched-group :shapes-group) (-> (update :touched ctk/set-touched-group :shapes-group)
(dissoc :remote-synced?))))) (dissoc :remote-synced?)))))
;; TODO: this looks wrong, why we allow nil values? ;; TODO: this looks wrong, why we allow nil values?

View File

@ -3,7 +3,8 @@
[clojure.test :as t] [clojure.test :as t]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.types.component :as ctk] [app.common.types.component :as ctk]
[app.common.types.container :as ctn])) [app.common.types.container :as ctn]
[app.common.types.file :as ctf]))
;; ---- Helpers to manage libraries and synchronization ;; ---- Helpers to manage libraries and synchronization
@ -75,7 +76,7 @@
[page root-inst-id libraries] [page root-inst-id libraries]
(let [root-inst (ctn/get-shape page root-inst-id) (let [root-inst (ctn/get-shape page root-inst-id)
component (cph/get-component libraries (:component-id root-inst)) component (ctf/get-component libraries (:component-id root-inst))
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id) shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst)) shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
@ -84,10 +85,10 @@
main-exists? (fn [shape] main-exists? (fn [shape]
(let [component-shape (let [component-shape
(cph/get-component-shape (:objects page) shape) (ctn/get-component-shape (:objects page) shape)
component component
(cph/get-component libraries (:component-id component-shape)) (ctf/get-component libraries (:component-id component-shape))
main-shape main-shape
(ctn/get-shape component (:shape-ref shape))] (ctn/get-shape component (:shape-ref shape))]
@ -111,7 +112,7 @@
[page root-inst-id libraries] [page root-inst-id libraries]
(let [root-inst (ctn/get-shape page root-inst-id) (let [root-inst (ctn/get-shape page root-inst-id)
component (cph/get-component libraries (:component-id root-inst)) component (ctf/get-component libraries (:component-id root-inst))
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id) shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst)) shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
@ -120,10 +121,10 @@
main-exists? (fn [shape] main-exists? (fn [shape]
(let [component-shape (let [component-shape
(cph/get-component-shape (:objects page) shape) (ctn/get-component-shape (:objects page) shape)
component component
(cph/get-component libraries (:component-id component-shape)) (ctf/get-component libraries (:component-id component-shape))
main-shape main-shape
(ctn/get-shape component (:shape-ref shape))] (ctn/get-shape component (:shape-ref shape))]
@ -138,7 +139,7 @@
(defn resolve-component (defn resolve-component
"Get the component with the given id and all its shapes." "Get the component with the given id and all its shapes."
[page component-id libraries] [page component-id libraries]
(let [component (cph/get-component libraries component-id) (let [component (ctf/get-component libraries component-id)
root-main (ctk/get-component-root component) root-main (ctk/get-component-root component)
shapes-main (cph/get-children-with-self (:objects component) (:id root-main))] shapes-main (cph/get-children-with-self (:objects component) (:id root-main))]

View File

@ -18,6 +18,7 @@
[app.common.spec :as us] [app.common.spec :as us]
[app.common.text :as txt] [app.common.text :as txt]
[app.common.transit :as t] [app.common.transit :as t]
[app.common.types.container :as ctn]
[app.common.types.shape :as cts] [app.common.types.shape :as cts]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
@ -641,8 +642,8 @@
(not (:component-root? shape))) (not (:component-root? shape)))
parent (get objects parent-id) parent (get objects parent-id)
component-shape (cph/get-component-shape objects shape) component-shape (ctn/get-component-shape objects shape)
component-shape-parent (cph/get-component-shape objects parent) component-shape-parent (ctn/get-component-shape objects parent)
detach? (and instance-part? (not= (:id component-shape) detach? (and instance-part? (not= (:id component-shape)
(:id component-shape-parent))) (:id component-shape-parent)))
@ -1406,7 +1407,7 @@
;; Check if the shape is an instance whose master is defined in a ;; Check if the shape is an instance whose master is defined in a
;; library that is not linked to the current file ;; library that is not linked to the current file
(foreign-instance? [shape paste-objects state] (foreign-instance? [shape paste-objects state]
(let [root (cph/get-root-shape paste-objects shape) (let [root (ctn/get-root-shape paste-objects shape)
root-file-id (:component-file root)] root-file-id (:component-file root)]
(and (some? root) (and (some? root)
(not= root-file-id (:current-file-id state)) (not= root-file-id (:current-file-id state))

View File

@ -367,7 +367,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [libraries (wsh/get-libraries state) (let [libraries (wsh/get-libraries state)
component (cph/get-component libraries id) component (ctf/get-component libraries id)
all-components (-> state :workspace-data :components vals) all-components (-> state :workspace-data :components vals)
unames (into #{} (map :name) all-components) unames (into #{} (map :name) all-components)
new-name (ctst/generate-unique-name unames (:name component)) new-name (ctst/generate-unique-name unames (:name component))
@ -484,7 +484,7 @@
(watch [it state _] (watch [it state _]
(let [file (wsh/get-local-file state) (let [file (wsh/get-local-file state)
page-id (get state :current-page-id) page-id (get state :current-page-id)
container (cph/get-container file :page page-id) container (ctf/get-container file :page page-id)
changes (-> (pcb/empty-changes it) changes (-> (pcb/empty-changes it)
(pcb/with-container container) (pcb/with-container container)
@ -500,7 +500,7 @@
(let [page-id (:current-page-id state) (let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id) objects (wsh/lookup-page-objects state page-id)
file (wsh/get-local-file state) file (wsh/get-local-file state)
container (cph/get-container file :page page-id) container (ctf/get-container file :page page-id)
selected (->> state selected (->> state
(wsh/lookup-selected) (wsh/lookup-selected)
(cph/clean-loops objects)) (cph/clean-loops objects))
@ -557,7 +557,7 @@
libraries (wsh/get-libraries state) libraries (wsh/get-libraries state)
page-id (:current-page-id state) page-id (:current-page-id state)
container (cph/get-container file :page page-id) container (ctf/get-container file :page page-id)
components-v2 components-v2
(features/active-feature? state :components-v2) (features/active-feature? state :components-v2)
@ -593,7 +593,7 @@
local-file (wsh/get-local-file state) local-file (wsh/get-local-file state)
libraries (wsh/get-libraries state) libraries (wsh/get-libraries state)
container (cph/get-container local-file :page page-id) container (ctf/get-container local-file :page page-id)
shape (ctn/get-shape container id) shape (ctn/get-shape container id)
changes changes

View File

@ -18,6 +18,7 @@
[app.common.types.color :as ctc] [app.common.types.color :as ctc]
[app.common.types.component :as ctk] [app.common.types.component :as ctk]
[app.common.types.container :as ctn] [app.common.types.container :as ctn]
[app.common.types.file :as ctf]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.common.types.typography :as cty] [app.common.types.typography :as cty]
[app.main.data.workspace.groups :as dwg] [app.main.data.workspace.groups :as dwg]
@ -126,7 +127,7 @@
(defn generate-instantiate-component (defn generate-instantiate-component
"Generate changes to create a new instance from a component." "Generate changes to create a new instance from a component."
[it file-id component-id position page libraries] [it file-id component-id position page libraries]
(let [component (cph/get-component libraries file-id component-id) (let [component (ctf/get-component libraries file-id component-id)
[new-shape new-shapes] [new-shape new-shapes]
(ctn/make-component-instance page component file-id position) (ctn/make-component-instance page component file-id position)
@ -190,7 +191,7 @@
asset-id asset-id
library-id library-id
state state
(cph/make-container page :page) (ctn/make-container page :page)
components-v2))) components-v2)))
changes)))) changes))))
@ -226,7 +227,7 @@
asset-id asset-id
library-id library-id
state state
(cph/make-container local-component :component) (ctn/make-container local-component :component)
components-v2))) components-v2)))
changes)))) changes))))
@ -235,7 +236,7 @@
or a component) that use assets of the given type in the given library." or a component) that use assets of the given type in the given library."
[it asset-type asset-id library-id state container components-v2] [it asset-type asset-id library-id state container components-v2]
(if (cph/page? container) (if (ctn/page? container)
(log/debug :msg "Sync page in local file" :page-id (:id container)) (log/debug :msg "Sync page in local file" :page-id (:id container))
(log/debug :msg "Sync component in local library" :component-id (:id container))) (log/debug :msg "Sync component in local library" :component-id (:id container)))
@ -450,7 +451,7 @@
[changes libraries container shape-id reset? components-v2] [changes libraries container shape-id reset? components-v2]
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?) (log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
(let [shape-inst (ctn/get-shape container shape-id) (let [shape-inst (ctn/get-shape container shape-id)
component (cph/get-component libraries component (ctf/get-component libraries
(:component-file shape-inst) (:component-file shape-inst)
(:component-id shape-inst)) (:component-id shape-inst))
shape-main (when component shape-main (when component
@ -582,7 +583,7 @@
[changes libraries container shape-id] [changes libraries container shape-id]
(log/debug :msg "Sync shape inverse" :shape (str shape-id)) (log/debug :msg "Sync shape inverse" :shape (str shape-id))
(let [shape-inst (ctn/get-shape container shape-id) (let [shape-inst (ctn/get-shape container shape-id)
component (cph/get-component libraries component (ctf/get-component libraries
(:component-file shape-inst) (:component-file shape-inst)
(:component-id shape-inst)) (:component-id shape-inst))
shape-main (ctn/get-shape component (:shape-ref shape-inst)) shape-main (ctn/get-shape component (:shape-ref shape-inst))
@ -612,7 +613,7 @@
(if (nil? shape-main) (if (nil? shape-main)
;; This should not occur, but protect against it in any case ;; This should not occur, but protect against it in any case
changes changes
(let [component-container (cph/make-container component :component) (let [component-container (ctn/make-container component :component)
omit-touched? false omit-touched? false
set-remote-synced? (not initial-root?) set-remote-synced? (not initial-root?)
@ -819,7 +820,7 @@
:shapes all-parents})) :shapes all-parents}))
changes' (reduce del-obj-change changes' new-shapes)] changes' (reduce del-obj-change changes' new-shapes)]
(if (and (cph/touched-group? parent-shape :shapes-group) omit-touched?) (if (and (ctk/touched-group? parent-shape :shapes-group) omit-touched?)
changes changes
changes'))) changes')))
@ -902,7 +903,7 @@
(defn- remove-shape (defn- remove-shape
[changes shape container omit-touched?] [changes shape container omit-touched?]
(log/info :msg (str "REMOVE-SHAPE " (log/info :msg (str "REMOVE-SHAPE "
(if (cph/page? container) "[P] " "[C] ") (if (ctn/page? container) "[P] " "[C] ")
(:name shape))) (:name shape)))
(let [objects (get container :objects) (let [objects (get container :objects)
parents (cph/get-parent-ids objects (:id shape)) parents (cph/get-parent-ids objects (:id shape))
@ -940,14 +941,14 @@
changes' changes'
(map :id children))] (map :id children))]
(if (and (cph/touched-group? parent :shapes-group) omit-touched?) (if (and (ctk/touched-group? parent :shapes-group) omit-touched?)
changes changes
changes'))) changes')))
(defn- move-shape (defn- move-shape
[changes shape index-before index-after container omit-touched?] [changes shape index-before index-after container omit-touched?]
(log/info :msg (str "MOVE " (log/info :msg (str "MOVE "
(if (cph/page? container) "[P] " "[C] ") (if (ctn/page? container) "[P] " "[C] ")
(:name shape) (:name shape)
" " " "
index-before index-before
@ -971,7 +972,7 @@
:index index-before :index index-before
:ignore-touched true})))] :ignore-touched true})))]
(if (and (cph/touched-group? parent :shapes-group) omit-touched?) (if (and (ctk/touched-group? parent :shapes-group) omit-touched?)
changes changes
changes'))) changes')))
@ -983,7 +984,7 @@
changes changes
(do (do
(log/info :msg (str "CHANGE-TOUCHED " (log/info :msg (str "CHANGE-TOUCHED "
(if (cph/page? container) "[P] " "[C] ") (if (ctn/page? container) "[P] " "[C] ")
(:name dest-shape)) (:name dest-shape))
:options options) :options options)
(let [new-touched (cond (let [new-touched (cond
@ -1018,7 +1019,7 @@
changes changes
(do (do
(log/info :msg (str "CHANGE-REMOTE-SYNCED? " (log/info :msg (str "CHANGE-REMOTE-SYNCED? "
(if (cph/page? container) "[P] " "[C] ") (if (ctn/page? container) "[P] " "[C] ")
(:name shape)) (:name shape))
:remote-synced? remote-synced?) :remote-synced? remote-synced?)
(-> changes (-> changes
@ -1048,7 +1049,7 @@
(log/info :msg (str "SYNC " (log/info :msg (str "SYNC "
(:name origin-shape) (:name origin-shape)
" -> " " -> "
(if (cph/page? container) "[P] " "[C] ") (if (ctn/page? container) "[P] " "[C] ")
(:name dest-shape))) (:name dest-shape)))
(let [; To synchronize geometry attributes we need to make a prior (let [; To synchronize geometry attributes we need to make a prior
@ -1127,7 +1128,7 @@
(defn- make-change (defn- make-change
[container change] [container change]
(if (cph/page? container) (if (ctn/page? container)
(assoc change :page-id (:id container)) (assoc change :page-id (:id container))
(assoc change :component-id (:id container)))) (assoc change :component-id (:id container))))

View File

@ -16,6 +16,7 @@
[app.common.pages.common :as cpc] [app.common.pages.common :as cpc]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.container :as ctn]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.collapse :as dwc] [app.main.data.workspace.collapse :as dwc]
@ -249,7 +250,7 @@
shape shape
(nil? root) (nil? root)
(cph/get-root-shape objects shape) (ctn/get-root-shape objects shape)
:else root) :else root)
@ -259,7 +260,7 @@
transformed-shape transformed-shape
(nil? transformed-root) (nil? transformed-root)
(as-> (cph/get-root-shape objects transformed-shape) $ (as-> (ctn/get-root-shape objects transformed-shape) $
(gsh/transform-shape (merge $ (get modif-tree (:id $))))) (gsh/transform-shape (merge $ (get modif-tree (:id $)))))
:else transformed-root) :else transformed-root)

View File

@ -11,6 +11,10 @@
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.common.pages.helpers :as cph] ; TODO: move this to ctst
[app.common.types.component :as ctk]
[app.common.types.container :as ctn]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.workspace.viewport.utils :as vwu] [app.main.ui.workspace.viewport.utils :as vwu]
[app.util.dom :as dom] [app.util.dom :as dom]
@ -249,6 +253,21 @@
(dom/remove-attribute! node "data-old-transform") (dom/remove-attribute! node "data-old-transform")
(dom/remove-attribute! node "transform"))))))))) (dom/remove-attribute! node "transform")))))))))
(defn get-copy-shapes
"If one or more of the shapes belongs to a component's main instance, find all copies of
the component in the same page. Ignore copies with the geometry values touched."
[shapes objects]
(letfn [(get-copy-shapes-one [shape]
(let [root-shape (ctn/get-root-shape objects shape)]
(when (:main-instance? root-shape)
(->> (ctn/get-instances objects shape)
(filter #(not (ctk/touched-group? % :geometry-group)))))))
(pack-main-copies [shape]
(map #(vector shape %) (get-copy-shapes-one shape)))]
(mapcat pack-main-copies shapes)))
(defn use-dynamic-modifiers (defn use-dynamic-modifiers
[objects node modifiers] [objects node modifiers]
@ -277,7 +296,187 @@
prev-shapes (mf/use-var nil) prev-shapes (mf/use-var nil)
prev-modifiers (mf/use-var nil) prev-modifiers (mf/use-var nil)
prev-transforms (mf/use-var nil)] prev-transforms (mf/use-var nil)
copy-shapes
(mf/use-memo
(mf/deps (and (d/not-empty? @prev-modifiers) (d/not-empty? modifiers)))
(fn []
(get-copy-shapes shapes objects)))
transforms
(mf/use-memo
(mf/deps objects modifiers transforms copy-shapes)
(fn []
(let [add-copy-transforms
(fn [transforms main-shape copy-shape]
(let [main-bounds (gsh/bounding-box main-shape)
copy-bounds (gsh/bounding-box copy-shape)
delta (gpt/subtract (gpt/point (:x copy-bounds) (:y copy-bounds))
(gpt/point (:x main-bounds) (:y main-bounds)))
;; Move the modifier origin points to the position of the copy.
main-modifiers (get-in modifiers [(:id main-shape) :modifiers])
copy-modifiers (let [origin (:resize-origin main-modifiers)
origin-2 (:resize-origin-2 main-modifiers)]
(cond-> main-modifiers
(some? origin)
(assoc :resize-origin (gpt/add origin delta))
(some? origin-2)
(assoc :resize-origin-2 (gpt/add origin-2 delta))))
center (gsh/center-shape copy-shape)]
(update transforms (:id copy-shape)
#(let [transform (or % (gmt/matrix))]
(gmt/multiply transform
(gsh/modifiers->transform center copy-modifiers))))))
apply-delta
(fn [transforms shape-id delta]
(let [shape-ids (-> (cph/get-children-ids objects shape-id)
(conj shape-id))
add-delta (fn [transform]
(let [transform (or transform (gmt/matrix))]
(gmt/multiply transform (gmt/translate-matrix delta))))]
(reduce #(update %1 %2 add-delta)
transforms
shape-ids)))
manage-root
(fn [transforms main-shape copy-shape]
(let [main-modifiers (get-in modifiers [(:id main-shape) :modifiers])
modified-main (gsh/apply-modifiers main-shape main-modifiers)
delta (gpt/subtract (gsh/orig-pos main-shape)
(gsh/orig-pos modified-main))]
(cond-> transforms
(not (gpt/almost-zero? delta))
(apply-delta (:id copy-shape) delta))))
manage-nonroot
(fn [transforms main-shape copy-shape]
; TODO: comparar el orig-pos de la main-shape modificada con el del su propio
; root también modificado (antes de rotación). Si es menor que cero en alguno
; de los dos ejes, añadir un desplazamiento al root y todos sus hijos
(let [main-root (ctn/get-root-shape objects main-shape)
main-root-modifiers (get-in modifiers [(:id main-root) :modifiers])
modified-main-root (gsh/apply-modifiers main-root main-root-modifiers)
main-shape-modifiers (get-in modifiers [(:id main-shape) :modifiers])
modified-main-shape (gsh/apply-modifiers main-shape main-shape-modifiers)
delta (gpt/subtract (gsh/orig-pos modified-main-shape)
(gsh/orig-pos modified-main-root))
delta-x (- (min 0 (:x delta)))
delta-y (- (min 0 (:y delta)))]
(if (or (pos? delta-x) (pos? delta-y))
(let [copy-root (ctn/get-root-shape objects copy-shape)]
(apply-delta transforms (:id copy-root) (gpt/point delta-x delta-y)))
transforms)))
add-all-transforms
(fn [transforms [main-shape copy-shape]]
(js/console.log "----------------------")
(js/console.log "main-shape" (clj->js main-shape))
(js/console.log "copy-shape" (clj->js copy-shape))
(as-> transforms $
(add-copy-transforms $ main-shape copy-shape)
(if (ctk/instance-root? main-shape)
(manage-root $ main-shape copy-shape)
(manage-nonroot $ main-shape copy-shape))))]
(js/console.log "==================")
(reduce add-all-transforms
transforms
copy-shapes))))
;; (let [translate1
;; (fn [shape modifiers]
;; (let [root-shape (ctn/get-root-shape objects shape)
;; root-pos (gsh/orig-pos root-shape)
;;
;; modified-shape (gsh/apply-modifiers shape modifiers)
;; modified-pos (gsh/orig-pos modified-shape)]
;; ;; (js/console.log "root-pos" (clj->js root-pos))
;; ;; (js/console.log "modified-pos" (clj->js modified-pos))
;; (if (or (< (:x modified-pos) (:x root-pos))
;; (< (:y modified-pos) (:y root-pos)))
;; (let [displacement (get modifiers :displacement (gmt/matrix))
;; delta (gpt/point (max 0 (- (:x root-pos) (:x modified-pos)))
;; (max 0 (- (:y root-pos) (:y modified-pos))))]
;; [(assoc modifiers :displacement
;; (gmt/add-translate displacement
;; (gmt/translate-matrix delta)))
;; delta])
;; [modifiers (gpt/point 0 0)])))
;;
;; get-copy-transform
;; (fn [[main-shape copy-shape]]
;; (js/console.log "----------------------")
;; (js/console.log "main-shape" (clj->js main-shape))
;; (js/console.log "copy-shape" (clj->js copy-shape))
;; (let [[main-modifiers deltaa] (->> (get-in modifiers [(:id main-shape) :modifiers])
;; (translate1 main-shape))
;;
;; main-bounds (gsh/bounding-box main-shape)
;; copy-bounds (gpt/add (gpt/point
;; (:x (gsh/bounding-box copy-shape))
;; (:y (gsh/bounding-box copy-shape)))
;; deltaa)
;; delta (gpt/subtract (gpt/point (:x copy-bounds) (:y copy-bounds))
;; (gpt/point (:x main-bounds) (:y main-bounds)))
;;
;; root-shape (ctn/get-root-shape objects main-shape)
;; root-modifiers (get-in modifiers [(:id root-shape) :modifiers])
;; _ (js/console.log "main-modifiers" (clj->js main-modifiers))
;; _ (js/console.log "root-modifiers" (clj->js root-modifiers))
;;
;; ;; root-shape (ctn/get-root-shape objects copy-shape)
;; ;; root-pos (gsh/orig-pos root-shape)
;; ;; copy-pos (gsh/orig-pos copy-shape)
;;
;; ;; Move the modifier origin points to the position of the copy.
;; copy-modifiers (let [origin (:resize-origin main-modifiers)
;; origin-2 (:resize-origin-2 main-modifiers)]
;; (cond-> main-modifiers
;; (some? origin)
;; (assoc :resize-origin (gpt/add origin delta))
;;
;; (some? origin-2)
;; (assoc :resize-origin-2 (gpt/add origin-2 delta))
;;
;; ;; (gpt/close? root-pos copy-pos)
;; ;; (dissoc :displacement)
;; ))
;;
;; center (gsh/center-shape copy-shape)]
;;
;; ;; (js/console.log "delta" (clj->js delta))
;; ;; (js/console.log "main-modifiers" (clj->js main-modifiers))
;; ;; (js/console.log "main-transform" (str (gsh/modifiers->transform
;; ;; (gsh/center-shape main-shape)
;; ;; main-modifiers)))
;; ;; (js/console.log "copy-modifiers" (clj->js copy-modifiers))
;; ;; (js/console.log "copy-transform" (str (gsh/modifiers->transform
;; ;; center copy-modifiers)))
;; (gsh/modifiers->transform center copy-modifiers)))]
;;
;; (reduce #(assoc %1 (:id (second %2)) (get-copy-transform %2))
;; transforms
;; copy-shapes))))
shapes
(mf/use-memo
(mf/deps transforms)
(fn []
(map #(get objects %) (keys transforms))))]
(mf/use-layout-effect (mf/use-layout-effect
(mf/deps transforms) (mf/deps transforms)

View File

@ -302,7 +302,7 @@
; Renamed component ; Renamed component
; Rect-1 ; Rect-1
(let [libs (wsh/get-libraries new-state) (let [libs (wsh/get-libraries new-state)
component (cph/get-component libs component (ctf/get-component libs
(:component-file instance1) (:component-file instance1)
(:component-id instance1))] (:component-id instance1))]
(t/is (= (:name component) (t/is (= (:name component)
@ -400,7 +400,7 @@
(:id instance1)) (:id instance1))
libs (wsh/get-libraries new-state) libs (wsh/get-libraries new-state)
component (cph/get-component libs component (ctf/get-component libs
(:component-file instance1) (:component-file instance1)
(:component-id instance1))] (:component-id instance1))]

View File

@ -5,6 +5,7 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.types.component :as ctk] [app.common.types.component :as ctk]
[app.common.types.container :as ctn] [app.common.types.container :as ctn]
[app.common.types.file :as ctf]
[app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.state-helpers :as wsh]
[app.test-helpers.pages :as thp])) [app.test-helpers.pages :as thp]))
@ -85,7 +86,7 @@
root-inst (ctn/get-shape page root-inst-id) root-inst (ctn/get-shape page root-inst-id)
libs (wsh/get-libraries state) libs (wsh/get-libraries state)
component (cph/get-component libs (:component-id root-inst)) component (ctf/get-component libs (:component-id root-inst))
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id) shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst)) shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
@ -94,10 +95,10 @@
main-exists? (fn [shape] main-exists? (fn [shape]
(let [component-shape (let [component-shape
(cph/get-component-shape (:objects page) shape) (ctn/get-component-shape (:objects page) shape)
component component
(cph/get-component libs (:component-id component-shape)) (ctf/get-component libs (:component-id component-shape))
main-shape main-shape
(ctn/get-shape component (:shape-ref shape))] (ctn/get-shape component (:shape-ref shape))]
@ -125,7 +126,7 @@
root-inst (ctn/get-shape page root-inst-id) root-inst (ctn/get-shape page root-inst-id)
libs (wsh/get-libraries state) libs (wsh/get-libraries state)
component (cph/get-component libs (:component-id root-inst)) component (ctf/get-component libs (:component-id root-inst))
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id) shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst)) shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
@ -134,10 +135,10 @@
main-exists? (fn [shape] main-exists? (fn [shape]
(let [component-shape (let [component-shape
(cph/get-component-shape (:objects page) shape) (ctn/get-component-shape (:objects page) shape)
component component
(cph/get-component libs (:component-id component-shape)) (ctf/get-component libs (:component-id component-shape))
main-shape main-shape
(ctn/get-shape component (:shape-ref shape))] (ctn/get-shape component (:shape-ref shape))]
@ -154,7 +155,7 @@
[state component-id] [state component-id]
(let [page (thp/current-page state) (let [page (thp/current-page state)
libs (wsh/get-libraries state) libs (wsh/get-libraries state)
component (cph/get-component libs component-id) component (ctf/get-component libs component-id)
root-main (ctk/get-component-root component) root-main (ctk/get-component-root component)
shapes-main (cph/get-children-with-self (:objects component) (:id root-main))] shapes-main (cph/get-children-with-self (:objects component) (:id root-main))]