0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-19 19:21:23 -05:00

Adds autolayout positions calculations

This commit is contained in:
alonso.torres 2022-09-29 13:37:54 +02:00
parent 5050c35257
commit c01c46041d
37 changed files with 938 additions and 594 deletions

View file

@ -252,3 +252,14 @@
(update :d mth/precision 4)
(update :e mth/precision 4)
(update :f mth/precision 4)))
(defn transform-point-center
"Transform a point around the shape center"
[point center matrix]
(if (and (some? point) (some? matrix) (some? center))
(gpt/transform
point
(multiply (translate-matrix center)
matrix
(translate-matrix (gpt/negate center))))
point))

View file

@ -28,7 +28,7 @@
rotation of each shape. Mainly used for multiple selection."
[shapes]
(->> shapes
(map (comp gpr/points->selrect :points gtr/transform-shape))
(map (comp gpr/points->selrect :points))
(gpr/join-selrects)))
(defn translate-to-frame
@ -166,23 +166,17 @@
(dm/export gtr/transform-matrix)
(dm/export gtr/transform-str)
(dm/export gtr/inverse-transform-matrix)
(dm/export gtr/transform-point-center)
(dm/export gtr/transform-rect)
(dm/export gtr/calculate-adjust-matrix)
(dm/export gtr/update-group-selrect)
(dm/export gtr/update-mask-selrect)
(dm/export gtr/resize-modifiers)
(dm/export gtr/change-orientation-modifiers)
(dm/export gtr/rotation-modifiers)
(dm/export gtr/merge-modifiers)
(dm/export gtr/transform-shape)
(dm/export gtr/transform-selrect)
(dm/export gtr/transform-selrect-matrix)
(dm/export gtr/transform-bounds)
(dm/export gtr/modifiers->transform)
(dm/export gtr/empty-modifiers?)
(dm/export gtr/move-position-data)
(dm/export gtr/apply-transform)
(dm/export gtr/apply-objects-modifiers)
;; Constratins
(dm/export gct/calc-child-modifiers)

View file

@ -6,14 +6,19 @@
(ns app.common.geom.shapes.constraints
(:require
[app.common.geom.matrix :as gmt]
[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.uuid :as uuid]))
;; Auxiliary methods to work in an specifica axis
(defn other-axis [axis]
(if (= :x axis) :y :x))
(defn get-delta-start [axis rect tr-rect]
(if (= :x axis)
(- (:x1 tr-rect) (:x1 rect))
@ -29,6 +34,11 @@
(- (:width tr-rect) (:width rect))
(- (:height tr-rect) (:height rect))))
(defn get-delta-scale [axis rect tr-rect]
(if (= :x axis)
(/ (:width tr-rect) (:width rect))
(/ (:height tr-rect) (:height rect))))
(defn get-delta-center [axis center tr-center]
(if (= :x axis)
(- (:x tr-center) (:x center))
@ -53,78 +63,138 @@
(:width rect)
(:height rect)))
(defn right-vector
[child-points parent-points]
(let [[p0 p1 p2 _] parent-points
[_c0 c1 _ _] child-points
dir-v (gpt/to-vec p0 p1)
cp (gsi/line-line-intersect c1 (gpt/add c1 dir-v) p1 p2)]
(gpt/to-vec c1 cp)))
(defn left-vector
[child-points parent-points]
(let [[p0 p1 _ p3] parent-points
[_ _ _ c3] child-points
dir-v (gpt/to-vec p0 p1)
cp (gsi/line-line-intersect c3 (gpt/add c3 dir-v) p0 p3)]
(gpt/to-vec c3 cp)))
(defn top-vector
[child-points parent-points]
(let [[p0 p1 _ p3] parent-points
[c0 _ _ _] child-points
dir-v (gpt/to-vec p0 p3)
cp (gsi/line-line-intersect c0 (gpt/add c0 dir-v) p0 p1)]
(gpt/to-vec c0 cp)))
(defn bottom-vector
[child-points parent-points]
(let [[p0 _ p2 p3] parent-points
[_ _ c2 _] child-points
dir-v (gpt/to-vec p0 p3)
cp (gsi/line-line-intersect c2 (gpt/add c2 dir-v) p2 p3)]
(gpt/to-vec c2 cp)))
(defn center-horizontal-vector
[child-points parent-points]
(let [[p0 p1 _ p3] parent-points
[_ c1 _ _] child-points
dir-v (gpt/to-vec p0 p1)
p1c (gpt/add p0 (gpt/scale dir-v 0.5))
p2c (gpt/add p3 (gpt/scale dir-v 0.5))
cp (gsi/line-line-intersect c1 (gpt/add c1 dir-v) p1c p2c)]
(gpt/to-vec c1 cp)))
(defn center-vertical-vector
[child-points parent-points]
(let [[p0 p1 p2 _] parent-points
[_ c1 _ _] child-points
dir-v (gpt/to-vec p1 p2)
p3c (gpt/add p0 (gpt/scale dir-v 0.5))
p2c (gpt/add p1 (gpt/scale dir-v 0.5))
cp (gsi/line-line-intersect c1 (gpt/add c1 dir-v) p3c p2c)]
(gpt/to-vec c1 cp)))
(defn start-vector
[axis child-points parent-points]
((if (= :x axis) left-vector top-vector) child-points parent-points))
(defn end-vector
[axis child-points parent-points]
((if (= :x axis) right-vector bottom-vector) child-points parent-points))
(defn center-vector
[axis child-points parent-points]
((if (= :x axis) center-horizontal-vector center-vertical-vector) child-points parent-points))
;; Constraint function definitions
(defmulti constraint-modifier (fn [type & _] type))
(defmethod constraint-modifier :start
[_ axis parent _ _ transformed-parent-rect]
(let [parent-rect (:selrect parent)
delta-start (get-delta-start axis parent-rect transformed-parent-rect)]
(if-not (mth/almost-zero? delta-start)
{:displacement (get-displacement axis delta-start)}
{})))
(defmethod constraint-modifier :end
[_ axis parent _ _ transformed-parent-rect]
(let [parent-rect (:selrect parent)
delta-end (get-delta-end axis parent-rect transformed-parent-rect)]
(if-not (mth/almost-zero? delta-end)
{:displacement (get-displacement axis delta-end)}
{})))
[_ axis child-points-before parent-points-before child-points-after parent-points-after]
(let [end-before (end-vector axis child-points-before parent-points-before)
end-after (end-vector axis child-points-after parent-points-after)
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}]))
(defmethod constraint-modifier :fixed
[_ axis parent child _ transformed-parent-rect]
(let [parent-rect (:selrect parent)
child-rect (gre/points->rect (:points child))
[_ axis child-points-before parent-points-before child-points-after parent-points-after transformed-parent]
(let [[c0 c1 _ c4] child-points-after
delta-start (get-delta-start axis parent-rect transformed-parent-rect)
delta-size (get-delta-size axis parent-rect transformed-parent-rect)
child-size (get-size axis child-rect)]
(if (or (not (mth/almost-zero? delta-start))
(not (mth/almost-zero? delta-size)))
;; Same as constraint end
end-before (end-vector axis child-points-before parent-points-before)
end-after (end-vector axis child-points-after parent-points-after)
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))
{:displacement (get-displacement axis delta-start)
:resize-origin (get-displacement axis delta-start (:x child-rect) (:y child-rect))
:resize-vector (get-scale axis (/ (+ child-size delta-size) child-size))}
{})))
before-vec (if (= axis :x) (gpt/to-vec c0 c1) (gpt/to-vec c0 c4))
after-vec (if (= axis :x)
(gpt/to-vec c0 (gpt/add c1 disp-vector-end))
(gpt/to-vec c0 (gpt/add c4 disp-vector-end))
)
resize-angl (gpt/angle-with-other before-vec after-vec)
resize-sign (if (mth/close? resize-angl 180) -1 1)
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)}]))
(defmethod constraint-modifier :center
[_ axis parent _ _ transformed-parent-rect]
(let [parent-rect (:selrect parent)
parent-center (gco/center-rect parent-rect)
transformed-parent-center (gco/center-rect transformed-parent-rect)
delta-center (get-delta-center axis parent-center transformed-parent-center)]
(if-not (mth/almost-zero? delta-center)
{:displacement (get-displacement axis delta-center)}
{})))
(defmethod constraint-modifier :scale
[_ axis _ _ modifiers _]
(let [{:keys [resize-vector resize-vector-2 displacement]} modifiers]
(cond-> {}
(and (some? resize-vector)
(not= (axis resize-vector) 1))
(assoc :resize-origin (:resize-origin modifiers)
:resize-vector (if (= :x axis)
(gpt/point (:x resize-vector) 1)
(gpt/point 1 (:y resize-vector))))
(and (= :y axis) (some? resize-vector-2)
(not (mth/close? (:y resize-vector-2) 1)))
(assoc :resize-origin (:resize-origin-2 modifiers)
:resize-vector (gpt/point 1 (:y resize-vector-2)))
(some? displacement)
(assoc :displacement
(get-displacement axis (-> (gpt/point 0 0)
(gpt/transform displacement)
(gpt/transform (:resize-transform-inverse modifiers (gmt/matrix)))
axis))))))
[_ axis child-points-before parent-points-before child-points-after parent-points-after]
(let [center-before (center-vector axis child-points-before parent-points-before)
center-after (center-vector axis child-points-after parent-points-after)
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}]))
(defmethod constraint-modifier :default [_ _ _ _ _]
{})
[])
(def const->type+axis
{:left :start
@ -152,7 +222,7 @@
:top
:scale)))
(defn clean-modifiers
#_(defn clean-modifiers
"Remove redundant modifiers"
[{:keys [displacement resize-vector resize-vector-2] :as modifiers}]
@ -174,55 +244,91 @@
(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.
Returns a points array"
[child parent]
(-> child
:points
(gco/transform-points (:transform-inverse parent))
(gre/points->rect)
(gre/rect->points) ;; Restore to points so we can transform them
(gco/transform-points (:transform parent))))
(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]
(let [child-bb-before
(-> child
:points
(gco/transform-points (:transform-inverse parent))
(gre/points->rect))
child-bb-after
(-> transformed-child
:points
(gco/transform-points (:transform-inverse transformed-parent))
(gre/points->rect))
scale-x (/ (:width child-bb-before) (:width 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)})
(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)}))))))
(defn calc-child-modifiers
[parent child modifiers ignore-constraints transformed-parent-rect]
[parent child modifiers ignore-constraints transformed-parent]
(if (and (nil? (:resize-vector modifiers))
(nil? (:resize-vector-2 modifiers)))
;; If we don't have a resize modifier we return the same modifiers
modifiers
(let [constraints-h
(if-not ignore-constraints
(:constraints-h child (default-constraints-h child))
:scale)
(let [constraints-h
(if-not ignore-constraints
(:constraints-h child (default-constraints-h child))
:scale)
constraints-v
(if-not ignore-constraints
(:constraints-v child (default-constraints-v child))
:scale)
constraints-v
(if-not ignore-constraints
(:constraints-v child (default-constraints-v child))
:scale)]
modifiers-h (constraint-modifier (constraints-h const->type+axis) :x parent child modifiers transformed-parent-rect)
modifiers-v (constraint-modifier (constraints-v const->type+axis) :y parent child modifiers transformed-parent-rect)]
(if (and (= :scale constraints-h) (= :scale constraints-v))
modifiers
;; Build final child modifiers. Apply transform again to the result, to get the
;; real modifiers that need to be applied to the child, including rotation as needed.
(cond-> {}
(some? (:displacement-after modifiers))
(assoc :displacement-after (:displacement-after modifiers))
(let [transformed-child (gst/transform-shape child modifiers)
modifiers (normalize-modifiers constraints-h constraints-v modifiers child parent transformed-child transformed-parent)
(or (contains? modifiers-h :displacement)
(contains? modifiers-v :displacement))
(assoc :displacement (cond-> (gpt/point (get-in modifiers-h [:displacement :x] 0)
(get-in modifiers-v [:displacement :y] 0))
(some? (:resize-transform modifiers))
(gpt/transform (:resize-transform modifiers))
tranformed-child-2 (gst/transform-shape child modifiers)
parent-points-before (:points parent)
child-points-before (bounding-box-parent-transform child parent)
:always
(gmt/translate-matrix)))
parent-points-after (:points transformed-parent)
child-points-after (bounding-box-parent-transform tranformed-child-2 transformed-parent)
(:resize-vector modifiers-h)
(assoc :resize-origin (:resize-origin modifiers-h)
:resize-vector (gpt/point (get-in modifiers-h [:resize-vector :x] 1)
(get-in modifiers-h [:resize-vector :y] 1)))
modifiers-h (constraint-modifier (constraints-h const->type+axis) :x
child-points-before parent-points-before
child-points-after parent-points-after
transformed-parent)
(:resize-vector modifiers-v)
(assoc :resize-origin-2 (:resize-origin modifiers-v)
:resize-vector-2 (gpt/point (get-in modifiers-v [:resize-vector :x] 1)
(get-in modifiers-v [:resize-vector :y] 1)))
modifiers-v (constraint-modifier (constraints-v const->type+axis) :y
child-points-before parent-points-before
child-points-after parent-points-after
transformed-parent)]
(:resize-transform modifiers)
(assoc :resize-transform (:resize-transform modifiers)
:resize-transform-inverse (:resize-transform-inverse modifiers))
:always
(clean-modifiers)))))
(update modifiers :v2 d/concat-vec modifiers-h modifiers-v)))))

