From 11f347941eae4bde24ba0ad053b25d6acd176c03 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 19 Oct 2022 13:27:44 +0200 Subject: [PATCH] :sparkles: Refactor for new modifiers --- .../app/common/geom/shapes/constraints.cljc | 78 ++--- common/src/app/common/geom/shapes/layout.cljc | 185 +++------- .../src/app/common/geom/shapes/modifiers.cljc | 187 +--------- .../common/geom/shapes/pixel_precision.cljc | 53 +++ common/src/app/common/geom/shapes/points.cljc | 61 ++++ .../app/common/geom/shapes/transforms.cljc | 163 +-------- common/src/app/common/types/modifiers.cljc | 325 +++++++++++------- .../app/main/data/workspace/drawing/box.cljs | 5 +- .../src/app/main/data/workspace/shapes.cljs | 1 - .../src/app/main/data/workspace/texts.cljs | 8 +- .../app/main/data/workspace/transforms.cljs | 88 ++--- .../src/app/main/ui/workspace/shapes.cljs | 2 +- .../shapes/frame/dynamic_modifiers.cljs | 104 +----- .../shapes/text/viewport_texts_html.cljs | 7 - .../app/main/ui/workspace/viewport/debug.cljs | 2 +- 15 files changed, 445 insertions(+), 824 deletions(-) create mode 100644 common/src/app/common/geom/shapes/pixel_precision.cljc create mode 100644 common/src/app/common/geom/shapes/points.cljc diff --git a/common/src/app/common/geom/shapes/constraints.cljc b/common/src/app/common/geom/shapes/constraints.cljc index 2e9aa8a9b..ce4171d02 100644 --- a/common/src/app/common/geom/shapes/constraints.cljc +++ b/common/src/app/common/geom/shapes/constraints.cljc @@ -6,13 +6,13 @@ (ns app.common.geom.shapes.constraints (:require - [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.intersect :as gsi] [app.common.geom.shapes.rect :as gre] [app.common.geom.shapes.transforms :as gst] [app.common.math :as mth] + [app.common.types.modifiers :as ctm] [app.common.uuid :as uuid])) ;; Auxiliary methods to work in an specifica axis @@ -152,8 +152,7 @@ end-angl (gpt/angle-with-other end-before end-after) target-end (if (mth/close? end-angl 180) (- (gpt/length end-before)) (gpt/length end-before)) disp-vector-end (gpt/subtract end-after (gpt/scale (gpt/unit end-after) target-end))] - [{:type :move - :vector disp-vector-end}])) + (ctm/move disp-vector-end))) (defmethod constraint-modifier :fixed [_ axis child-points-before parent-points-before child-points-after parent-points-after transformed-parent] @@ -177,11 +176,7 @@ scale (* resize-sign (/ (gpt/length after-vec) (gpt/length before-vec))) ] - [{:type :resize - :vector (get-scale axis scale) - :origin c0 - :transform (:transform transformed-parent) - :transform-inverse (:transform-inverse transformed-parent)}])) + (ctm/resize (get-scale axis scale) c0 (:transform transformed-parent) (:transform-inverse transformed-parent)))) (defmethod constraint-modifier :center [_ axis child-points-before parent-points-before child-points-after parent-points-after] @@ -190,8 +185,7 @@ center-angl (gpt/angle-with-other center-before center-after) target-center (if (mth/close? center-angl 180) (- (gpt/length center-before)) (gpt/length center-before)) disp-vector-center (gpt/subtract center-after (gpt/scale (gpt/unit center-after) target-center))] - [{:type :move - :vector disp-vector-center}])) + (ctm/move disp-vector-center))) (defmethod constraint-modifier :default [_ _ _ _ _] []) @@ -222,29 +216,6 @@ :top :scale))) -#_(defn clean-modifiers - "Remove redundant modifiers" - [{:keys [displacement resize-vector resize-vector-2] :as modifiers}] - - (cond-> modifiers - ;; Displacement with value 0. We don't move in any direction - (and (some? displacement) - (mth/almost-zero? (:e displacement)) - (mth/almost-zero? (:f displacement))) - (dissoc :displacement) - - ;; Resize with value very close to 1 means no resize - (and (some? resize-vector) - (mth/almost-zero? (- 1.0 (:x resize-vector))) - (mth/almost-zero? (- 1.0 (:y resize-vector)))) - (dissoc :resize-origin :resize-vector) - - (and (some? resize-vector) - (mth/almost-zero? (- 1.0 (:x resize-vector-2))) - (mth/almost-zero? (- 1.0 (:y resize-vector-2)))) - (dissoc :resize-origin-2 :resize-vector-2))) - - (defn bounding-box-parent-transform "Returns a bounding box for the child in the same coordinate system as the parent. @@ -259,36 +230,27 @@ (defn normalize-modifiers "Before aplying constraints we need to remove the deformation caused by the resizing of the parent" - [constraints-h constraints-v modifiers child parent transformed-child transformed-parent] + [constraints-h constraints-v modifiers child parent transformed-child {:keys [transform transform-inverse] :as transformed-parent}] (let [child-bb-before (gst/parent-coords-rect child parent) child-bb-after (gst/parent-coords-rect transformed-child transformed-parent) scale-x (/ (:width child-bb-before) (:width child-bb-after)) - scale-y (/ (:height child-bb-before) (:height child-bb-after))] + scale-y (/ (:height child-bb-before) (:height child-bb-after)) - (-> modifiers - (update :v2 #(cond-> % - (not= :scale constraints-h) - (conj - ;; This resize will leave the shape in its original position relative to the parent - {:type :resize - :transform (:transform transformed-parent) - :transform-inverse (:transform-inverse transformed-parent) - :origin (-> transformed-parent :points (nth 0)) - :vector (gpt/point scale-x 1)}) + ;; TODO LAYOUT: Is the first always the origin? + resize-origin (-> transformed-parent :points first)] - (not= :scale constraints-v) - (conj - {:type :resize - :transform (:transform transformed-parent) - :transform-inverse (:transform-inverse transformed-parent) - :origin (-> transformed-parent :points (nth 0)) - :vector (gpt/point 1 scale-y)})))))) + (cond-> modifiers + (not= :scale constraints-h) + (ctm/set-resize (gpt/point scale-x 1) resize-origin transform transform-inverse) + + (not= :scale constraints-v) + (ctm/set-resize (gpt/point 1 scale-y) resize-origin transform transform-inverse)))) (defn calc-child-modifiers [parent child modifiers ignore-constraints transformed-parent] - (let [modifiers (select-keys modifiers [:v2]) + (let [modifiers (ctm/select-child-modifiers modifiers) constraints-h (if-not ignore-constraints @@ -306,12 +268,12 @@ (let [transformed-child (gst/transform-shape child modifiers) modifiers (normalize-modifiers constraints-h constraints-v modifiers child parent transformed-child transformed-parent) - tranformed-child-2 (gst/transform-shape child modifiers) + transformed-child (gst/transform-shape child modifiers) parent-points-before (:points parent) child-points-before (bounding-box-parent-transform child parent) parent-points-after (:points transformed-parent) - child-points-after (bounding-box-parent-transform tranformed-child-2 transformed-parent) + child-points-after (bounding-box-parent-transform transformed-child transformed-parent) modifiers-h (constraint-modifier (constraints-h const->type+axis) :x child-points-before parent-points-before @@ -323,6 +285,6 @@ child-points-after parent-points-after transformed-parent)] - (update modifiers :v2 d/concat-vec modifiers-h modifiers-v))))) - - + (-> modifiers + (ctm/add-modifiers modifiers-h) + (ctm/add-modifiers modifiers-v)))))) diff --git a/common/src/app/common/geom/shapes/layout.cljc b/common/src/app/common/geom/shapes/layout.cljc index a5f0d79c5..d3282b357 100644 --- a/common/src/app/common/geom/shapes/layout.cljc +++ b/common/src/app/common/geom/shapes/layout.cljc @@ -10,9 +10,11 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] + [app.common.geom.shapes.points :as gpo] [app.common.geom.shapes.rect :as gsr] [app.common.geom.shapes.transforms :as gst] - [app.common.pages.helpers :as cph])) + [app.common.pages.helpers :as cph] + [app.common.types.modifiers :as ctm])) ;; :layout ;; true if active, false if not ;; :layout-dir ;; :right, :left, :top, :bottom @@ -56,107 +58,18 @@ [{:keys [layout-v-orientation]}] (= layout-v-orientation :bottom)) -(defn add-padding [transformed-rect {:keys [layout-padding-type layout-padding]}] - (let [{:keys [p1 p2 p3 p4]} layout-padding - [p1 p2 p3 p4] - (if (= layout-padding-type :multiple) - [p1 p2 p3 p4] - [p1 p1 p1 p1])] - - (-> transformed-rect - (update :y + p1) - (update :width - p2 p3) - (update :x + p3) - (update :height - p1 p4)))) - -;; FUNCTIONS TO WORK WITH POINTS SQUARES - -(defn origin - [points] - (nth points 0)) - -(defn start-hv - "Horizontal vector from the origin with a magnitude `val`" - [[p0 p1 _ _] val] - (-> (gpt/to-vec p0 p1) - (gpt/unit) - (gpt/scale val))) - -(defn end-hv - "Horizontal vector from the oposite to the origin in the x axis with a magnitude `val`" - [[p0 p1 _ _] val] - (-> (gpt/to-vec p1 p0) - (gpt/unit) - (gpt/scale val))) - -(defn start-vv - "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" - [[p0 _ _ p3] val] - (-> (gpt/to-vec p0 p3) - (gpt/unit) - (gpt/scale val))) - -(defn end-vv - "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" - [[p0 _ _ p3] val] - (-> (gpt/to-vec p3 p0) - (gpt/unit) - (gpt/scale val))) - -;;(defn start-hp -;; [[p0 _ _ _ :as points] val] -;; (gpt/add p0 (start-hv points val))) -;; -;;(defn end-hp -;; "Horizontal Vector from the oposite to the origin in the x axis with a magnitude `val`" -;; [[_ p1 _ _ :as points] val] -;; (gpt/add p1 (end-hv points val))) -;; -;;(defn start-vp -;; "Vertical Vector from the oposite to the origin in the x axis with a magnitude `val`" -;; [[p0 _ _ _ :as points] val] -;; (gpt/add p0 (start-vv points val))) -;; -;;(defn end-vp -;; "Vertical Vector from the oposite to the origin in the x axis with a magnitude `val`" -;; [[_ _ p3 _ :as points] val] -;; (gpt/add p3 (end-vv points val))) - -(defn width-points - [[p0 p1 _ _]] - (gpt/length (gpt/to-vec p0 p1))) - -(defn height-points - [[p0 _ _ p3]] - (gpt/length (gpt/to-vec p0 p3))) - -(defn pad-points - [[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left] - (let [top-v (start-vv points pad-top) - right-v (end-hv points pad-right) - bottom-v (end-vv points pad-bottom) - left-v (start-hv points pad-left)] - - [(-> p0 (gpt/add left-v) (gpt/add top-v)) - (-> p1 (gpt/add right-v) (gpt/add top-v)) - (-> p2 (gpt/add right-v) (gpt/add bottom-v)) - (-> p3 (gpt/add left-v) (gpt/add bottom-v))])) - -;;;; - - (defn calc-layout-lines [{:keys [layout-gap layout-wrap-type] :as parent} children layout-bounds] (let [wrap? (= layout-wrap-type :wrap) - layout-width (width-points layout-bounds) - layout-height (height-points layout-bounds) + layout-width (gpo/width-points layout-bounds) + layout-height (gpo/height-points layout-bounds) reduce-fn (fn [[{:keys [line-width line-height num-children line-fill? child-fill? num-child-fill] :as line-data} result] child] (let [child-bounds (gst/parent-coords-points child parent) - child-width (width-points child-bounds) - child-height (height-points child-bounds) + child-width (gpo/width-points child-bounds) + child-height (gpo/height-points child-bounds) col? (col? parent) row? (row? parent) @@ -212,8 +125,8 @@ (defn calc-layout-lines-position [{:keys [layout-gap] :as parent} layout-bounds layout-lines] - (let [layout-width (width-points layout-bounds) - layout-height (height-points layout-bounds) + (let [layout-width (gpo/width-points layout-bounds) + layout-height (gpo/height-points layout-bounds) row? (row? parent) col? (col? parent) space-between? (= :space-between (:layout-type parent)) @@ -225,16 +138,16 @@ (letfn [;; short version to not repeat always with all arguments (xv [val] - (start-hv layout-bounds val)) + (gpo/start-hv layout-bounds val)) ;; short version to not repeat always with all arguments (yv [val] - (start-vv layout-bounds val)) + (gpo/start-vv layout-bounds val)) (get-base-line [total-width total-height] - (cond-> (origin layout-bounds) + (cond-> (gpo/origin layout-bounds) (and row? h-center?) (gpt/add (xv (/ (- layout-width total-width) 2))) @@ -348,8 +261,8 @@ layout-bounds {:keys [num-children line-width line-height child-fill?] :as line-data}] - (let [width (width-points layout-bounds) - height (height-points layout-bounds) + (let [width (gpo/width-points layout-bounds) + height (gpo/height-points layout-bounds) layout-gap (cond @@ -396,8 +309,8 @@ v-end? (v-end? parent) points (:points parent) - xv (partial start-hv points) - yv (partial start-vv points) + xv (partial gpo/start-hv points) + yv (partial gpo/start-vv points) corner-p (cond-> start-p @@ -447,26 +360,18 @@ (cond (and (col? parent) (= :fill layout-h-behavior) child-fill?) - (let [layout-width (width-points layout-bounds) + (let [layout-width (gpo/width-points layout-bounds) fill-space (- layout-width line-width (* layout-gap (dec num-children))) fill-width (/ fill-space (:num-child-fill layout-data)) fill-scale (/ fill-width child-width)] + {:width fill-width - :modifiers [{:type :resize - :origin child-origin - :transform transform - :transform-inverse transform-inverse - :vector (gpt/point fill-scale 1)}]}) + :modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)}) (and (row? parent) (= :fill layout-h-behavior) line-fill?) (let [fill-scale (/ line-width child-width)] {:width line-width - :modifiers [{:type :resize - :origin child-origin - :transform transform - :transform-inverse transform-inverse - :vector (gpt/point fill-scale 1)}]}) - )) + :modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)}))) (defn calc-fill-height-data "Calculates the size and modifiers for the height of an auto-fill child" @@ -477,43 +382,33 @@ (cond (and (row? parent) (= :fill layout-v-behavior) child-fill?) - (let [layout-height (height-points layout-bounds) + (let [layout-height (gpo/height-points layout-bounds) fill-space (- layout-height line-height (* layout-gap (dec num-children))) fill-height (/ fill-space (:num-child-fill layout-data)) fill-scale (/ fill-height child-height)] {:height fill-height - :modifiers [{:type :resize - :origin child-origin - :transform transform - :transform-inverse transform-inverse - :vector (gpt/point 1 fill-scale)}]}) + :modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)}) (and (col? parent) (= :fill layout-v-behavior) line-fill?) (let [fill-scale (/ line-height child-height)] {:height line-height - :modifiers [{:type :resize - :origin child-origin - :transform transform - :transform-inverse transform-inverse - :vector (gpt/point 1 fill-scale)}]}) - )) + :modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)}))) (defn normalize-child-modifiers "Apply the modifiers and then normalized them against the parent coordinates" - [parent child modifiers transformed-parent] + [parent child modifiers {:keys [transform transform-inverse] :as transformed-parent}] (let [transformed-child (gst/transform-shape child modifiers) child-bb-before (gst/parent-coords-rect child parent) child-bb-after (gst/parent-coords-rect transformed-child transformed-parent) scale-x (/ (:width child-bb-before) (:width child-bb-after)) - scale-y (/ (:height child-bb-before) (:height child-bb-after))] + scale-y (/ (:height child-bb-before) (:height child-bb-after)) + + resize-origin (-> transformed-parent :points first) ;; TODO LAYOUT: IS always the origin?n + resize-vector (gpt/point scale-x scale-y)] (-> modifiers - (update :v2 #(conj % - {:type :resize - :transform (:transform transformed-parent) - :transform-inverse (:transform-inverse transformed-parent) - :origin (-> transformed-parent :points (nth 0)) - :vector (gpt/point scale-x scale-y)}))))) + (ctm/select-child-modifiers) + (ctm/set-resize resize-vector resize-origin transform transform-inverse)))) (defn calc-layout-data "Digest the layout data to pass it to the constrains" @@ -529,7 +424,7 @@ ;; Normalize the points to remove flips points (gst/parent-coords-points parent parent) - layout-bounds (pad-points points pad-top pad-right pad-bottom pad-left) + layout-bounds (gpo/pad-points points pad-top pad-right pad-bottom pad-left) ;; Reverse reverse? (or (= :left layout-dir) (= :bottom layout-dir)) @@ -549,9 +444,9 @@ [parent child layout-line] (let [child-bounds (gst/parent-coords-points child parent) - child-origin (origin child-bounds) - child-width (width-points child-bounds) - child-height (height-points child-bounds) + child-origin (gpo/origin child-bounds) + child-width (gpo/width-points child-bounds) + child-height (gpo/height-points child-bounds) fill-width (calc-fill-width-data parent child child-origin child-width layout-line) fill-height (calc-fill-height-data parent child child-origin child-height layout-line) @@ -564,15 +459,15 @@ move-vec (gpt/to-vec child-origin corner-p) modifiers - (-> [] - (cond-> fill-width (d/concat-vec (:modifiers fill-width))) - (cond-> fill-height (d/concat-vec (:modifiers fill-height))) - (conj {:type :move :vector move-vec}))] + (-> (ctm/empty-modifiers) + (cond-> fill-width (ctm/add-modifiers (:modifiers fill-width))) + (cond-> fill-height (ctm/add-modifiers (:modifiers fill-height))) + (ctm/set-move move-vec))] [modifiers layout-line])) -(defn drop-areas +(defn layout-drop-areas [{:keys [margin-x margin-y] :as frame} layout-data children] (let [col? (col? frame) @@ -730,6 +625,6 @@ position (gmt/transform-point-center position (gco/center-shape frame) (:transform-inverse frame)) children (cph/get-immediate-children objects frame-id) layout-data (calc-layout-data frame children) - drop-areas (drop-areas frame layout-data children) + drop-areas (layout-drop-areas frame layout-data children) area (d/seek #(gsr/contains-point? % position) drop-areas)] (:index area))) diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index 6cb5f0d6f..3660aec60 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -7,118 +7,22 @@ (ns app.common.geom.shapes.modifiers (:require [app.common.data :as d] - [app.common.geom.matrix :as gmt] - [app.common.geom.point :as gpt] - [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.constraints :as gct] [app.common.geom.shapes.layout :as gcl] - [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.pixel-precision :as gpp] [app.common.geom.shapes.transforms :as gtr] - [app.common.math :as mth] [app.common.types.modifiers :as ctm] [app.common.uuid :as uuid])) -;; TODO LAYOUT: ADAPT TO NEW MODIFIERS -(defn set-pixel-precision - "Adjust modifiers so they adjust to the pixel grid" - [modifiers shape] - - (if (and (some? (:resize-transform modifiers)) - (not (gmt/unit? (:resize-transform modifiers)))) - ;; If we're working with a rotation we don't handle pixel precision because - ;; the transformation won't have the precision anyway - modifiers - - (let [center (gco/center-shape shape) - base-bounds (-> (:points shape) (gpr/points->rect)) - - raw-bounds - (-> (gtr/transform-bounds (:points shape) center modifiers) - (gpr/points->rect)) - - flip-x? (neg? (get-in modifiers [:resize-vector :x])) - flip-y? (or (neg? (get-in modifiers [:resize-vector :y])) - (neg? (get-in modifiers [:resize-vector-2 :y]))) - - path? (= :path (:type shape)) - vertical-line? (and path? (<= (:width raw-bounds) 0.01)) - horizontal-line? (and path? (<= (:height raw-bounds) 0.01)) - - target-width (if vertical-line? - (:width raw-bounds) - (max 1 (mth/round (:width raw-bounds)))) - - target-height (if horizontal-line? - (:height raw-bounds) - (max 1 (mth/round (:height raw-bounds)))) - - target-p (cond-> (gpt/round (gpt/point raw-bounds)) - flip-x? - (update :x + target-width) - - flip-y? - (update :y + target-height)) - - ratio-width (/ target-width (:width raw-bounds)) - ratio-height (/ target-height (:height raw-bounds)) - - modifiers - (-> modifiers - (d/without-nils) - (d/update-in-when - [:resize-vector :x] #(* % ratio-width)) - - ;; If the resize-vector-2 modifier arrives means the resize-vector - ;; will only resize on the x axis - (cond-> (nil? (:resize-vector-2 modifiers)) - (d/update-in-when - [:resize-vector :y] #(* % ratio-height))) - - (d/update-in-when - [:resize-vector-2 :y] #(* % ratio-height))) - - origin (get modifiers :resize-origin) - origin-2 (get modifiers :resize-origin-2) - - resize-v (get modifiers :resize-vector) - resize-v-2 (get modifiers :resize-vector-2) - displacement (get modifiers :displacement) - - target-p-inv - (-> target-p - (gpt/transform - (cond-> (gmt/matrix) - (some? displacement) - (gmt/multiply (gmt/inverse displacement)) - - (and (some? resize-v) (some? origin)) - (gmt/scale (gpt/inverse resize-v) origin) - - (and (some? resize-v-2) (some? origin-2)) - (gmt/scale (gpt/inverse resize-v-2) origin-2)))) - - delta-v (gpt/subtract target-p-inv (gpt/point base-bounds)) - - modifiers - (-> modifiers - (d/update-when :displacement #(gmt/multiply (gmt/translate-matrix delta-v) %)) - (cond-> (nil? (:displacement modifiers)) - (assoc :displacement (gmt/translate-matrix delta-v))))] - modifiers))) - - (defn set-children-modifiers [modif-tree objects parent ignore-constraints snap-pixel?] - ;; TODO LAYOUT: SNAP PIXEL! (letfn [(set-child [transformed-parent _snap-pixel? modif-tree child] (let [modifiers (get-in modif-tree [(:id parent) :modifiers]) child-modifiers (gct/calc-child-modifiers parent child modifiers ignore-constraints transformed-parent) - ;;child-modifiers (cond-> child-modifiers snap-pixel? (set-pixel-precision child)) - ] + child-modifiers (cond-> child-modifiers snap-pixel? (gpp/set-pixel-precision child))] (cond-> modif-tree (not (ctm/empty-modifiers? child-modifiers)) - (update-in [(:id child) :modifiers :v2] d/concat-vec (:v2 child-modifiers)))))] - + (update-in [(:id child) :modifiers] ctm/add-modifiers child-modifiers))))] (let [children (map (d/getf objects) (:shapes parent)) modifiers (get-in modif-tree [(:id parent) :modifiers]) transformed-parent (gtr/transform-shape parent modifiers)] @@ -144,7 +48,7 @@ child-modifiers (gcl/normalize-child-modifiers parent child modifiers transformed-parent)] (cond-> modif-tree (not (ctm/empty-modifiers? child-modifiers)) - (update-in [(:id child) :modifiers :v2] d/concat-vec (:v2 child-modifiers))))) + (update-in [(:id child) :modifiers] ctm/add-modifiers child-modifiers)))) (apply-modifiers [modif-tree child] (let [modifiers (get-in modif-tree [(:id child) :modifiers])] @@ -162,7 +66,7 @@ modif-tree (cond-> modif-tree (d/not-empty? modifiers) - (update-in [(:id child) :modifiers :v2] d/concat-vec modifiers))] + (update-in [(:id child) :modifiers] ctm/add-modifiers modifiers))] [layout-line modif-tree]))] @@ -186,7 +90,7 @@ pending (rest layout-lines) from-idx 0] - + (if (and (some? layout-line) (<= from-idx max-idx)) (let [to-idx (+ from-idx (:num-children layout-line)) children (subvec children from-idx to-idx) @@ -197,73 +101,6 @@ modif-tree))))) -#_(defn set-layout-modifiers' - ;; TODO LAYOUT: SNAP PIXEL! - [modif-tree objects parent _snap-pixel?] - - (letfn [(transform-child [child] - (let [modifiers (get modif-tree (:id child)) - - child - (cond-> child - (some? modifiers) - (-> (merge modifiers) gtr/transform-shape) - - (and (nil? modifiers) (group? child)) - (gtr/apply-group-modifiers objects modif-tree)) - - child - (-> child - (gtr/apply-transform (gmt/transform-in (gco/center-shape parent) (:transform-inverse parent))))] - - child)) - - (set-layout-modifiers [parent transform [layout-data modif-tree] child] - (let [[modifiers layout-data] - (gcl/calc-layout-modifiers parent transform child layout-data) - - modif-tree - (cond-> modif-tree - (d/not-empty? modifiers) - (update-in [(:id child) :modifiers :v2] d/concat-vec modifiers))] - - [layout-data modif-tree]))] - - (let [modifiers (get modif-tree (:id parent)) - shape (-> parent (merge modifiers) gtr/transform-shape) - children (->> (:shapes shape) - (map (d/getf objects)) - (map transform-child)) - - center (gco/center-shape shape) - {:keys [transform transform-inverse]} shape - - shape - (-> shape - (gtr/apply-transform (gmt/transform-in center transform-inverse))) - - transformed-rect (:selrect shape) - - layout-data (gcl/calc-layout-data shape children transformed-rect) - children (into [] (cond-> children (:reverse? layout-data) reverse)) - - max-idx (dec (count children)) - layout-lines (:layout-lines layout-data)] - - (loop [modif-tree modif-tree - layout-line (first layout-lines) - pending (rest layout-lines) - from-idx 0] - (if (and (some? layout-line) (<= from-idx max-idx)) - (let [to-idx (+ from-idx (:num-children layout-line)) - children (subvec children from-idx to-idx) - - [_ modif-tree] - (reduce (partial set-layout-modifiers shape transform) [layout-line modif-tree] children)] - (recur modif-tree (first pending) (rest pending) to-idx)) - - modif-tree))))) - (defn get-first-layout [id objects] @@ -337,8 +174,11 @@ (let [set-modifiers (fn [modif-tree id] - (let [shape (get objects id) - modifiers (cond-> (get-modifier shape) snap-pixel? (set-pixel-precision shape))] + (let [root? (= uuid/zero id) + shape (get objects id) + modifiers (cond-> (get-modifier shape) + (and (not root?) snap-pixel?) + (gpp/set-pixel-precision shape))] (-> modif-tree (assoc id {:modifiers modifiers})))) @@ -349,11 +189,12 @@ (->> shapes-tree (reduce (fn [modif-tree shape] - (let [modifiers (get-in modif-tree [(:id shape) :modifiers]) + (let [root? (= uuid/zero (:id shape)) + modifiers (get-in modif-tree [(:id shape) :modifiers]) has-modifiers? (some? modifiers) is-layout? (layout? shape) is-parent? (or (group? shape) (and (frame? shape) (not (layout? shape)))) - root? (= uuid/zero (:id shape)) + ;; If the current child is inside the layout we ignore the constraints is-inside-layout? (inside-layout? objects shape)] diff --git a/common/src/app/common/geom/shapes/pixel_precision.cljc b/common/src/app/common/geom/shapes/pixel_precision.cljc new file mode 100644 index 000000000..03aa4359a --- /dev/null +++ b/common/src/app/common/geom/shapes/pixel_precision.cljc @@ -0,0 +1,53 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.common.geom.shapes.pixel-precision + (:require + [app.common.geom.point :as gpt] + [app.common.geom.shapes.points :as gpo] + [app.common.geom.shapes.rect :as gpr] + [app.common.geom.shapes.transforms :as gtr] + [app.common.math :as mth] + [app.common.pages.helpers :as cph] + [app.common.types.modifiers :as ctm])) + +(defn size-pixel-precision + [modifiers shape] + (let [{:keys [points transform transform-inverse] :as shape} (gtr/transform-shape shape modifiers) + origin (gpo/origin points) + curr-width (gpo/width-points points) + curr-height (gpo/height-points points) + + path? (cph/path-shape? shape) + vertical-line? (and path? (<= curr-width 0.01)) + horizontal-line? (and path? (<= curr-height 0.01)) + + target-width (if vertical-line? curr-width (max 1 (mth/round curr-width))) + target-height (if horizontal-line? curr-height (max 1 (mth/round curr-height))) + + ratio-width (/ target-width curr-width) + ratio-height (/ target-height curr-height) + scalev (gpt/point ratio-width ratio-height)] + (-> modifiers + (ctm/set-resize scalev origin transform transform-inverse)))) + +(defn position-pixel-precision + [modifiers shape] + (let [{:keys [points]} (gtr/transform-shape shape modifiers) + bounds (gpr/points->rect points) + corner (gpt/point bounds) + target-corner (gpt/round corner) + deltav (gpt/to-vec corner target-corner)] + (-> modifiers + (ctm/set-move deltav)))) + +(defn set-pixel-precision + "Adjust modifiers so they adjust to the pixel grid" + [modifiers shape] + + (-> modifiers + (size-pixel-precision shape) + (position-pixel-precision shape))) diff --git a/common/src/app/common/geom/shapes/points.cljc b/common/src/app/common/geom/shapes/points.cljc new file mode 100644 index 000000000..1f80f28df --- /dev/null +++ b/common/src/app/common/geom/shapes/points.cljc @@ -0,0 +1,61 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.common.geom.shapes.points + (:require + [app.common.geom.point :as gpt])) + +(defn origin + [points] + (nth points 0)) + +(defn start-hv + "Horizontal vector from the origin with a magnitude `val`" + [[p0 p1 _ _] val] + (-> (gpt/to-vec p0 p1) + (gpt/unit) + (gpt/scale val))) + +(defn end-hv + "Horizontal vector from the oposite to the origin in the x axis with a magnitude `val`" + [[p0 p1 _ _] val] + (-> (gpt/to-vec p1 p0) + (gpt/unit) + (gpt/scale val))) + +(defn start-vv + "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" + [[p0 _ _ p3] val] + (-> (gpt/to-vec p0 p3) + (gpt/unit) + (gpt/scale val))) + +(defn end-vv + "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" + [[p0 _ _ p3] val] + (-> (gpt/to-vec p3 p0) + (gpt/unit) + (gpt/scale val))) + +(defn width-points + [[p0 p1 _ _]] + (gpt/length (gpt/to-vec p0 p1))) + +(defn height-points + [[p0 _ _ p3]] + (gpt/length (gpt/to-vec p0 p3))) + +(defn pad-points + [[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left] + (let [top-v (start-vv points pad-top) + right-v (end-hv points pad-right) + bottom-v (end-vv points pad-bottom) + left-v (start-hv points pad-left)] + + [(-> p0 (gpt/add left-v) (gpt/add top-v)) + (-> p1 (gpt/add right-v) (gpt/add top-v)) + (-> p2 (gpt/add right-v) (gpt/add bottom-v)) + (-> p3 (gpt/add left-v) (gpt/add bottom-v))])) diff --git a/common/src/app/common/geom/shapes/transforms.cljc b/common/src/app/common/geom/shapes/transforms.cljc index 08bf7383e..ce888ddf1 100644 --- a/common/src/app/common/geom/shapes/transforms.cljc +++ b/common/src/app/common/geom/shapes/transforms.cljc @@ -14,8 +14,6 @@ [app.common.geom.shapes.path :as gpa] [app.common.geom.shapes.rect :as gpr] [app.common.math :as mth] - [app.common.pages.helpers :as cph] - [app.common.text :as txt] [app.common.types.modifiers :as ctm] [app.common.uuid :as uuid])) @@ -312,6 +310,8 @@ (dissoc :transform :transform-inverse)) (cond-> (some? selrect) (assoc :selrect selrect)) + + ;; TODO LAYOUT: Make sure the order of points is alright (cond-> (d/not-empty? points) (assoc :points points)) (assoc :rotation rotation)))) @@ -376,113 +376,22 @@ (assoc :flip-x (-> mask :flip-x)) (assoc :flip-y (-> mask :flip-y))))) - -#_(defn- set-flip [shape modifiers] - (let [rv1x (or (get-in modifiers [:resize-vector :x]) 1) - rv1y (or (get-in modifiers [:resize-vector :y]) 1) - rv2x (or (get-in modifiers [:resize-vector-2 :x]) 1) - rv2y (or (get-in modifiers [:resize-vector-2 :y]) 1)] - (cond-> shape - (or (neg? rv1x) (neg? rv2x)) - (-> (update :flip-x not) - (update :rotation -)) - (or (neg? rv1y) (neg? rv2y)) - (-> (update :flip-y not) - (update :rotation -))))) - -#_(defn- set-flip-2 [shape transform] - (let [pt-a (gpt/point (:selrect shape)) - pt-b (gpt/point (-> shape :selrect :x2) (-> shape :selrect :y2)) - - shape-transform (:transform shape (gmt/matrix)) - pt-a' (gpt/transform pt-a (gmt/multiply shape-transform transform )) - pt-b' (gpt/transform pt-b (gmt/multiply shape-transform transform )) - - {:keys [x y]} (gpt/to-vec pt-a' pt-b')] - - (cond-> shape - (neg? x) - (-> (update :flip-x not) - (update :rotation -)) - (neg? y) - (-> (update :flip-y not) - (update :rotation -))))) - -#_(defn- apply-displacement [shape] - (let [modifiers (:modifiers shape)] - (if (contains? modifiers :displacement) - (let [mov-vec (-> (gpt/point 0 0) - (gpt/transform (:displacement modifiers))) - shape (move shape mov-vec) - modifiers (dissoc modifiers :displacement)] - (-> shape - (assoc :modifiers modifiers) - (cond-> (empty-modifiers? modifiers) - (dissoc :modifiers)))) - shape))) - -(defn- apply-text-resize - [shape modifiers] - (if (and (= (:type shape) :text) - (:resize-scale-text modifiers)) - (let [merge-attrs (fn [attrs] - (let [font-size (-> (get attrs :font-size 14) - (d/parse-double) - (* (get-in modifiers [:resize-vector :x] 1)) - (* (get-in modifiers [:resize-vector-2 :x] 1)) - (str))] - (d/txt-merge attrs {:font-size font-size})))] - (update shape :content #(txt/transform-nodes - txt/is-text-node? - merge-attrs - %))) - shape)) - -(defn- apply-structure-modifiers - [shape modifiers] - - (let [remove-children - (fn [shapes children-to-remove] - (let [remove? (set children-to-remove)] - (d/removev remove? shapes))) - - apply-modifier - (fn [shape {:keys [type value index]}] - (cond-> shape - (and (= type :add-children) (some? index)) - (update :shapes - (fn [shapes] - (if (vector? shapes) - (cph/insert-at-index shapes index value) - (d/concat-vec shapes value)))) - - (and (= type :add-children) (nil? index)) - (update :shapes d/concat-vec value) - - (= type :remove-children) - (update :shapes remove-children value)))] - - (reduce apply-modifier shape (:v3 modifiers)))) - (defn apply-modifiers [shape modifiers] - (let [center (gco/center-shape shape) - transform (ctm/modifiers->transform center modifiers)] - + (let [transform (ctm/modifiers->transform modifiers)] (cond-> shape - #_(set-flip-2 transform) (and (some? transform) ;; Never transform the root frame (not= uuid/zero (:id shape))) (apply-transform transform) :always - (apply-structure-modifiers modifiers)))) + (ctm/apply-structure-modifiers modifiers)))) (defn apply-objects-modifiers [objects modifiers] (letfn [(process-shape [objects [id modifier]] - (update objects id apply-modifiers (:modifiers modifier)))] + (d/update-when objects id apply-modifiers (:modifiers modifier)))] (reduce process-shape objects modifiers))) (defn transform-shape @@ -495,66 +404,12 @@ ([shape modifiers] (cond-> shape (and (some? modifiers) (not (ctm/empty-modifiers? modifiers))) - (-> (apply-modifiers modifiers) - (apply-text-resize modifiers))))) - -(defn transform-bounds-v2 - [points center modifiers] - (let [transform (ctm/modifiers->transform center {:v2 modifiers}) - result (gco/transform-points points center transform)] - - ;;(.log js/console "??" (str transform) (clj->js result)) - result) - - #_(letfn [(apply-modifier [points {:keys [type vector origin]}] - (case type - :move - (let [displacement (gmt/translate-matrix vector)] - (gco/transform-points points displacement)) - - :resize - (gco/transform-points points origin (gmt/scale-matrix vector)) - - points))] - (->> modifiers - (reduce apply-modifier points)))) + (apply-modifiers modifiers)))) (defn transform-bounds - [points center {:keys [v2 displacement displacement-after resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}] - - ;; FIXME: Improve Performance - (if (some? v2) - (transform-bounds-v2 points center v2) - (let [resize-transform-inverse (or resize-transform-inverse (gmt/matrix)) - - displacement - (when (some? displacement) - (gmt/multiply resize-transform-inverse displacement)) - - resize-origin - (when (some? resize-origin) - (gmt/transform-point-center resize-origin center resize-transform-inverse)) - - resize-origin-2 - (when (some? resize-origin-2) - (gmt/transform-point-center resize-origin-2 center resize-transform-inverse)) - ] - - (if (and (nil? displacement) (nil? resize-origin) (nil? resize-origin-2) (nil? displacement-after)) - points - - (cond-> points - (some? displacement) - (gco/transform-points displacement) - - (some? resize-origin) - (gco/transform-points resize-origin (gmt/scale-matrix resize-vector)) - - (some? resize-origin-2) - (gco/transform-points resize-origin-2 (gmt/scale-matrix resize-vector-2)) - - (some? displacement-after) - (gco/transform-points displacement-after)))))) + [points center modifiers] + (let [transform (ctm/modifiers->transform modifiers)] + (gco/transform-points points center transform))) (defn transform-selrect [selrect modifiers] diff --git a/common/src/app/common/types/modifiers.cljc b/common/src/app/common/types/modifiers.cljc index 5c905aeff..bd0715aec 100644 --- a/common/src/app/common/types/modifiers.cljc +++ b/common/src/app/common/types/modifiers.cljc @@ -10,70 +10,168 @@ [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] - [app.common.spec :as us])) + [app.common.pages.helpers :as cph] + [app.common.spec :as us] + [app.common.text :as txt])) ;; --- Modifiers -;; The `modifiers` structure contains a list of transformations to -;; do make to a shape, in this order: +;; Moodifiers types +;; - geometry: Geometry +;; * move +;; * resize +;; * rotation +;; - structure-parent: Structure non recursive +;; * add-children +;; * remove-children +;; - structure-child: Structre recursive +;; * scale-content ;; -;; - resize-origin (gpt/point) + resize-vector (gpt/point)q -;; apply a scale vector to all points of the shapes, starting -;; from the origin point. -;; -;; - resize-origin-2 + resize-vector-2 -;; same as the previous one, for cases in that we need to make -;; two vectors from different origin points. -;; -;; - displacement (gmt/matrix) -;; apply a translation matrix to the shape -;; -;; - rotation (gmt/matrix) -;; apply a rotation matrix to the shape -;; -;; - resize-transform (gmt/matrix) + resize-transform-inverse (gmt/matrix) -;; a copy of the rotation matrix currently applied to the shape; -;; this is needed temporarily to apply the resize vectors. -;; -;; - resize-scale-text (bool) -;; tells if the resize vectors must be applied to text shapes -;; or not. + +(def conjv (fnil conj [])) + +;; Public builder API + +(defn empty-modifiers [] + {}) + +(defn set-move + ([modifiers x y] + (set-move modifiers (gpt/point x y))) + + ([modifiers vector] + (-> modifiers + (update :geometry conjv {:type :move :vector vector})))) + +(defn set-resize + ([modifiers vector origin] + (-> modifiers + (update :geometry conjv {:type :resize + :vector vector + :origin origin}))) + + ([modifiers vector origin transform transform-inverse] + (-> modifiers + (update :geometry conjv {:type :resize + :vector vector + :origin origin + :transform transform + :transform-inverse transform-inverse})))) + +(defn set-rotation + [modifiers center angle] + (-> modifiers + (update :geometry conjv {:type :rotation + :center center + :rotation angle}))) + +(defn set-remove-children + [modifiers shapes] + (-> modifiers + (update :structure-parent conjv {:type :remove-children + :value shapes})) + ) + +(defn set-add-children + [modifiers shapes index] + (-> modifiers + (update :structure-parent conjv {:type :add-children + :value shapes + :index index}))) + +(defn set-scale-content + [modifiers value] + (-> modifiers + (update :structure-child conjv {:type :scale-content :value value}))) + + +(defn add-modifiers + [modifiers new-modifiers] + + (cond-> modifiers + (some? (:geometry new-modifiers)) + (update :geometry #(d/concat-vec [] % (:geometry new-modifiers))) + + (some? (:structure-parent new-modifiers)) + (update :structure-parent #(d/concat-vec [] % (:structure-parent new-modifiers))) + + (some? (:structure-child new-modifiers)) + (update :structure-child #(d/concat-vec [] % (:structure-child new-modifiers))))) + + +;; These are convenience methods to create single operation modifiers without the builder (defn move ([x y] - (move (gpt/point x y))) + (set-move (empty-modifiers) (gpt/point x y))) ([vector] - {:v2 [{:type :move :vector vector}]})) + (set-move (empty-modifiers) vector))) (defn resize - [vector origin] - {:v2 [{:type :resize :vector vector :origin origin}]}) + ([vector origin] + (set-resize (empty-modifiers) vector origin)) + + ([vector origin transform transform-inverse] + (set-resize (empty-modifiers) vector origin transform transform-inverse))) + +(defn rotation + [shape center angle] + (let [shape-center (gco/center-shape shape) + rotation (-> (gmt/matrix) + (gmt/rotate angle center) + (gmt/rotate (- angle) shape-center))] + + (-> (empty-modifiers) + (set-rotation shape-center angle) + (set-move (gpt/transform (gpt/point 1 1) rotation))))) + +(defn remove-children + [shapes] + (-> (empty-modifiers) + (set-remove-children shapes))) + +(defn add-children + [shapes index] + (-> (empty-modifiers) + (set-add-children shapes index))) + +(defn scale-content + [value] + (-> (empty-modifiers) + (set-scale-content value))) + +(defn select-child-modifiers + [modifiers] + (select-keys modifiers [:geometry :structure-child])) + +(defn select-structure + [modifiers] + (select-keys modifiers [:structure-parent])) (defn add-move ([object x y] (add-move object (gpt/point x y))) ([object vector] - (assoc-in - object - [:modifiers :displacement] - (gmt/translate-matrix (:x vector) (:y vector))))) + (update object :modifiers (move vector)))) (defn add-resize [object vector origin] - (-> object - (assoc-in [:modifiers :resize-vector] vector) - (assoc-in [:modifiers :resize-origin] origin))) + (update object :modifiers (resize vector origin))) -(defn empty-modifiers? [modifiers] - (empty? (dissoc modifiers :ignore-geometry?))) +(defn empty-modifiers? + [modifiers] + (and (empty? (:geometry modifiers)) + (empty? (:structure-parent modifiers)) + (empty? (:structure-child modifiers)))) -(defn resize-modifiers +(defn change-dimensions [shape attr value] (us/assert map? shape) (us/assert #{:width :height} attr) (us/assert number? value) + (let [{:keys [proportion proportion-lock]} shape size (select-keys (:selrect shape) [:width :height]) new-size (if-not proportion-lock @@ -99,10 +197,8 @@ scalev (gpt/divide (gpt/point width height) (gpt/point sr-width sr-height))] - {:resize-vector scalev - :resize-origin origin - :resize-transform shape-transform - :resize-transform-inverse shape-transform-inv})) + + (resize scalev origin shape-transform shape-transform-inv))) (defn change-orientation-modifiers [shape orientation] @@ -124,26 +220,8 @@ scalev (gpt/divide (gpt/point new-width new-height) (gpt/point sr-width sr-height))] - {:resize-vector scalev - :resize-origin origin - :resize-transform shape-transform - :resize-transform-inverse shape-transform-inv})) -(defn rotation-modifiers - [shape center angle] - (let [shape-center (gco/center-shape shape) - rotation (-> (gmt/matrix) - (gmt/rotate angle center) - (gmt/rotate (- angle) shape-center))] - - {:v2 [{:type :rotation - :center shape-center - :rotation angle} - - {:type :move - :vector (gpt/transform (gpt/point 1 1) rotation)}]} - #_{:rotation angle - :displacement displacement})) + (resize scalev origin shape-transform shape-transform-inv))) (defn merge-modifiers [objects modifiers] @@ -155,7 +233,29 @@ (->> modifiers (reduce set-modifier objects)))) -(defn modifiers-v2->transform +(defn only-move? + [modifier] + (and (= 1 (-> modifier :geometry count)) + (= :move (-> modifier :geometry first :type)))) + +(defn get-frame-add-children + [modif-tree] + + (let [structure-changes + (into {} + (comp (filter (fn [[_ val]] (-> val :modifiers :structure-parent some?))) + (map (fn [[key val]] + [key (-> val :modifiers :structure-parent)]))) + modif-tree)] + (into [] + (mapcat (fn [[frame-id changes]] + (->> changes + (filter (fn [{:keys [type]}] (= type :add-children))) + (mapcat (fn [{:keys [value]}] + (->> value (map (fn [id] {:frame frame-id :shape id})))))))) + structure-changes))) + +(defn modifiers->transform [modifiers] (letfn [(apply-modifier [matrix {:keys [type vector rotation center origin transform transform-inverse] :as modifier}] (case type @@ -182,77 +282,58 @@ (gmt/multiply (gmt/rotate-matrix rotation)) (gmt/translate (gpt/negate center))) matrix)))] - (->> modifiers + (->> modifiers :geometry (reduce apply-modifier (gmt/matrix))))) -(defn- normalize-scale - "We normalize the scale so it's not too close to 0" - [scale] - (cond - (and (< scale 0) (> scale -0.01)) -0.01 - (and (>= scale 0) (< scale 0.01)) 0.01 - :else scale)) +(defn scale-text-content + [content value] -(defn modifiers->transform - ([modifiers] - (modifiers->transform nil modifiers)) + (->> content + (txt/transform-nodes + txt/is-text-node? + (fn [attrs] + (let [font-size (-> (get attrs :font-size 14) + (d/parse-double) + (* value) + (str)) ] + (d/txt-merge attrs {:font-size font-size})))))) - ([center modifiers] - (if (some? (:v2 modifiers)) - (modifiers-v2->transform (:v2 modifiers)) - (let [displacement (:displacement modifiers) - displacement-after (:displacement-after modifiers) - resize-v1 (:resize-vector modifiers) - resize-v2 (:resize-vector-2 modifiers) - origin-1 (:resize-origin modifiers (gpt/point)) - origin-2 (:resize-origin-2 modifiers (gpt/point)) +(defn apply-scale-content + [shape value] - ;; Normalize x/y vector coordinates because scale by 0 is infinite - resize-1 (when (some? resize-v1) - (gpt/point (normalize-scale (:x resize-v1)) - (normalize-scale (:y resize-v1)))) + (cond-> shape + (cph/text-shape? shape) + (update :content scale-text-content value))) - resize-2 (when (some? resize-v2) - (gpt/point (normalize-scale (:x resize-v2)) - (normalize-scale (:y resize-v2)))) +(defn apply-structure-modifiers + [shape modifiers] + (let [remove-children + (fn [shapes children-to-remove] + (let [remove? (set children-to-remove)] + (d/removev remove? shapes))) - resize-transform (:resize-transform modifiers) - resize-transform-inverse (:resize-transform-inverse modifiers) - rt-modif (:rotation modifiers)] - (cond-> (gmt/matrix) - (some? displacement-after) - (gmt/multiply displacement-after) + apply-modifier + (fn [shape {:keys [type value index]}] + (cond-> shape + (and (= type :add-children) (some? index)) + (update :shapes + (fn [shapes] + (if (vector? shapes) + (cph/insert-at-index shapes index value) + (d/concat-vec shapes value)))) - (some? resize-1) - (-> (gmt/translate origin-1) - (cond-> (some? resize-transform) - (gmt/multiply resize-transform)) - (gmt/scale resize-1) - (cond-> (some? resize-transform-inverse) - (gmt/multiply resize-transform-inverse)) - (gmt/translate (gpt/negate origin-1))) + (and (= type :add-children) (nil? index)) + (update :shapes d/concat-vec value) - (some? resize-2) - (-> (gmt/translate origin-2) - (cond-> (some? resize-transform) - (gmt/multiply resize-transform)) - (gmt/scale resize-2) - (cond-> (some? resize-transform-inverse) - (gmt/multiply resize-transform-inverse)) - (gmt/translate (gpt/negate origin-2))) + (= type :remove-children) + (update :shapes remove-children value) - (some? displacement) - (gmt/multiply displacement) + (= type :scale-content) + (apply-scale-content value)))] - (some? rt-modif) - (-> (gmt/translate center) - (gmt/multiply (gmt/rotate-matrix rt-modif)) - (gmt/translate (gpt/negate center)))))) - )) -(defn only-move? - [modifier] - (and (= 1 (-> modifier :v2 count)) - (= :move (-> modifier :v2 first :type)))) + (as-> shape $ + (reduce apply-modifier $ (:structure-parent modifiers)) + (reduce apply-modifier $ (:structure-child modifiers))))) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 65843fc6b..ad91a1226 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -47,8 +47,9 @@ (-> shape (assoc :click-draw? false) - (gsh/transform-shape (ctm/resize scalev (gpt/point x y))) - (gsh/transform-shape (ctm/move movev))))) + (gsh/transform-shape (-> (ctm/empty-modifiers) + (ctm/set-resize scalev (gpt/point x y)) + (ctm/set-move movev)))))) (defn update-drawing [state initial point lock?] (update-in state [:workspace-drawing :object] resize-shape initial point lock?)) diff --git a/frontend/src/app/main/data/workspace/shapes.cljs b/frontend/src/app/main/data/workspace/shapes.cljs index daa033365..2f15ac226 100644 --- a/frontend/src/app/main/data/workspace/shapes.cljs +++ b/frontend/src/app/main/data/workspace/shapes.cljs @@ -22,7 +22,6 @@ [app.main.data.workspace.edition :as dwe] [app.main.data.workspace.selection :as dws] [app.main.data.workspace.shape-layout :as dwsl] - [app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.state-helpers :as wsh] [app.main.features :as features] [app.main.streams :as ms] diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 1c9f5f147..dbfb5f453 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -320,8 +320,8 @@ (letfn [(update-fn [shape] (let [{:keys [selrect grow-type]} shape {shape-width :width shape-height :height} selrect - modifier-width (ctm/resize-modifiers shape :width new-width) - modifier-height (ctm/resize-modifiers shape :height new-height)] + modifier-width (ctm/change-dimensions shape :width new-width) + modifier-height (ctm/change-dimensions shape :height new-height)] ;; TODO LAYOUT: MEZCLAR ESTOS EN UN UNICO MODIFIER (cond-> shape (and (not-changed? shape-width new-width) (= grow-type :auto-width)) @@ -346,8 +346,8 @@ (defn apply-text-modifier [shape {:keys [width height position-data]}] - (let [modifier-width (when width (ctm/resize-modifiers shape :width width)) - modifier-height (when height (ctm/resize-modifiers shape :height height)) + (let [modifier-width (when width (ctm/change-dimensions shape :width width)) + modifier-height (when height (ctm/change-dimensions shape :height height)) ;; TODO LAYOUT: MEZCLAR LOS DOS EN UN UNICO MODIFIER new-shape diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 7873b7eba..f304dbe31 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -146,11 +146,14 @@ (concat (keys workspace-modifiers) ids) objects (fn [shape] - (let [modifiers (if (contains? ids (:id shape)) modifiers {}) - old-modifiers-v3 (get-in state [:workspace-modifiers (:id shape) :modifiers :v3])] + (let [ + modifiers (if (contains? ids (:id shape)) modifiers (ctm/empty-modifiers)) + + structure-modifiers (ctm/select-structure + (get-in state [:workspace-modifiers (:id shape) :modifiers]))] (cond-> modifiers - (some? old-modifiers-v3) - (assoc :v3 old-modifiers-v3)))) + (some? structure-modifiers) + (ctm/add-modifiers structure-modifiers)))) ignore-constraints snap-pixel?)] (update state :workspace-modifiers merge modif-tree)))))) @@ -175,7 +178,7 @@ get-modifier (fn [shape] - (ctm/rotation-modifiers shape center angle)) + (ctm/rotation shape center angle)) modif-tree (gsh/set-objects-modifiers ids objects get-modifier false false)] @@ -396,32 +399,18 @@ resize-origin (cond-> (gmt/transform-point-center handler-origin shape-center shape-transform) (some? displacement) - (gpt/add displacement))] + (gpt/add displacement)) - (rx/of (set-modifiers ids - {:v2 (-> [] - (cond-> displacement - (conj {:type :move - :vector displacement})) - (conj {:type :resize - :vector scalev - :origin resize-origin - :transform shape-transform - :transform-inverse shape-transform-inverse})) - ;;:displacement displacement - ;;:resize-vector scalev - ;;:resize-origin resize-origin - ;;:resize-transform shape-transform - ;;:resize-scale-text scale-text - ;;:resize-transform-inverse shape-transform-inverse - })) - #_(rx/of (set-modifiers ids - {:displacement displacement - :resize-vector scalev - :resize-origin resize-origin - :resize-transform shape-transform - :resize-scale-text scale-text - :resize-transform-inverse shape-transform-inverse})))) + modifiers + (-> (ctm/empty-modifiers) + (cond-> displacement + (ctm/set-move displacement)) + (ctm/set-resize scalev resize-origin shape-transform shape-transform-inverse) + + (cond-> scale-text + (ctm/set-scale-content (:x scalev))))] + + (rx/of (set-modifiers ids modifiers)))) ;; Unifies the instantaneous proportion lock modifier ;; activated by Shift key and the shapes own proportion @@ -471,7 +460,7 @@ snap-pixel? (and (contains? (:workspace-layout state) :snap-pixel-grid) (int? value)) get-modifier - (fn [shape] (ctm/resize-modifiers shape attr value)) + (fn [shape] (ctm/change-dimensions shape attr value)) modif-tree (gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)] @@ -655,15 +644,13 @@ (d/removev #(= target-frame %)))] (cond (not= original-frame target-frame) - [[original-frame {:modifiers {:v3 [{:type :remove-children :value shapes}]}}] - [target-frame {:modifiers {:v3 [{:type :add-children - :value shapes - :index drop-index}]}}]] + [[original-frame {:modifiers (ctm/remove-children shapes)}] + [target-frame {:modifiers (ctm/add-children shapes drop-index)}]] + layout? - [[target-frame {:modifiers {:v3 [{:type :add-children - :value shapes - :index drop-index}]}}]])))) + [[target-frame {:modifiers (ctm/add-children shapes drop-index)}]])))) (keys origin-frame-ids))] + (assoc state :workspace-modifiers modif-tree))))) (defn- start-move @@ -725,8 +712,7 @@ ;; We try to use the previous snap so we don't have to wait for the result of the new (rx/map snap/correct-snap-point) - - (rx/map (fn [move-vec] {:v2 [{:type :move :vector move-vec}]})) + (rx/map ctm/move) (rx/map (partial set-modifiers ids)) (rx/take-until stopper))) @@ -867,14 +853,9 @@ origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))] (rx/of (set-modifiers selected - {:v2 [{:type :resize - :vector (gpt/point -1.0 1.0) - :origin origin} - {:type :move - :vector (gpt/point (:width selrect) 0)}]} - #_{:resize-vector (gpt/point -1.0 1.0) - :resize-origin origin - :displacement (gmt/translate-matrix (gpt/point (- (:width selrect)) 0))} + (-> (ctm/empty-modifiers) + (ctm/set-resize (gpt/point -1.0 1.0) origin) + (ctm/move (gpt/point (:width selrect) 0))) true) (apply-modifiers)))))) @@ -889,13 +870,8 @@ origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))] (rx/of (set-modifiers selected - {:v2 [{:type :resize - :vector (gpt/point 1.0 -1.0) - :origin origin} - {:type :move - :vector (gpt/point 0 (:height selrect))}]} - #_{:resize-vector (gpt/point 1.0 -1.0) - :resize-origin origin - :displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))} + (-> (ctm/empty-modifiers) + (ctm/set-resize (gpt/point 1.0 -1.0) origin) + (ctm/move (gpt/point 0 (:height selrect)))) true) (apply-modifiers)))))) diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 836114c51..a6ca1742b 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -103,7 +103,7 @@ opts #js {:shape shape :thumbnail? thumbnail?}] (when (and (some? shape) (not (:hidden shape))) - [:g.ws-shape-wrapper + [:g.workspace-shape-wrapper (case (:type shape) :path [:> path/path-wrapper opts] :text [:> text/text-wrapper opts] 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 6d95966d4..288ebcbff 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 @@ -19,67 +19,6 @@ [app.util.globals :as globals] [rumext.v2 :as mf])) -(defn- transform-no-resize - "If we apply a scale directly to the texts it will show deformed so we need to create this - correction matrix to \"undo\" the resize but keep the other transformations." - [{:keys [x y width height points transform transform-inverse] :as shape} current-transform modifiers] - - (let [corner-pt (first points) - corner-pt (cond-> corner-pt (some? transform-inverse) (gpt/transform transform-inverse)) - - resize-x? (some? (:resize-vector modifiers)) - resize-y? (some? (:resize-vector-2 modifiers)) - - flip-x? (neg? (get-in modifiers [:resize-vector :x])) - flip-y? (or (neg? (get-in modifiers [:resize-vector :y])) - (neg? (get-in modifiers [:resize-vector-2 :y]))) - - result (cond-> (gmt/matrix) - (and (some? transform) (or resize-x? resize-y?)) - (gmt/multiply transform) - - resize-x? - (gmt/scale (gpt/inverse (:resize-vector modifiers)) corner-pt) - - resize-y? - (gmt/scale (gpt/inverse (:resize-vector-2 modifiers)) corner-pt) - - flip-x? - (gmt/scale (gpt/point -1 1) corner-pt) - - flip-y? - (gmt/scale (gpt/point 1 -1) corner-pt) - - (and (some? transform) (or resize-x? resize-y?)) - (gmt/multiply transform-inverse)) - - [width height] - (if (or resize-x? resize-y?) - (let [pc (cond-> (gpt/point x y) - (some? transform) - (gpt/transform transform) - - (some? current-transform) - (gpt/transform current-transform)) - - pw (cond-> (gpt/point (+ x width) y) - (some? transform) - (gpt/transform transform) - - (some? current-transform) - (gpt/transform current-transform)) - - ph (cond-> (gpt/point x (+ y height)) - (some? transform) - (gpt/transform transform) - - (some? current-transform) - (gpt/transform current-transform))] - [(gpt/distance pc pw) (gpt/distance pc ph)]) - [width height])] - - [result width height])) - (defn get-shape-node ([id] (get-shape-node js/document id)) @@ -191,15 +130,8 @@ (let [transform (get transforms id) modifiers (get-in modifiers [id :modifiers])] - ;; TODO LAYOUT: Adapt to new modifiers (doseq [node nodes] (cond - ;; Text shapes need special treatment because their resize only change - ;; the text area, not the change size/position - (dom/class? node "frame-thumbnail") - (let [[transform] (transform-no-resize shape transform modifiers)] - (set-transform-att! node "transform" transform)) - (dom/class? node "frame-children") (set-transform-att! node "transform" (gmt/inverse transform)) @@ -256,11 +188,7 @@ (/ (:height shape) (:height shape')))] ;; Reverse the change in size so we can recalculate the layout (-> modifiers - (update :v2 conj {:type :resize - :vector scalev - :transform (:transform shape') - :transform-inverse (:transform-inverse shape') - :origin (-> shape' :points first)})))) + (ctm/set-resize scalev (-> shape' :points first) (:transform shape') (:transform-inverse shape'))))) (defn use-dynamic-modifiers [objects node modifiers] @@ -272,37 +200,13 @@ (when (some? modifiers) (d/mapm (fn [id {modifiers :modifiers}] (let [shape (get objects id) - center (gsh/center-shape shape) text? (= :text (:type shape)) modifiers (cond-> modifiers text? (adapt-text-modifiers shape))] - (ctm/modifiers->transform center modifiers))) + (ctm/modifiers->transform modifiers))) modifiers)))) - structure-changes - (mf/use-memo - (mf/deps modifiers) - (fn [] - (into {} - (comp (filter (fn [[_ val]] (-> val :modifiers :v3 some?))) - (map (fn [[key val]] - [key (-> val :modifiers :v3)]))) - - modifiers))) - - structure-changes (hooks/use-equal-memo structure-changes) - - add-children - (mf/use-memo - (mf/deps structure-changes) - (fn [] - (into [] - (mapcat (fn [[frame-id changes]] - (->> changes - (filter (fn [{:keys [type]}] (= type :add-children))) - (mapcat (fn [{:keys [value]}] - (->> value (map (fn [id] {:frame frame-id :shape id})))))))) - structure-changes))) - + add-children (mf/use-memo (mf/deps modifiers) #(ctm/get-frame-add-children modifiers)) + add-children (hooks/use-equal-memo add-children) add-children-prev (hooks/use-previous add-children) shapes diff --git a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs index 74e8057e0..50e2e6ebc 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/viewport_texts_html.cljs @@ -35,13 +35,6 @@ (with-meta (meta (:position-data shape)))) (dissoc :position-data :transform :transform-inverse))) -#_(defn strip-modifier - [modifier] - (if (or (some? (dm/get-in modifier [:modifiers :resize-vector])) - (some? (dm/get-in modifier [:modifiers :resize-vector-2]))) - modifier - (d/update-when modifier :modifiers dissoc :displacement :rotation))) - (defn fix-position [shape modifier] (let [shape' (-> shape (assoc :grow-type :fixed) diff --git a/frontend/src/app/main/ui/workspace/viewport/debug.cljs b/frontend/src/app/main/ui/workspace/viewport/debug.cljs index 0f23f9eee..ef81d5fa9 100644 --- a/frontend/src/app/main/ui/workspace/viewport/debug.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/debug.cljs @@ -31,7 +31,7 @@ (when (and shape (:layout shape)) (let [children (cph/get-immediate-children objects (:id shape)) layout-data (gsl/calc-layout-data shape children) - drop-areas (gsl/drop-areas shape layout-data children)] + drop-areas (gsl/layout-drop-areas shape layout-data children)] [:g.debug-layout {:pointer-events "none" :transform (gsh/transform-str shape)} (for [[idx drop-area] (d/enumerate drop-areas)]