diff --git a/common/src/app/common/geom/matrix.cljc b/common/src/app/common/geom/matrix.cljc index b8e0bf19e..b0b200997 100644 --- a/common/src/app/common/geom/matrix.cljc +++ b/common/src/app/common/geom/matrix.cljc @@ -219,3 +219,13 @@ e' (/ (- (* c f) (* d e)) det) f' (/ (- (* b e) (* a f)) det)] (Matrix. a' b' c' d' e' f'))) + +(defn round + [mtx] + (-> mtx + (update :a mth/precision 4) + (update :b mth/precision 4) + (update :c mth/precision 4) + (update :d mth/precision 4) + (update :e mth/precision 4) + (update :f mth/precision 4))) diff --git a/frontend/src/app/main/data/workspace/state_helpers.cljs b/frontend/src/app/main/data/workspace/state_helpers.cljs index 4da32f002..9b4986922 100644 --- a/frontend/src/app/main/data/workspace/state_helpers.cljs +++ b/frontend/src/app/main/data/workspace/state_helpers.cljs @@ -8,7 +8,9 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.pages.helpers :as cph])) + [app.common.geom.shapes :as gsh] + [app.common.pages.helpers :as cph] + [app.common.path.commands :as upc])) (defn lookup-page ([state] @@ -50,6 +52,10 @@ (filter selectable?) selected))))) +(defn lookup-selected-raw + [state] + (dm/get-in state [:workspace-local :selected])) + (defn lookup-selected ([state] (lookup-selected state nil)) @@ -94,3 +100,26 @@ (-> (:workspace-libraries state) (assoc id {:id id :data local})))) + +(defn- set-content-modifiers [state] + (fn [id shape] + (let [content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers])] + (if (some? content-modifiers) + (update shape :content upc/apply-content-modifiers content-modifiers) + shape)))) + +(defn select-bool-children + [parent-id state] + (let [objects (lookup-page-objects state) + selected (lookup-selected-raw state) + modifiers (:workspace-modifiers state) + + children-ids (cph/get-children-ids objects parent-id) + selected-children (into [] (filter selected) children-ids) + + modifiers (select-keys modifiers selected-children) + children (select-keys objects children-ids)] + + (as-> children $ + (gsh/merge-modifiers $ modifiers) + (d/mapm (set-content-modifiers state) $)))) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 839ff694c..24b48c0aa 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -9,9 +9,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.geom.shapes :as gsh] [app.common.pages.helpers :as cph] - [app.common.path.commands :as upc] [app.main.data.workspace.state-helpers :as wsh] [app.main.store :as st] [okulary.core :as l])) @@ -193,28 +191,29 @@ (assoc :pages (:pages data))))) st/state =)) +(def workspace-data + (l/derived :workspace-data st/state)) + (def workspace-file-colors - (l/derived (fn [state] - (when-let [file (:workspace-data state)] - (->> (:colors file) - (d/mapm #(assoc %2 :file-id (:id file)))))) - st/state)) + (l/derived (fn [data] + (when data + (->> (:colors data) + (d/mapm #(assoc %2 :file-id (:id data)))))) + workspace-data + =)) (def workspace-recent-colors - (l/derived (fn [state] - (dm/get-in state [:workspace-data :recent-colors] [])) - st/state)) + (l/derived (fn [data] + (get data :recent-colors [])) + workspace-data)) (def workspace-recent-fonts - (l/derived (fn [state] - (dm/get-in state [:workspace-data :recent-fonts] [])) - st/state)) + (l/derived (fn [data] + (get data :workspace-data [])) + workspace-data)) (def workspace-file-typography - (l/derived (fn [state] - (when-let [file (:workspace-data state)] - (:typographies file))) - st/state)) + (l/derived :typographies workspace-data)) (def workspace-project (l/derived :workspace-project st/state)) @@ -313,24 +312,8 @@ workspace-modifiers-with-objects =)) -(defn- set-content-modifiers [state] - (fn [id shape] - (let [content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers])] - (if (some? content-modifiers) - (update shape :content upc/apply-content-modifiers content-modifiers) - shape)))) - (defn select-bool-children [id] - (let [selector - (fn [state] - (let [objects (wsh/lookup-page-objects state) - modifiers (:workspace-modifiers state) - children (->> (cph/get-children-ids objects id) - (select-keys objects))] - (as-> children $ - (gsh/merge-modifiers $ modifiers) - (d/mapm (set-content-modifiers state) $))))] - (l/derived selector st/state =))) + (l/derived (partial wsh/select-bool-children id) st/state =)) (def selected-data (l/derived #(let [selected (wsh/lookup-selected %) diff --git a/frontend/src/app/main/ui/shapes/filters.cljs b/frontend/src/app/main/ui/shapes/filters.cljs index b5cf278f2..c3b957401 100644 --- a/frontend/src/app/main/ui/shapes/filters.cljs +++ b/frontend/src/app/main/ui/shapes/filters.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.shapes.filters (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.geom.shapes :as gsh] [app.common.math :as mth] [app.common.uuid :as uuid] @@ -249,6 +250,7 @@ :height filter-height :filterUnits "objectBoundingBox" :color-interpolation-filters "sRGB"} - (for [entry filters] - [:& filter-entry {:entry entry}])]))) + (for [[index entry] (d/enumerate filters)] + [:& filter-entry {:key (dm/str filter-id "-" index) + :entry entry}])]))) diff --git a/frontend/src/app/main/ui/shapes/text/svg_text.cljs b/frontend/src/app/main/ui/shapes/text/svg_text.cljs index 79d1127f1..4c8054c24 100644 --- a/frontend/src/app/main/ui/shapes/text/svg_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/svg_text.cljs @@ -64,6 +64,7 @@ ;; These position attributes are not really necesary but they are convenient for for the export group-props (-> #js {:transform transform + :className "text-container" :x x :y y :width width diff --git a/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs b/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs index e465205c7..14620a762 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame/dynamic_modifiers.cljs @@ -81,6 +81,7 @@ (let [shape-node (dom/query base-node (str "#shape-" id)) frame? (= :frame type) + text? (= :text type) group? (= :group type) mask? (and group? masked-group?)] @@ -103,6 +104,10 @@ (dom/query-all shape-defs ".svg-def") (dom/query-all shape-defs ".svg-mask-wrapper"))) + text? + [shape-node + (dom/query shape-node ".text-container")] + :else [shape-node]))) @@ -161,6 +166,10 @@ (str value))] (dom/set-attribute! node att (str new-value)))) +(defn override-transform-att! + [node att value] + (dom/set-attribute! node att (str value))) + (defn update-transform! [base-node shapes transforms modifiers] (doseq [{:keys [id] :as shape} shapes] @@ -179,6 +188,17 @@ (dom/class? node "frame-children") (set-transform-att! node "transform" (gmt/inverse transform)) + ;; We need to update the shape transform matrix when there is a resize + ;; we do it dinamicaly here + (dom/class? node "text-container") + (let [modifiers (dissoc modifiers :displacement :rotation)] + (when (not (gsh/empty-modifiers? modifiers)) + (let [mtx (-> shape + (assoc :modifiers modifiers) + (gsh/transform-shape) + (gsh/transform-matrix {:no-flip true}))] + (override-transform-att! node "transform" mtx)))) + (or (= (dom/get-tag-name node) "mask") (= (dom/get-tag-name node) "filter")) (transform-region! node modifiers) diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index 1fe11720e..1c22c42d1 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -166,7 +166,8 @@ (:name frame)]])) (mf/defc frame-titles - {::mf/wrap-props false} + {::mf/wrap-props false + ::mf/wrap [mf/memo]} [props] (let [objects (unchecked-get props "objects") zoom (unchecked-get props "zoom")