View file

@ -348,3 +348,25 @@
:points
(every? (partial has-point-rect? rect))))
(defn line-line-intersect
"Calculates the interesection point for two lines given by the points a-b and b-c"
[a b c d]
(let [;; Line equation representation: ax + by + c = 0
a1 (- (:y b) (:y a))
b1 (- (:x a) (:x b))
c1 (+ (* a1 (:x a)) (* b1 (:y a)))
a2 (- (:y d) (:y c))
b2 (- (:x c) (:x d))
c2 (+ (* a2 (:x c)) (* b2 (:y c)))
;; Cramer's rule
det (- (* a1 b2) (* a2 b1))]
;; If almost zero the lines are parallel
(when (not (mth/almost-zero? det))
(let [x (/ (- (* b2 c1) (* b1 c2)) det)
y (/ (- (* c2 a1) (* c1 a2)) det)]
(gpt/point x y)))))

View file

@ -6,7 +6,6 @@
(ns app.common.geom.shapes.layout
(:require
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.geom.shapes.rect :as gre]))
@ -71,24 +70,39 @@
(let [wrap? (= layout-wrap-type :wrap)
reduce-fn
(fn [[{:keys [line-width line-height num-children] :as line-data} result] child]
(fn [[{:keys [line-width line-height num-children child-fill? num-child-fill] :as line-data} result] child]
(let [child-bounds (-> child :points gre/points->rect)
next-width (-> child-bounds :width)
next-height (-> child-bounds :height)]
cur-child-fill?
(or (and (col? shape) (= :fill (:layout-h-behavior child)))
(and (row? shape) (= :fill (:layout-v-behavior child))))
next-width (if cur-child-fill?
0
(-> child-bounds :width))
next-height (if cur-child-fill?
0
(-> child-bounds :height))]
(if (and (some? line-data)
(or (not wrap?)
(and (col? shape) (<= (+ line-width next-width (* layout-gap num-children)) width))
(and (row? shape) (<= (+ line-height next-height (* layout-gap num-children)) height))))
[{:line-width (if (col? shape) (+ line-width next-width) (max line-width next-width))
:line-height (if (row? shape) (+ line-height next-height) (max line-height next-height))
:num-children (inc num-children)}
;; Si autofill añadimos el minwidth que por defecto es 0
[{:line-width (if (col? shape) (+ line-width next-width) (max line-width next-width))
:line-height (if (row? shape) (+ line-height next-height) (max line-height next-height))
:num-children (inc num-children)
:child-fill? (or cur-child-fill? child-fill?)
:num-child-fill (cond-> num-child-fill cur-child-fill? inc)}
result]
[{:line-width next-width
:line-height next-height
:num-children 1}
[{:line-width next-width
:line-height next-height
:num-children 1
:child-fill? child-fill?
:num-child-fill (if child-fill? 1 0)}
(cond-> result (some? line-data) (conj line-data))])))
[line-data layout-lines] (reduce reduce-fn [nil []] children)]
@ -124,13 +138,14 @@
[base-x base-y]))
(get-start-line
[{:keys [line-width line-height num-children]} base-x base-y]
[{:keys [line-width line-height num-children child-fill?]} base-x base-y]
(let [children-gap (* layout-gap (dec num-children))
start-x
(cond
(or (and (col? shape) (= :space-between layout-type))
(or (and (col? shape) child-fill?)
(and (col? shape) (= :space-between layout-type))
(and (col? shape) (= :space-around layout-type)))
x
@ -154,7 +169,8 @@
start-y
(cond
(or (and (row? shape) (= :space-between layout-type))
(or (and (row? shape) child-fill?)
(and (row? shape) (= :space-between layout-type))
(and (row? shape) (= :space-around layout-type)))
y
@ -240,6 +256,7 @@
0)]
(assoc line-data
:layout-bounds layout-bounds
:layout-gap layout-gap
:margin-x margin-x
:margin-y margin-y)))
@ -314,14 +331,39 @@
"Calculates the modifiers for the layout"
[parent transform child layout-data]
(let [bounds (-> child :points gre/points->selrect)
(let [child-bounds (-> child :points gre/points->selrect)
[corner-p layout-data] (next-p parent bounds layout-data)
fill-space (- (-> layout-data :layout-bounds :width) (:line-width layout-data))
fill-width (- (/ fill-space (:num-child-fill layout-data))
(* 2 (:layout-gap layout-data)))
fill-scale (/ fill-width (:width child-bounds))
child-bounds
(cond-> child-bounds
(and (col? parent) (= :fill (:layout-h-behavior child)))
(assoc :width fill-width))
[corner-p layout-data] (next-p parent child-bounds layout-data)
delta-p (-> corner-p
(gpt/subtract (gpt/point bounds))
(gpt/subtract (gpt/point child-bounds))
(cond-> (some? transform) (gpt/transform transform)))
modifiers {:displacement-after (gmt/translate-matrix delta-p)}]
modifiers []
modifiers
(cond-> modifiers
(and (col? parent) (= :fill (:layout-h-behavior child)))
(conj {:type :resize
:from :layout
:origin (gpt/point child-bounds)
:vector (gpt/point fill-scale 1)}))
modifiers
(conj modifiers {:type :move
:from :layout
:vector delta-p})]
[modifiers layout-data]))

View file

@ -15,8 +15,10 @@
[app.common.geom.shapes.rect :as gpr]
[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]
@ -106,44 +108,65 @@
(defn set-children-modifiers
[modif-tree shape objects ignore-constraints snap-pixel?]
(letfn [(set-child [transformed-rect snap-pixel? modif-tree child]
[modif-tree objects shape 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 shape) :modifiers])
child-modifiers (gct/calc-child-modifiers shape child modifiers ignore-constraints transformed-rect)
child-modifiers (cond-> child-modifiers snap-pixel? (set-pixel-precision child))]
(cond-> modif-tree
(not (gtr/empty-modifiers? child-modifiers))
(update-in [(:id child) :modifiers] #(merge child-modifiers %)))))]
child-modifiers (gct/calc-child-modifiers shape child modifiers ignore-constraints transformed-parent)
;;_ (.log js/console (:name child) (clj->js child-modifiers))
;;child-modifiers (cond-> child-modifiers snap-pixel? (set-pixel-precision child))
result
(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] #(merge-mod2 child-modifiers %))
#_(update-in [(:id child) :modifiers] #(merge child-modifiers %)))
;;_ (.log js/console ">>>" (:name child))
;;_ (.log js/console " >" (clj->js child-modifiers))
;;_ (.log js/console " >" (clj->js (get-in modif-tree [(:id child) :modifiers])))
;;_ (.log js/console " >" (clj->js (get-in result [(:id child) :modifiers])))
]
result
))
]
(let [children (map (d/getf objects) (:shapes shape))
modifiers (get-in modif-tree [(:id shape) :modifiers])
transformed-rect (gtr/transform-selrect (:selrect shape) modifiers)
;; transformed-rect (gtr/transform-selrect (:selrect shape) modifiers)
;; transformed-rect (-> shape (merge {:modifiers modifiers}) gtr/transform-shape :selrect)
transformed-parent (-> shape (merge {:modifiers modifiers}) gtr/transform-shape)
resize-modif? (or (:resize-vector modifiers) (:resize-vector-2 modifiers))]
(reduce (partial set-child transformed-rect (and snap-pixel? resize-modif?)) modif-tree children))))
(reduce (partial set-child transformed-parent (and snap-pixel? resize-modif?)) modif-tree children))))
(defn group? [shape]
(or (= :group (:type shape))
(= :bool (:type shape))))
(defn merge-modifiers
[modif-tree ids modifiers]
(reduce
(fn [modif-tree id]
(update-in modif-tree [id :modifiers] #(merge % modifiers)))
modif-tree
ids))
(defn frame? [shape]
(= :frame (:type shape)))
(defn layout? [shape]
(and (frame? shape)
(:layout shape)))
(defn set-layout-modifiers
[modif-tree objects id]
;; TODO LAYOUT: SNAP PIXEL!
[modif-tree objects parent _snap-pixel?]
(letfn [(transform-child [parent child]
(letfn [(transform-child [child]
(let [modifiers (get modif-tree (:id child))
child
(cond-> child
(not (group? child))
(some? modifiers)
(-> (merge modifiers) gtr/transform-shape)
(group? child)
(and (nil? modifiers) (group? child))
(gtr/apply-group-modifiers objects modif-tree))
child
@ -158,22 +181,17 @@
modif-tree
(cond-> modif-tree
(not (gtr/empty-modifiers? modifiers))
(merge-modifiers [(:id child)] modifiers)
(and (not (gtr/empty-modifiers? modifiers)) (group? child))
(merge-modifiers (:shapes child) modifiers))]
(d/not-empty? modifiers)
(update-in [(:id child) :modifiers :v2] d/concat-vec modifiers)
#_(merge-modifiers [(:id child)] modifiers))]
[layout-data modif-tree]))]
(let [modifiers (get modif-tree id)
shape (-> (get objects id) (merge modifiers) gtr/transform-shape)
(let [modifiers (get modif-tree (:id parent))
shape (-> parent (merge modifiers) gtr/transform-shape)
children (->> (:shapes shape)
(map (d/getf objects))
(map (partial transform-child shape)))
(map transform-child))
center (gco/center-shape shape)
{:keys [transform transform-inverse]} shape
@ -230,6 +248,17 @@
:else
(recur (:id parent) result)))))
(defn resolve-tree-sequence
;; TODO LAYOUT: Esta ahora puesto al zero pero tiene que mirar todas las raices
"Given the ids that have changed search for layout roots to recalculate"
[_ids objects]
(->> (tree-seq
#(d/not-empty? (get-in objects [% :shapes]))
#(get-in objects [% :shapes])
uuid/zero)
(map #(get objects %))))
(defn resolve-layout-ids
"Given a list of ids, resolve the parent layouts that will need to update. This will go upwards
in the tree while a layout is found"
@ -239,6 +268,28 @@
(map #(get-first-layout % objects))
ids))
(defn inside-layout?
[objects shape]
(loop [current-id (:id shape)]
(let [current (get objects current-id)]
(cond
(or (nil? current) (= current-id (:parent-id current)))
false
(= :frame (:type current))
(:layout current)
:else
(recur (:parent-id current))))))
#_(defn modif->js
[modif-tree objects]
(clj->js (into {}
(map (fn [[k v]]
[(get-in objects [k :name]) v]))
modif-tree)))
(defn set-objects-modifiers
[ids objects get-modifier ignore-constraints snap-pixel?]
@ -251,40 +302,27 @@
modif-tree (reduce set-modifiers {} ids)
ids (resolve-layout-ids ids objects)
shapes-tree (resolve-tree-sequence ids objects)
;; First: Calculate children modifiers (constraints, etc)
[modif-tree touched-layouts]
(loop [current (first ids)
pending (rest ids)
modif-tree modif-tree
touched-layouts (d/ordered-set)]
(if (some? current)
(let [shape (get objects current)
pending (concat pending (:shapes shape))
touched-layouts
(cond-> touched-layouts
(:layout shape)
(conj (:id shape)))
modif-tree
(-> modif-tree
(set-children-modifiers shape objects ignore-constraints snap-pixel?))]
(recur (first pending) (rest pending) modif-tree touched-layouts))
[modif-tree touched-layouts]))
;; Second: Calculate layout positioning
modif-tree
(loop [current (first touched-layouts)
pending (rest touched-layouts)
modif-tree modif-tree]
(->> shapes-tree
(reduce
(fn [modif-tree shape]
(let [has-modifiers? (some? (get-in modif-tree [(:id shape) :modifiers]))
is-layout? (layout? shape)
is-parent? (or (group? shape) (and (frame? shape) (not (layout? shape))))
(if (some? current)
(let [modif-tree (set-layout-modifiers modif-tree objects current)]
(recur (first pending) (rest pending) modif-tree))
modif-tree))]
;; If the current child is inside the layout we ignore the constraints
is-inside-layout? (inside-layout? objects shape)]
(cond-> modif-tree
is-layout?
(set-layout-modifiers objects shape snap-pixel?)
(and has-modifiers? is-parent?)
(set-children-modifiers objects shape (or ignore-constraints is-inside-layout?) snap-pixel?))))
modif-tree))]
;;(.log js/console ">result" (modif->js modif-tree objects))
modif-tree))

View file

@ -14,8 +14,8 @@
[app.common.geom.shapes.path :as gpa]
[app.common.geom.shapes.rect :as gpr]
[app.common.math :as mth]
[app.common.spec :as us]
[app.common.text :as txt]))
[app.common.text :as txt]
[app.common.types.modifiers :as ctm]))
(def ^:dynamic *skip-adjust* false)
@ -76,14 +76,6 @@
; ---- Geometric operations
(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- calculate-skew-angle
"Calculates the skew angle of the parallelogram given by the points"
[[p1 _ p3 p4]]
@ -182,17 +174,6 @@
(gmt/multiply (:transform-inverse shape (gmt/matrix)))
(gmt/translate (gpt/negate center)))))
(defn transform-point-center
"Transform a point around the shape center"
[point center matrix]
(if (and (some? point) (some? matrix) (some? center))
(gpt/transform
point
(gmt/multiply (gmt/translate-matrix center)
matrix
(gmt/translate-matrix (gpt/negate center))))
point))
(defn transform-rect
"Transform a rectangles and changes its attributes"
[rect matrix]
@ -273,6 +254,30 @@
(if transform (gmt/multiply transform matrix) matrix)
(if transform-inverse (gmt/multiply matrix-inverse transform-inverse) matrix-inverse)]))
(defn- adjust-shape-flips
"After some tranformations the flip-x/flip-y flags can change we need
to check this before adjusting the selrect"
[shape points]
(let [points' (:points shape)
xv1 (gpt/to-vec (nth points' 0) (nth points' 1))
xv2 (gpt/to-vec (nth points 0) (nth points 1))
dot-x (gpt/dot xv1 xv2)
yv1 (gpt/to-vec (nth points' 0) (nth points' 3))
yv2 (gpt/to-vec (nth points 0) (nth points 3))
dot-y (gpt/dot yv1 yv2)]
(cond-> shape
(neg? dot-x)
(-> (update :flip-x not)
(update :rotation -))
(neg? dot-y)
(-> (update :flip-y not)
(update :rotation -)))))
(defn apply-transform
"Given a new set of points transformed, set up the rectangle so it keeps
its properties. We adjust de x,y,width,height and create a custom transform"
@ -280,6 +285,7 @@
(let [points' (:points shape)
points (gco/transform-points points' transform-mtx)
shape (-> shape (adjust-shape-flips points))
bool? (= (:type shape) :bool)
path? (= (:type shape) :path)
@ -289,7 +295,6 @@
base-rotation (or (:rotation shape) 0)
modif-rotation (or (get-in shape [:modifiers :rotation]) 0)
rotation (mod (+ base-rotation modif-rotation) 360)]
(-> shape
(cond-> bool?
(update :bool-content gpa/transform-content transform-mtx))
@ -368,173 +373,8 @@
(assoc :flip-x (-> mask :flip-x))
(assoc :flip-y (-> mask :flip-y)))))
;; --- Modifiers
;; The `modifiers` structure contains a list of transformations to
;; do make to a shape, in this order:
;;
;; - resize-origin (gpt/point) + resize-vector (gpt/point)
;; 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.
(defn empty-modifiers? [modifiers]
(empty? (dissoc modifiers :ignore-geometry?)))
(defn resize-modifiers
[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
(assoc size attr value)
(if (= attr :width)
(-> size
(assoc :width value)
(assoc :height (/ value proportion)))
(-> size
(assoc :height value)
(assoc :width (* value proportion)))))
width (:width new-size)
height (:height new-size)
shape-transform (:transform shape)
shape-transform-inv (:transform-inverse shape)
shape-center (gco/center-shape shape)
{sr-width :width sr-height :height} (:selrect shape)
origin (cond-> (gpt/point (:selrect shape))
(some? shape-transform)
(transform-point-center shape-center shape-transform))
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}))
(defn change-orientation-modifiers
[shape orientation]
(us/assert map? shape)
(us/verify #{:horiz :vert} orientation)
(let [width (:width shape)
height (:height shape)
new-width (if (= orientation :horiz) (max width height) (min width height))
new-height (if (= orientation :horiz) (min width height) (max width height))
shape-transform (:transform shape)
shape-transform-inv (:transform-inverse shape)
shape-center (gco/center-shape shape)
{sr-width :width sr-height :height} (:selrect shape)
origin (cond-> (gpt/point (:selrect shape))
(some? shape-transform)
(transform-point-center shape-center shape-transform))
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 [displacement (let [shape-center (gco/center-shape shape)]
(-> (gmt/matrix)
(gmt/rotate angle center)
(gmt/rotate (- angle) shape-center)))]
{:rotation angle
:displacement displacement}))
(defn merge-modifiers
[objects modifiers]
(let [set-modifier
(fn [objects [id modifiers]]
(-> objects
(d/update-when id merge modifiers)))]
(->> modifiers
(reduce set-modifier objects))))
(defn modifiers->transform
([modifiers]
(modifiers->transform nil modifiers))
([center 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))
;; 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))))
resize-2 (when (some? resize-v2)
(gpt/point (normalize-scale (:x resize-v2))
(normalize-scale (:y resize-v2))))
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)
(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)))
(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)))
(some? displacement)
(gmt/multiply displacement)
(some? rt-modif)
(-> (gmt/translate center)
(gmt/multiply (gmt/rotate-matrix rt-modif))
(gmt/translate (gpt/negate center)))))))
(defn- set-flip [shape modifiers]
#_(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)
@ -547,7 +387,25 @@
(-> (update :flip-y not)
(update :rotation -)))))
(defn- apply-displacement [shape]
#_(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)
@ -580,64 +438,87 @@
(defn apply-modifiers
[shape modifiers]
(let [center (gco/center-shape shape)
transform (modifiers->transform center modifiers)]
(apply-transform shape transform)))
transform (ctm/modifiers->transform center modifiers)]
(-> shape
#_(set-flip-2 transform)
(apply-transform transform))))
(defn apply-objects-modifiers
[objects modifiers]
(letfn [(process-shape [objects [id modifier]]
(update objects id apply-modifiers (:modifiers modifier)))]
(reduce process-shape objects modifiers)))
(defn transform-shape
[shape]
(let [modifiers (:modifiers shape)]
(cond
(nil? modifiers)
shape
([shape]
(let [modifiers (:modifiers shape)]
(-> shape
(dissoc :modifiers)
(transform-shape modifiers))))
(empty-modifiers? modifiers)
(dissoc shape :modifiers)
([shape modifiers]
(cond-> shape
(and (some? modifiers) (not (ctm/empty-modifiers? modifiers)))
(-> (apply-modifiers modifiers)
(apply-text-resize modifiers)))))
:else
(let [shape (apply-displacement shape)
modifiers (:modifiers shape)]
(cond-> shape
(not (empty-modifiers? modifiers))
(-> (set-flip 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)]
:always
(dissoc :modifiers))))))
;;(.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))))
(defn transform-bounds
[points center {:keys [displacement displacement-after resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}]
[points center {:keys [v2 displacement displacement-after resize-transform-inverse resize-vector resize-origin resize-vector-2 resize-origin-2]}]
;; FIXME: Improve Performance
(let [resize-transform-inverse (or resize-transform-inverse (gmt/matrix))
(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))
displacement
(when (some? displacement)
(gmt/multiply resize-transform-inverse displacement))
resize-origin
(when (some? resize-origin)
(transform-point-center resize-origin center resize-transform-inverse))
resize-origin
(when (some? resize-origin)
(gmt/transform-point-center resize-origin center resize-transform-inverse))
resize-origin-2
(when (some? resize-origin-2)
(transform-point-center resize-origin-2 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
(if (and (nil? displacement) (nil? resize-origin) (nil? resize-origin-2) (nil? displacement-after))
points
(cond-> points
(some? displacement)
(gco/transform-points displacement)
(cond-> points
(some? displacement)
(gco/transform-points displacement)
(some? resize-origin)
(gco/transform-points resize-origin (gmt/scale-matrix resize-vector))
(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? resize-origin-2)
(gco/transform-points resize-origin-2 (gmt/scale-matrix resize-vector-2))
(some? displacement-after)
(gco/transform-points displacement-after)))))
(some? displacement-after)
(gco/transform-points displacement-after))))))
(defn transform-selrect
[selrect modifiers]

View file

@ -102,13 +102,7 @@
(fix-frames-selrects)
(and (empty? (:points object)) (not= (:id object) uuid/zero))
(fix-empty-points)
;; Setup an empty transformation to re-calculate selrects
;; and points data
:always
(-> (assoc :modifiers {:displacement (gmt/matrix)})
(gsh/transform-shape))))
(fix-empty-points)))
(update-page [page]
(update page :objects d/update-vals update-object))]

