0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-04 11:01:20 -05:00

Refactor for new modifiers

This commit is contained in:
alonso.torres 2022-10-19 13:27:44 +02:00
parent c3ed46d3ab
commit 11f347941e
15 changed files with 445 additions and 824 deletions

View file

@ -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))))))

View file

@ -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)))

View file

@ -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)]

View file

@ -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)))

View file

@ -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))]))

View file

@ -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]

View file

@ -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)))))

View file

@ -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?))

View file

@ -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]

View file

@ -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

View file

@ -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))))))

View file

@ -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]

View file

@ -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

View file

@ -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)

View file

@ -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)]