View file

@ -0,0 +1,256 @@
;; 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) UXBOX Labs SL
(ns app.common.types.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.spec :as us]))
;; --- Modifiers
;; The `modifiers` structure contains a list of transformations to
;; do make to a shape, in this order:
;;
;; - 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.
(defn move
([x y]
(move (gpt/point x y)))
([vector]
{:v2 [{:type :move :vector vector}]}))
(defn resize
[vector origin]
{:v2 [{:type :resize :vector vector :origin origin}]})
(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)))))
(defn add-resize
[object vector origin]
(-> object
(assoc-in [:modifiers :resize-vector] vector)
(assoc-in [:modifiers :resize-origin] origin)))
(defn empty-modifiers? [modifiers]
(empty? (dissoc modifiers :ignore-geometry?)))
(defn resize-modifiers
[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
(assoc size attr value)
(if (= attr :width)
(-> size
(assoc :width value)
(assoc :height (/ value proportion)))
(-> size
(assoc :height value)
(assoc :width (* value proportion)))))
width (:width new-size)
height (:height new-size)
shape-transform (:transform shape)
shape-transform-inv (:transform-inverse shape)
shape-center (gco/center-shape shape)
{sr-width :width sr-height :height} (:selrect shape)
origin (cond-> (gpt/point (:selrect shape))
(some? shape-transform)
(gmt/transform-point-center shape-center shape-transform))
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}))
(defn change-orientation-modifiers
[shape orientation]
(us/assert map? shape)
(us/verify #{:horiz :vert} orientation)
(let [width (:width shape)
height (:height shape)
new-width (if (= orientation :horiz) (max width height) (min width height))
new-height (if (= orientation :horiz) (min width height) (max width height))
shape-transform (:transform shape)
shape-transform-inv (:transform-inverse shape)
shape-center (gco/center-shape shape)
{sr-width :width sr-height :height} (:selrect shape)
origin (cond-> (gpt/point (:selrect shape))
(some? shape-transform)
(gmt/transform-point-center shape-center shape-transform))
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}))
(defn merge-modifiers
[objects modifiers]
(let [set-modifier
(fn [objects [id modifiers]]
(-> objects
(d/update-when id merge modifiers)))]
(->> modifiers
(reduce set-modifier objects))))
(defn modifiers-v2->transform
[modifiers]
(letfn [(apply-modifier [matrix {:keys [type vector rotation center origin transform transform-inverse] :as modifier}]
(case type
:move
(gmt/multiply (gmt/translate-matrix vector) matrix)
;;:transform
;;(gmt/multiply transform matrix)
:resize
(gmt/multiply
(-> (gmt/matrix)
(gmt/translate origin)
(cond-> (some? transform)
(gmt/multiply transform))
(gmt/scale vector)
(cond-> (some? transform-inverse)
(gmt/multiply transform-inverse))
(gmt/translate (gpt/negate origin)))
matrix)
:rotation
;; TODO LAYOUT: Comprobar que pasa si no hay centro
(gmt/multiply
(-> (gmt/matrix)
(gmt/translate center)
(gmt/multiply (gmt/rotate-matrix rotation))
(gmt/translate (gpt/negate center)))
matrix)))]
(->> modifiers
(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 modifiers->transform
([modifiers]
(modifiers->transform nil modifiers))
([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))
;; 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))))
resize-2 (when (some? resize-v2)
(gpt/point (normalize-scale (:x resize-v2))
(normalize-scale (:y resize-v2))))
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)
(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)))
(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)))
(some? displacement)
(gmt/multiply displacement)
(some? rt-modif)
(-> (gmt/translate center)
(gmt/multiply (gmt/rotate-matrix rt-modif))
(gmt/translate (gpt/negate center))))))
))

View file

@ -159,8 +159,8 @@
build-move-event
(fn [comment-thread]
(let [frame (get objects (:frame-id comment-thread))
frame' (-> (merge frame (get object-modifiers (:frame-id comment-thread)))
(gsh/transform-shape))
modifiers (get object-modifiers (:frame-id comment-thread))
frame' (gsh/transform-shape frame modifiers)
moved (gpt/to-vec (gpt/point (:x frame) (:y frame))
(gpt/point (:x frame') (:y frame')))
position (get-in threads-position-map [(:id comment-thread) :position])

View file

@ -10,6 +10,7 @@
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.common.pages.helpers :as cph]
[app.common.types.modifiers :as ctm]
[app.common.types.shape :as cts]
[app.common.types.shape-tree :as ctst]
[app.common.uuid :as uuid]
@ -37,9 +38,7 @@
scalev)]
(-> shape
(assoc :click-draw? false)
(assoc-in [:modifiers :resize-vector] scalev)
(assoc-in [:modifiers :resize-origin] (gpt/point x y))
(assoc-in [:modifiers :resize-rotation] 0))))
(gsh/transform-shape (ctm/resize scalev (gpt/point x y))))))
(defn update-drawing [state point lock?]
(update-in state [:workspace-drawing :object] resize-shape point lock?))

View file

@ -6,10 +6,10 @@
(ns app.main.data.workspace.drawing.common
(:require
[app.common.geom.matrix :as gmt]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.common.pages.helpers :as cph]
[app.common.types.modifiers :as ctm]
[app.common.types.shape :as cts]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.state-helpers :as wsh]
@ -51,8 +51,8 @@
(and click-draw? (not text?))
(-> (assoc :width min-side :height min-side)
(assoc-in [:modifiers :displacement]
(gmt/translate-matrix (- (/ min-side 2)) (- (/ min-side 2)))))
(gsh/transform-shape (ctm/move (- (/ min-side 2)) (- (/ min-side 2))))
#_(ctm/add-move (- (/ min-side 2)) (- (/ min-side 2))))
(and click-draw? text?)
(assoc :height 17 :width 4 :grow-type :auto-width)
@ -61,8 +61,7 @@
(cts/setup-rect-selrect)
:always
(-> (gsh/transform-shape)
(dissoc :initialized? :click-draw?)))]
(dissoc :initialized? :click-draw?))]
;; Add & select the created shape to the workspace
(rx/concat
(if (= :text (:type shape))

View file

@ -79,8 +79,7 @@
build-move-event
(fn [guide]
(let [frame (get objects (:frame-id guide))
frame' (-> (merge frame (get object-modifiers (:frame-id guide)))
(gsh/transform-shape))
frame' (gsh/transform-shape (get object-modifiers (:frame-id guide)))
moved (gpt/to-vec (gpt/point (:x frame) (:y frame))
(gpt/point (:x frame') (:y frame')))

View file

@ -55,7 +55,7 @@
(dwt/apply-modifiers))
(rx/empty))))))
;; TODO: Remove constraints from children
;; TODO LAYOUT: Remove constraints from children
(defn create-layout
[ids type]
(ptk/reify ::create-layout

View file

@ -8,9 +8,9 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph]
[app.common.path.commands :as upc]))
[app.common.path.commands :as upc]
[app.common.types.modifiers :as ctm]))
(defn lookup-page
([state]
@ -137,5 +137,6 @@
children (select-keys objects children-ids)]
(as-> children $
(gsh/merge-modifiers $ modifiers)
;; TODO LAYOUT: REVIEW THIS
(ctm/merge-modifiers $ modifiers)
(d/mapm (set-content-modifiers state) $))))

View file

@ -13,6 +13,7 @@
[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]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.common :as dwc]
@ -319,17 +320,16 @@
(letfn [(update-fn [shape]
(let [{:keys [selrect grow-type]} shape
{shape-width :width shape-height :height} selrect
modifier-width (gsh/resize-modifiers shape :width new-width)
modifier-height (gsh/resize-modifiers shape :height new-height)]
modifier-width (ctm/resize-modifiers shape :width new-width)
modifier-height (ctm/resize-modifiers 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))
(-> (assoc :modifiers modifier-width)
(gsh/transform-shape))
(gsh/transform-shape modifier-width)
(and (not-changed? shape-height new-height)
(or (= grow-type :auto-height) (= grow-type :auto-width)))
(-> (assoc :modifiers modifier-height)
(gsh/transform-shape)))))]
(gsh/transform-shape modifier-height))))]
(rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? false}))))))
@ -346,18 +346,17 @@
(defn apply-text-modifier
[shape {:keys [width height position-data]}]
(let [modifier-width (when width (gsh/resize-modifiers shape :width width))
modifier-height (when height (gsh/resize-modifiers shape :height height))
(let [modifier-width (when width (ctm/resize-modifiers shape :width width))
modifier-height (when height (ctm/resize-modifiers shape :height height))
;; TODO LAYOUT: MEZCLAR LOS DOS EN UN UNICO MODIFIER
new-shape
(cond-> shape
(some? modifier-width)
(-> (assoc :modifiers modifier-width)
(gsh/transform-shape))
(gsh/transform-shape modifier-width)
(some? modifier-height)
(-> (assoc :modifiers modifier-height)
(gsh/transform-shape))
(gsh/transform-shape modifier-height)
(some? position-data)
(assoc :position-data position-data))

View file

@ -16,6 +16,7 @@
[app.common.pages.common :as cpc]
[app.common.pages.helpers :as cph]
[app.common.spec :as us]
[app.common.types.modifiers :as ctm]
[app.common.types.shape-tree :as ctst]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.collapse :as dwc]
@ -154,14 +155,14 @@
ids
(->> shapes
(remove #(get % :blocked false))
(mapcat #(cph/get-children objects (:id %)))
(concat shapes)
#_(mapcat #(cph/get-children objects (:id %)))
#_(concat shapes)
(filter #((cpc/editable-attrs (:type %)) :rotation))
(map :id))
get-modifier
(fn [shape]
(gsh/rotation-modifiers shape center angle))
(ctm/rotation-modifiers shape center angle))
modif-tree
(gsh/set-objects-modifiers ids objects get-modifier false false)]
@ -193,7 +194,7 @@
(let [objects (wsh/lookup-page-objects state)
object-modifiers (get state :workspace-modifiers)
ids (keys object-modifiers)
ids (or (keys object-modifiers) [])
ids-with-children (into (vec ids) (mapcat #(cph/get-children-ids objects %)) ids)
shapes (map (d/getf objects) ids)
@ -209,11 +210,10 @@
(dch/update-shapes
ids
(fn [shape]
(let [modif (get object-modifiers (:id shape))
(let [modif (get-in object-modifiers [(:id shape) :modifiers])
text-shape? (cph/text-shape? shape)]
(-> shape
(merge modif)
(gsh/transform-shape)
(gsh/transform-shape modif)
(cond-> text-shape?
(update-grow-type shape)))))
{:reg-objects? true
@ -295,7 +295,7 @@
(let [children (map (d/getf objects) (:shapes shape))
shape-id (:id shape)
transformed-shape (gsh/transform-shape (merge shape (get modif-tree shape-id)))
transformed-shape (gsh/transform-shape shape (get modif-tree shape-id))
[root transformed-root ignore-geometry?]
(check-delta shape root transformed-shape transformed-root objects modif-tree)
@ -331,10 +331,10 @@
rotation (or rotation 0)
initial (gsh/transform-point-center initial shape-center shape-transform-inverse)
initial (gmt/transform-point-center initial shape-center shape-transform-inverse)
initial (fix-init-point initial handler shape)
point (gsh/transform-point-center (if (= rotation 0) point-snap point)
point (gmt/transform-point-center (if (= rotation 0) point-snap point)
shape-center shape-transform-inverse)
shapev (-> (gpt/point width height))
@ -381,14 +381,28 @@
(gpt/transform shape-transform)))
resize-origin
(cond-> (gsh/transform-point-center handler-origin shape-center shape-transform)
(cond-> (gmt/transform-point-center handler-origin shape-center shape-transform)
(some? displacement)
(gpt/add displacement))
displacement (when (some? displacement)
(gmt/translate-matrix 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
@ -444,7 +458,7 @@
snap-pixel? (and (contains? (:workspace-layout state) :snap-pixel-grid)
(int? value))
get-modifier
(fn [shape] (gsh/resize-modifiers shape attr value))
(fn [shape] (ctm/resize-modifiers shape attr value))
modif-tree
(gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)]
@ -468,7 +482,7 @@
snap-pixel? (contains? (get state :workspace-layout) :snap-pixel-grid)
get-modifier
(fn [shape] (gsh/change-orientation-modifiers shape orientation))
(fn [shape] (ctm/change-orientation-modifiers shape orientation))
modif-tree
(gsh/set-objects-modifiers ids objects get-modifier false snap-pixel?)]
@ -655,7 +669,10 @@
(rx/with-latest vector snap-delta)
;; 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 #(hash-map :displacement (gmt/translate-matrix %)))
#_(rx/map #(hash-map :displacement (gmt/translate-matrix %)))
(rx/map #(array-map :v2 [{:type :move :vector %}]))
(rx/map (partial set-modifiers ids))
(rx/take-until stopper))
@ -704,7 +721,7 @@
(rx/merge
(->> move-events
(rx/scan #(gpt/add %1 mov-vec) (gpt/point 0 0))
(rx/map #(hash-map :displacement (gmt/translate-matrix %)))
(rx/map #(ctm/move %))
(rx/map (partial set-modifiers selected))
(rx/take-until stopper))
(rx/of (move-selected direction shift?)))
@ -735,11 +752,11 @@
cpos (gpt/point (:x bbox) (:y bbox))
pos (gpt/point (or (:x position) (:x bbox))
(or (:y position) (:y bbox)))
delta (gpt/subtract pos cpos)
displ (gmt/translate-matrix delta)]
delta (gpt/subtract pos cpos)]
(rx/of (set-modifiers [id] {:displacement displ} false true)
(apply-modifiers [id]))))))
(rx/of
(set-modifiers [id] (ctm/move delta))
(apply-modifiers [id]))))))
(defn- calculate-frame-for-move
[ids]
@ -787,11 +804,16 @@
(let [objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state {:omit-blocked? true})
shapes (map #(get objects %) selected)
selrect (gsh/selection-rect (->> shapes (map gsh/transform-shape)))
selrect (gsh/selection-rect shapes)
origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))]
(rx/of (set-modifiers selected
{:resize-vector (gpt/point -1.0 1.0)
{: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))}
true)
@ -804,11 +826,16 @@
(let [objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state {:omit-blocked? true})
shapes (map #(get objects %) selected)
selrect (gsh/selection-rect (->> shapes (map gsh/transform-shape)))
selrect (gsh/selection-rect shapes)
origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))]
(rx/of (set-modifiers selected
{:resize-vector (gpt/point 1.0 -1.0)
{: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))))}
true)

View file

@ -15,12 +15,12 @@
["react-dom/server" :as rds]
[app.common.colors :as clr]
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.geom.shapes.bounds :as gsb]
[app.common.math :as mth]
[app.common.pages.helpers :as cph]
[app.common.types.modifiers :as ctm]
[app.common.types.shape-tree :as ctst]
[app.config :as cfg]
[app.main.fonts :as fonts]
@ -82,7 +82,8 @@
(let [render-thumbnails? (mf/use-ctx muc/render-thumbnails)
childs (mapv #(get objects %) (:shapes shape))
shape (gsh/transform-shape shape)]
;;shape (gsh/transform-shape shape)
]
(if (and render-thumbnails? (some? (:thumbnail shape)))
[:& frame/frame-thumbnail {:shape shape :bounds (:children-bounds shape)}]
[:& frame-shape {:shape shape :childs childs}])))))
@ -135,7 +136,7 @@
bool-wrapper (mf/use-memo (mf/deps objects) #(bool-wrapper-factory objects))
frame-wrapper (mf/use-memo (mf/deps objects) #(frame-wrapper-factory objects))]
(when (and shape (not (:hidden shape)))
(let [shape (gsh/transform-shape shape)
(let [;;shape (gsh/transform-shape shape)
opts #js {:shape shape}
svg-raw? (= :svg-raw (:type shape))]
(if-not svg-raw?
@ -167,7 +168,8 @@
(let [shapes (cph/get-immediate-children objects)
srect (gsh/selection-rect shapes)
object (merge object (select-keys srect [:x :y :width :height]))
object (gsh/transform-shape object)]
;; object (gsh/transform-shape object)
]
(assoc object :fill-color "#f0f0f0")))
(defn adapt-objects-for-shape
@ -180,14 +182,12 @@
;; Replace the previous object with the new one
objects (assoc objects object-id object)
modifier (-> (gpt/point (:x object) (:y object))
(gpt/negate)
(gmt/translate-matrix))
vector (-> (gpt/point (:x object) (:y object))
(gpt/negate))
mod-ids (cons object-id (cph/get-children-ids objects object-id))
updt-fn #(-> %1
(assoc-in [%2 :modifiers :displacement] modifier)
(update %2 gsh/transform-shape))]
updt-fn #(update %1 %2 gsh/transform-shape (ctm/move vector))]
(reduce updt-fn objects mod-ids)))
@ -247,24 +247,21 @@
bounds2 (gsb/get-object-bounds objects (dissoc frame :shadow :blur))
delta-bounds (gpt/point (:x bounds) (:y bounds))
modifier (gmt/translate-matrix (gpt/negate delta-bounds))
vector (gpt/negate delta-bounds)
children-ids
(cph/get-children-ids objects frame-id)
objects
(mf/with-memo [frame-id objects modifier]
(let [update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)]
(mf/with-memo [frame-id objects vector]
(let [update-fn #(update-in %1 %2 ctm/add-move vector)]
(->> children-ids
(into [frame-id])
(reduce update-fn objects))))
frame
(mf/with-memo [modifier]
(-> frame
(assoc-in [:modifiers :displacement] modifier)
(gsh/transform-shape)))
(mf/with-memo [vector]
(gsh/transform-shape frame (ctm/move vector)))
frame
(cond-> frame
@ -305,22 +302,21 @@
(let [group-id (:id group)
include-metadata? (mf/use-ctx export/include-metadata-ctx)
modifier
vector
(mf/use-memo
(mf/deps (:x group) (:y group))
(fn []
(-> (gpt/point (:x group) (:y group))
(gpt/negate)
(gmt/translate-matrix))))
(gpt/negate))))
objects
(mf/use-memo
(mf/deps modifier objects group-id)
(mf/deps vector objects group-id)
(fn []
(let [modifier-ids (cons group-id (cph/get-children-ids objects group-id))
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
update-fn #(update %1 %2 ctm/add-move vector)
modifiers (reduce update-fn {} modifier-ids)]
(gsh/merge-modifiers objects modifiers))))
(ctm/merge-modifiers objects modifiers))))
group (get objects group-id)
width (* (:width group) zoom)

View file

@ -6,7 +6,6 @@
(ns app.main.ui.shapes.bool
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes :as gsh]
[app.main.ui.hooks :refer [use-equal-memo]]
@ -15,6 +14,7 @@
[app.util.object :as obj]
[rumext.v2 :as mf]))
;; TODO LAYOUT: REVIEW DYNAMIC CHANGES IN BOOLEANS
(defn bool-shape
[shape-wrapper]
(mf/fnc bool-shape
@ -35,7 +35,7 @@
(some? childs)
(->> childs
(d/mapm #(gsh/transform-shape %2))
#_(d/mapm #(gsh/transform-shape %2))
(gsh/calc-bool-content shape)))))]
[:*

View file

@ -7,6 +7,7 @@
(ns app.main.ui.shapes.mask
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes :as gsh]
[app.main.ui.context :as muc]
[cuerdas.core :as str]
@ -50,9 +51,7 @@
render-id (mf/use-ctx muc/render-id)
svg-text? (and (= :text (:type mask)) (some? (:position-data mask)))
mask-bb (-> (gsh/transform-shape mask)
(:points))
mask-bb (:points mask)
mask-bb-rect (gsh/points->rect mask-bb)]
[:defs
[:filter {:id (filter-id render-id mask)}
@ -68,7 +67,7 @@
[:clipPath {:class "mask-clip-path"
:id (clip-id render-id mask)}
[:polyline {:points (->> mask-bb
(map #(str (:x %) "," (:y %)))
(map #(dm/str (:x %) "," (:y %)))
(str/join " "))}]]
;; When te shape is a text we pass to the shape the info and disable the filter.

View file

@ -88,7 +88,7 @@
[props]
(let [shape (unchecked-get props "shape")
childs (mapv #(get objects %) (:shapes shape))
shape (gsh/transform-shape shape)
;;shape (gsh/transform-shape shape)
props (-> (obj/create)
(obj/merge! props)
@ -171,8 +171,7 @@
(mf/use-memo (mf/deps objects)
#(svg-raw-container-factory objects))]
(when (and shape (not (:hidden shape)))
(let [shape (-> (gsh/transform-shape shape)
(gsh/translate-to-frame frame))
(let [shape (gsh/translate-to-frame shape frame)
opts #js {:shape shape
:frame frame}]
(case (:type shape)

View file

@ -8,9 +8,9 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.pages.helpers :as cph]
[app.common.types.modifiers :as ctm]
[app.common.types.page :as ctp]
[app.common.uuid :as uuid]
[app.main.data.comments :as dcm]
@ -31,11 +31,10 @@
[frame size objects]
(let [
frame-id (:id frame)
modifier (-> (gpt/point (:x size) (:y size))
(gpt/negate)
(gmt/translate-matrix))
vector (-> (gpt/point (:x size) (:y size))
(gpt/negate))
update-fn #(d/update-when %1 %2 assoc-in [:modifiers :displacement] modifier)]
update-fn #(d/update-when %1 %2 ctm/add-move vector)]
(->> (cph/get-children-ids objects frame-id)
(into [frame-id])

View file

@ -350,7 +350,7 @@
[props]
(let [shape (obj/get props "shape")
childs (mapv #(get objects %) (:shapes shape))
shape (gsh/transform-shape shape)
;;shape (gsh/transform-shape shape)
props (obj/merge! #js {} props
#js {:shape shape
:childs childs
@ -429,7 +429,8 @@
(mf/with-memo [objects]
(svg-raw-container-factory objects))]
(when (and shape (not (:hidden shape)))
(let [shape (-> (gsh/transform-shape shape)
(let [shape (-> shape
#_(gsh/transform-shape)
(gsh/translate-to-frame frame))
opts #js {:shape shape

View file

@ -11,6 +11,7 @@
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.types.modifiers :as ctm]
[app.main.store :as st]
[app.main.ui.workspace.viewport.utils :as vwu]
[app.util.dom :as dom]
@ -184,6 +185,7 @@
text? (= type :text)
transform-text? (and text? (and (nil? (:resize-vector modifiers)) (nil? (:resize-vector-2 modifiers))))]
;; TODO LAYOUT: Adapt to new modifiers
(doseq [node nodes]
(cond
;; Text shapes need special treatment because their resize only change
@ -197,7 +199,7 @@
(dom/class? node "text-container")
(let [modifiers (dissoc modifiers :displacement :rotation)]
(when (not (gsh/empty-modifiers? modifiers))
(when (not (ctm/empty-modifiers? modifiers))
(let [mtx (-> shape
(assoc :modifiers modifiers)
(gsh/transform-shape)
@ -260,12 +262,15 @@
(d/mapm (fn [id {modifiers :modifiers}]
(let [shape (get objects id)
center (gsh/center-shape shape)
;; TODO LAYOUT: Adapt to new modifiers
modifiers (cond-> modifiers
;; For texts we only use the displacement because
;; resize needs to recalculate the text layout
(= :text (:type shape))
(select-keys [:displacement :rotation]))]
(gsh/modifiers->transform center modifiers)))
(select-keys [:displacement :rotation]))
]
(ctm/modifiers->transform center modifiers)))
modifiers))))
shapes

View file

@ -58,7 +58,7 @@
:height height
:style {:fill "none" :stroke "red"}}]
;; Text baselineazo
;; Text baseline
[:line {:x1 (mth/round x)
:y1 (mth/round (- (:y data) (:height data)))
:x2 (mth/round (+ x width))

View file

@ -13,6 +13,7 @@
[app.common.math :as mth]
[app.common.pages.helpers :as cph]
[app.common.text :as txt]
[app.common.types.modifiers :as ctm]
[app.main.data.workspace.texts :as dwt]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
@ -33,6 +34,7 @@
(with-meta (meta (:position-data shape))))
(dissoc :position-data :transform :transform-inverse)))
;; TODO LAYOUT: Adapt to new modifiers
(defn strip-modifier
[modifier]
(if (or (some? (dm/get-in modifier [:modifiers :resize-vector]))
@ -43,9 +45,9 @@
(defn process-shape [modifiers {:keys [id] :as shape}]
(let [modifier (-> (get modifiers id) strip-modifier)
shape (cond-> shape
(not (gsh/empty-modifiers? (:modifiers modifier)))
(not (ctm/empty-modifiers? (:modifiers modifier)))
(-> (assoc :grow-type :fixed)
(merge modifier) gsh/transform-shape))]
(gsh/transform-shape modifier)))]
(-> shape
(cond-> (nil? (:position-data shape))
(assoc :migrate true))

View file

@ -7,7 +7,7 @@
(ns app.main.ui.workspace.sidebar.options
(:require
[app.common.data :as d]
[app.common.geom.shapes :as gsh]
[app.common.types.modifiers :as ctm]
[app.main.data.workspace :as udw]
[app.main.refs :as refs]
[app.main.store :as st]
@ -64,7 +64,7 @@
shared-libs (mf/deref refs/workspace-libraries)
modifiers (mf/deref refs/workspace-modifiers)
objects-modified (mf/with-memo [base-objects modifiers]
(gsh/merge-modifiers base-objects modifiers))
(ctm/merge-modifiers base-objects modifiers))
selected-shapes (into [] (keep (d/getf objects-modified)) selected)]
[:div.tool-window
[:div.tool-window-content

View file

@ -79,8 +79,7 @@
modifiers (mf/deref refs/workspace-modifiers)
objects-modified (mf/with-memo [base-objects modifiers]
(gsh/merge-modifiers base-objects modifiers))
(gsh/apply-objects-modifiers base-objects modifiers))
background (get options :background clr/canvas)
;; STATE
@ -203,7 +202,7 @@
{:key (dm/str "texts-" page-id)
:page-id page-id
:objects objects
:modifiers modifiers
;;:modifiers modifiers
:edition edition}]]]]
(when show-comments?
@ -336,10 +335,9 @@
(when show-prototypes?
[:& widgets/frame-flows
{:flows (:flows options)
:objects base-objects
:objects objects-modified
:selected selected
:zoom zoom
:modifiers modifiers
:on-frame-enter on-frame-enter
:on-frame-leave on-frame-leave
:on-frame-select on-frame-select}])
@ -348,8 +346,7 @@
[:& drawarea/draw-area
{:shape drawing-obj
:zoom zoom
:tool drawing-tool
:modifiers modifiers}])
:tool drawing-tool}])
(when show-grids?
[:& frame-grid/frame-grid
@ -371,9 +368,8 @@
:zoom zoom
:page-id page-id
:selected selected
:objects base-objects
:focus focus
:modifiers modifiers}])
:objects objects-modified
:focus focus}])
(when show-snap-distance?
[:& snap-distances/snap-distances
@ -416,7 +412,6 @@
{:zoom zoom
:vbox vbox
:hover-frame frame-parent
:modifiers modifiers
:disabled-guides? disabled-guides?}])
(when show-selection-handlers?

View file

@ -7,7 +7,6 @@
(ns app.main.ui.workspace.viewport.drawarea
"Drawing components."
(:require
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.main.ui.shapes.path :refer [path-shape]]
[app.main.ui.workspace.shapes :as shapes]
@ -22,7 +21,7 @@
[:g.draw-area
[:g {:style {:pointer-events "none"}}
[:& shapes/shape-wrapper {:shape (gsh/transform-shape shape)}]]
[:& shapes/shape-wrapper {:shape shape}]]
(case tool
:path [:& path-editor {:shape shape :zoom zoom}]
@ -31,7 +30,7 @@
(mf/defc generic-draw-area
[{:keys [shape zoom]}]
(let [{:keys [x y width height]} (:selrect (gsh/transform-shape shape))]
(let [{:keys [x y width height]} (:selrect shape)]
(when (and x y
(not (mth/nan? x))
(not (mth/nan? y)))

View file

@ -278,7 +278,7 @@
frame]} (use-guide handle-change-position get-hover-frame zoom guide)
base-frame (or frame hover-frame)
frame (gsh/transform-shape (merge base-frame frame-modifier))
frame (gsh/transform-shape base-frame frame-modifier)
move-vec (gpt/to-vec (gpt/point (:x base-frame) (:y base-frame))
(gpt/point (:x frame) (:y frame)))

View file

@ -9,7 +9,6 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes :as gsh]
[app.common.pages.helpers :as cph]
[app.common.types.shape.interactions :as ctsi]
[app.main.data.workspace :as dw]
@ -254,13 +253,11 @@
(mf/defc interactions
[{:keys [current-transform objects zoom selected hover-disabled?] :as props}]
(let [active-shapes (into []
(comp (filter #(seq (:interactions %)))
(map gsh/transform-shape))
(comp (filter #(seq (:interactions %))))
(vals objects))
selected-shapes (into []
(comp (map (d/getf objects))
(map gsh/transform-shape))
(map (d/getf objects))
selected)
{:keys [editing-interaction-index

View file

@ -72,7 +72,7 @@
"var(--color-primary)" "var(--color-component-highlight)")]
(for [shape shapes]
[:& outline {:key (str "outline-" (:id shape))
:shape (gsh/transform-shape shape)
:shape shape
:zoom zoom
:color color}])))

View file

@ -341,7 +341,7 @@
(let [shape (mf/use-memo
(mf/deps shapes)
#(->> shapes
(map gsh/transform-shape)
#_(map gsh/transform-shape)
(gsh/selection-rect)
(cts/setup-shape)))
on-resize
@ -369,7 +369,7 @@
(let [shape (mf/use-memo
(mf/deps shapes)
#(->> shapes
(map gsh/transform-shape)
#_(map gsh/transform-shape)
(gsh/selection-rect)
(cts/setup-shape)))]
@ -384,7 +384,7 @@
(mf/defc single-handlers
[{:keys [shape zoom color disable-handlers] :as props}]
(let [shape-id (:id shape)
shape (gsh/transform-shape shape)
;;shape (gsh/transform-shape shape)
on-resize
(fn [current-position _initial-position event]
@ -408,14 +408,13 @@
(mf/defc single-selection
[{:keys [shape zoom color disable-handlers on-move-selected on-context-menu] :as props}]
(let [shape (gsh/transform-shape shape)]
[:& controls-selection
{:shape shape
:zoom zoom
:color color
:disable-handlers disable-handlers
:on-move-selected on-move-selected
:on-context-menu on-context-menu}]))
[:& controls-selection
{:shape shape
:zoom zoom
:color color
:disable-handlers disable-handlers
:on-move-selected on-move-selected
:on-context-menu on-context-menu}])
(mf/defc selection-area
{::mf/wrap [mf/memo]}

View file

@ -50,20 +50,14 @@
:opacity line-opacity}])
(defn get-snap
[coord {:keys [shapes page-id remove-snap? zoom modifiers]}]
(let [shapes-sr
(->> shapes
;; Merge modifiers into shapes
(map #(merge % (get modifiers (:id %))))
;; Create the bounding rectangle for the shapes
(gsh/selection-rect))
[coord {:keys [shapes page-id remove-snap? zoom]}]
(let [bounds (gsh/selection-rect shapes)
frame-id (snap/snap-frame-id shapes)]
frame-id (snap/snap-frame-id shapes)]
(->> (rx/of shapes-sr)
(->> (rx/of bounds)
(rx/flat-map
(fn [selrect]
(->> (sp/selrect-snap-points selrect)
(fn [bounds]
(->> (sp/selrect-snap-points bounds)
(map #(vector frame-id %)))))
(rx/flat-map
@ -159,7 +153,7 @@
(mf/defc snap-points
{::mf/wrap [mf/memo]}
[{:keys [layout zoom objects selected page-id drawing modifiers focus] :as props}]
[{:keys [layout zoom objects selected page-id drawing focus] :as props}]
(us/assert set? selected)
(let [shapes (into [] (keep (d/getf objects)) selected)
@ -182,6 +176,5 @@
[:& snap-feedback {:shapes shapes
:page-id page-id
:remove-snap? remove-snap?
:zoom zoom
:modifiers modifiers}]))
:zoom zoom}]))

View file

@ -53,9 +53,7 @@
(defn text-transform
[{:keys [x y]} zoom]
(let [inv-zoom (/ 1 zoom)]
(str
"scale(" inv-zoom ", " inv-zoom ") "
"translate(" (* zoom x) ", " (* zoom y) ")")))
(dm/fmt "scale(%, %) translate(%, %)" inv-zoom inv-zoom (* zoom x) (* zoom y))))
(defn title-transform [frame zoom]
(let [frame-transform (gsh/transform-str frame {:no-flip true})

View file

@ -9,7 +9,6 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.types.shape-tree :as ctt]
[app.common.uuid :as uuid]
[app.main.data.workspace :as dw]
@ -182,8 +181,8 @@
:on-frame-select on-frame-select}]))]))
(mf/defc frame-flow
[{:keys [flow frame modifiers selected? zoom on-frame-enter on-frame-leave on-frame-select]}]
(let [{:keys [x y]} (gsh/transform-shape frame)
[{:keys [flow frame selected? zoom on-frame-enter on-frame-leave on-frame-select]}]
(let [{:keys [x y]} frame
flow-pos (gpt/point x (- y (/ 35 zoom)))
on-mouse-down
@ -217,9 +216,7 @@
:y -15
:width 100000
:height 24
:transform (str (when (and selected? modifiers)
(str (:displacement modifiers) " " ))
(vwu/text-transform flow-pos zoom))}
:transform (vwu/text-transform flow-pos zoom)}
[:div.flow-badge {:class (dom/classnames :selected selected?)}
[:div.content {:on-mouse-down on-mouse-down
:on-double-click on-double-click
@ -234,7 +231,6 @@
(let [flows (unchecked-get props "flows")
objects (unchecked-get props "objects")
zoom (unchecked-get props "zoom")
modifiers (unchecked-get props "modifiers")
selected (or (unchecked-get props "selected") #{})
on-frame-enter (unchecked-get props "on-frame-enter")
@ -248,7 +244,6 @@
:frame frame
:selected? (contains? selected (:id frame))
:zoom zoom
:modifiers modifiers
:on-frame-enter on-frame-enter
:on-frame-leave on-frame-leave
:on-frame-select on-frame-select}]))]))

View file

@ -29,10 +29,9 @@
(defn shape-snap-points
[{:keys [hidden blocked] :as shape}]
(when (and (not blocked) (not hidden))
(let [shape (gsh/transform-shape shape)]
(case (:type shape)
:frame (-> shape :points gsh/points->selrect frame-snap-points)
(into #{(gsh/center-shape shape)} (:points shape))))))
(case (:type shape)
:frame (-> shape :points gsh/points->selrect frame-snap-points)
(into #{(gsh/center-shape shape)} (:points shape)))))
(defn guide-snap-points
[guide frame]