0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-24 23:49:45 -05:00

♻️ Refactor selrec generation

This commit is contained in:
alonso.torres 2022-03-08 15:37:41 +01:00
parent ed9400912c
commit 0f54e85b36
18 changed files with 187 additions and 186 deletions

View file

@ -406,15 +406,24 @@
[v default]
(if (some? v) v default))
(defn num?
"Checks if a value `val` is a number but not an Infinite or NaN"
([val]
(and (number? val)
(mth/finite? val)
(not (mth/nan? val))))
([val & vals]
(and (num? val)
(->> vals (every? num?)))))
(defn check-num
"Function that checks if a number is nil or nan. Will return 0 when not
valid and the number otherwise."
([v]
(check-num v 0))
([v default]
(if (or (not v)
(not (mth/finite? v))
(mth/nan? v)) default v)))
(if (num? v) v default)))
(defn any-key? [element & rest]
(some #(contains? element %) rest))

View file

@ -21,6 +21,11 @@
(def conjv (fnil conj []))
(def conjs (fnil conj #{}))
(defn- raise
[err-str]
#?(:clj (throw (Exception. err-str))
:cljs (throw (js/Error. err-str))))
(defn- commit-change
([file change]
(commit-change file change nil))
@ -75,10 +80,12 @@
(commit-change file change {:add-container? true :fail-on-spec? fail-on-spec?})))
(defn setup-rect-selrect [obj]
(let [rect (select-keys obj [:x :y :width :height])
(defn setup-rect-selrect [{:keys [x y width height transform] :as obj}]
(when-not (d/num? x y width height)
(raise "Coords not valid for object"))
(let [rect (gsh/make-rect x y width height)
center (gsh/center-rect rect)
transform (:transform obj (gmt/matrix))
selrect (gsh/rect->selrect rect)
points (-> (gsh/rect->points rect)
@ -89,17 +96,13 @@
(assoc :points points))))
(defn- setup-path-selrect
[obj]
(let [content (:content obj)
center (:center obj)
[{:keys [content center transform transform-inverse] :as obj}]
transform-inverse
(->> (:transform-inverse obj (gmt/matrix))
(gmt/transform-in center))
(when (or (empty? content) (nil? center))
(raise "Path not valid"))
transform
(->> (:transform obj (gmt/matrix))
(gmt/transform-in center))
(let [transform (gmt/transform-in center transform)
transform-inverse (gmt/transform-in center transform-inverse)
content' (gsh/transform-content content transform-inverse)
selrect (gsh/content->selrect content')
@ -310,21 +313,30 @@
children (->> bool :shapes (mapv #(lookup-shape file %)))
file
(let [objects (lookup-objects file)
bool' (gsh/update-bool-selrect bool children objects)]
(cond
(empty? children)
(commit-change
file
{:type :mod-obj
:id bool-id
:operations
[{:type :set :attr :selrect :val (:selrect bool')}
{:type :set :attr :points :val (:points bool')}
{:type :set :attr :x :val (-> bool' :selrect :x)}
{:type :set :attr :y :val (-> bool' :selrect :y)}
{:type :set :attr :width :val (-> bool' :selrect :width)}
{:type :set :attr :height :val (-> bool' :selrect :height)}]}
{:type :del-obj
:id bool-id}
{:add-container? true})
{:add-container? true}))]
:else
(let [objects (lookup-objects file)
bool' (gsh/update-bool-selrect bool children objects)]
(commit-change
file
{:type :mod-obj
:id bool-id
:operations
[{:type :set :attr :selrect :val (:selrect bool')}
{:type :set :attr :points :val (:points bool')}
{:type :set :attr :x :val (-> bool' :selrect :x)}
{:type :set :attr :y :val (-> bool' :selrect :y)}
{:type :set :attr :width :val (-> bool' :selrect :width)}
{:type :set :attr :height :val (-> bool' :selrect :height)}]}
{:add-container? true})))]
(-> file
(update :parent-stack pop))))

View file

@ -187,7 +187,7 @@
(defmethod pp/simple-dispatch Matrix [obj] (pr obj))
(defn transform-in [pt mtx]
(if (some? pt)
(if (and (some? pt) (some? mtx))
(-> (matrix)
(translate pt)
(multiply mtx)

View file

@ -141,15 +141,17 @@
(dm/export gco/center-selrect)
(dm/export gco/center-rect)
(dm/export gco/center-points)
(dm/export gco/make-centered-rect)
(dm/export gco/transform-points)
(dm/export gpr/make-rect)
(dm/export gpr/rect->selrect)
(dm/export gpr/rect->points)
(dm/export gpr/points->selrect)
(dm/export gpr/points->rect)
(dm/export gpr/center->rect)
(dm/export gpr/center->selrect)
(dm/export gpr/join-rects)
(dm/export gpr/join-selrects)
(dm/export gpr/contains-selrect?)
(dm/export gtr/move)

View file

@ -6,29 +6,24 @@
(ns app.common.geom.shapes.common
(:require
[app.common.data :as d]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]))
(defn center-rect
[{:keys [x y width height]}]
(when (and (mth/finite? x)
(mth/finite? y)
(mth/finite? width)
(mth/finite? height))
(when (d/num? x y width height)
(gpt/point (+ x (/ width 2.0))
(+ y (/ height 2.0)))))
(defn center-selrect
"Calculate the center of the shape."
"Calculate the center of the selrect."
[selrect]
(center-rect selrect))
(def map-x-xf (comp (map :x) (remove nil?)))
(def map-y-xf (comp (map :y) (remove nil?)))
(defn center-points [points]
(let [ptx (into [] map-x-xf points)
pty (into [] map-y-xf points)
(let [ptx (into [] (keep :x) points)
pty (into [] (keep :y) points)
minx (reduce min ##Inf ptx)
miny (reduce min ##Inf pty)
maxx (reduce max ##-Inf ptx)
@ -41,35 +36,12 @@
[shape]
(center-rect (:selrect shape)))
(defn make-centered-rect
"Creates a rect given a center and a width and height"
[center width height]
{:x (- (:x center) (/ width 2.0))
:y (- (:y center) (/ height 2.0))
:width width
:height height})
(defn make-centered-selrect
"Creates a rect given a center and a width and height"
[center width height]
(let [x1 (- (:x center) (/ width 2.0))
y1 (- (:y center) (/ height 2.0))
x2 (+ x1 width)
y2 (+ y1 height)]
{:x x1
:y y1
:x1 x1
:x2 x2
:y1 y1
:y2 y2
:width width
:height height}))
(defn transform-points
([points matrix]
(transform-points points nil matrix))
([points center matrix]
(if (some? matrix)
(if (and (d/not-empty? points) (some? matrix))
(let [prev (if center (gmt/translate-matrix center) (gmt/matrix))
post (if center (gmt/translate-matrix (gpt/negate center)) (gmt/matrix))

View file

@ -362,13 +362,8 @@
extremities (mapcat calc-extremities
content
(concat [nil] content))
selrect (gpr/points->selrect extremities)]
(-> selrect
(update :width #(if (mth/almost-zero? %) 1 %))
(update :height #(if (mth/almost-zero? %) 1 %)))))
(concat [nil] content))]
(gpr/points->selrect extremities)))
(defn move-content [content move-vec]
(let [dx (:x move-vec)
@ -393,23 +388,26 @@
(defn transform-content
[content transform]
(let [set-tr (fn [params px py]
(let [tr-point (-> (gpt/point (get params px) (get params py))
(gpt/transform transform))]
(assoc params
px (:x tr-point)
py (:y tr-point))))
(if (some? transform)
(let [set-tr
(fn [params px py]
(let [tr-point (-> (gpt/point (get params px) (get params py))
(gpt/transform transform))]
(assoc params
px (:x tr-point)
py (:y tr-point))))
transform-params
(fn [{:keys [x c1x c2x] :as params}]
(cond-> params
(some? x) (set-tr :x :y)
(some? c1x) (set-tr :c1x :c1y)
(some? c2x) (set-tr :c2x :c2y)))]
transform-params
(fn [{:keys [x c1x c2x] :as params}]
(cond-> params
(some? x) (set-tr :x :y)
(some? c1x) (set-tr :c1x :c1y)
(some? c2x) (set-tr :c2x :c2y)))]
(into []
(map #(update % :params transform-params))
content)))
(into []
(map #(update % :params transform-params))
content))
content))
(defn segments->content
([segments]

View file

@ -6,80 +6,101 @@
(ns app.common.geom.shapes.rect
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.math :as mth]))
(defn make-rect
[x y width height]
(when (d/num? x y width height)
(let [width (max width 0.01)
height (max height 0.01)]
{:x x
:y y
:width width
:height height})))
(defn make-selrect
[x y width height]
(when (d/num? x y width height)
(let [width (max width 0.01)
height (max height 0.01)]
{:x x
:y y
:x1 x
:y1 y
:x2 (+ x width)
:y2 (+ y height)
:width width
:height height})))
(defn rect->points [{:keys [x y width height]}]
;; (assert (number? x))
;; (assert (number? y))
;; (assert (and (number? width) (> width 0)))
;; (assert (and (number? height) (> height 0)))
[(gpt/point x y)
(gpt/point (+ x width) y)
(gpt/point (+ x width) (+ y height))
(gpt/point x (+ y height))])
(when (d/num? x y)
(let [width (max width 0.01)
height (max height 0.01)]
[(gpt/point x y)
(gpt/point (+ x width) y)
(gpt/point (+ x width) (+ y height))
(gpt/point x (+ y height))])))
(defn rect->lines [{:keys [x y width height]}]
[[(gpt/point x y) (gpt/point (+ x width) y)]
[(gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height))]
[(gpt/point (+ x width) (+ y height)) (gpt/point x (+ y height))]
[(gpt/point x (+ y height)) (gpt/point x y)]])
(when (d/num? x y)
(let [width (max width 0.01)
height (max height 0.01)]
[[(gpt/point x y) (gpt/point (+ x width) y)]
[(gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height))]
[(gpt/point (+ x width) (+ y height)) (gpt/point x (+ y height))]
[(gpt/point x (+ y height)) (gpt/point x y)]])))
(defn points->rect
[points]
(let [minx (transduce gco/map-x-xf min ##Inf points)
miny (transduce gco/map-y-xf min ##Inf points)
maxx (transduce gco/map-x-xf max ##-Inf points)
maxy (transduce gco/map-y-xf max ##-Inf points)]
{:x minx
:y miny
:width (- maxx minx)
:height (- maxy miny)}))
(when (d/not-empty? points)
(let [minx (transduce (keep :x) min ##Inf points)
miny (transduce (keep :y) min ##Inf points)
maxx (transduce (keep :x) max ##-Inf points)
maxy (transduce (keep :y) max ##-Inf points)]
(when (d/num? minx miny maxx maxy)
(make-rect minx miny (- maxx minx) (- maxy miny))))))
(defn points->selrect [points]
(let [{:keys [x y width height] :as rect} (points->rect points)]
(assoc rect
:x1 x
:x2 (+ x width)
:y1 y
:y2 (+ y height))))
(when-let [rect (points->rect points)]
(let [{:keys [x y width height]} rect]
(make-selrect x y width height))))
(defn rect->selrect [rect]
(-> rect rect->points points->selrect))
(defn join-rects [rects]
(let [minx (transduce (comp (map :x) (remove nil?)) min ##Inf rects)
miny (transduce (comp (map :y) (remove nil?)) min ##Inf rects)
maxx (transduce (comp (map #(+ (:x %) (:width %))) (remove nil?)) max ##-Inf rects)
maxy (transduce (comp (map #(+ (:y %) (:height %))) (remove nil?)) max ##-Inf rects)]
{:x minx
:y miny
:width (- maxx minx)
:height (- maxy miny)}))
(when (d/not-empty? rects)
(let [minx (transduce (keep :x) min ##Inf rects)
miny (transduce (keep :y) min ##Inf rects)
maxx (transduce (keep #(when (and (:x %) (:width %)) (+ (:x %) (:width %)))) max ##-Inf rects)
maxy (transduce (keep #(when (and (:y %) (:height %))(+ (:y %) (:height %)))) max ##-Inf rects)]
(when (d/num? minx miny maxx maxy)
(make-rect minx miny (- maxx minx) (- maxy miny))))))
(defn join-selrects [selrects]
(let [minx (transduce (comp (map :x1) (remove nil?)) min ##Inf selrects)
miny (transduce (comp (map :y1) (remove nil?)) min ##Inf selrects)
maxx (transduce (comp (map :x2) (remove nil?)) max ##-Inf selrects)
maxy (transduce (comp (map :y2) (remove nil?)) max ##-Inf selrects)]
{:x minx
:y miny
:x1 minx
:y1 miny
:x2 maxx
:y2 maxy
:width (- maxx minx)
:height (- maxy miny)}))
(when (d/not-empty? selrects)
(let [minx (transduce (keep :x1) min ##Inf selrects)
miny (transduce (keep :y1) min ##Inf selrects)
maxx (transduce (keep :x2) max ##-Inf selrects)
maxy (transduce (keep :y2) max ##-Inf selrects)]
(when (d/num? minx miny maxx maxy)
(make-selrect minx miny (- maxx minx) (- maxy miny))))))
(defn center->rect [center width height]
(assert (gpt/point center))
(assert (and (number? width) (> width 0)))
(assert (and (number? height) (> height 0)))
(defn center->rect [{:keys [x y]} width height]
(when (d/num? x y width height)
(make-rect (- x (/ width 2))
(- y (/ height 2))
width
height)))
{:x (- (:x center) (/ width 2))
:y (- (:y center) (/ height 2))
:width width
:height height})
(defn center->selrect [{:keys [x y]} width height]
(when (d/num? x y width height)
(make-selrect (- x (/ width 2))
(- y (/ height 2))
width
height)))
(defn s=
[a b]

View file

@ -251,7 +251,7 @@
;; to have this width, height, x, y
new-width (max 0.01 (:width points-temp-dim))
new-height (max 0.01 (:height points-temp-dim))
selrect (gco/make-centered-selrect center new-width new-height)
selrect (gpr/center->selrect center new-width new-height)
rect-points (gpr/rect->points selrect)
[matrix matrix-inverse] (calculate-adjust-matrix points-temp rect-points flip-x flip-y)]

View file

@ -395,8 +395,8 @@
srect (gsh/selection-rect shapes)
local (assoc local :vport size :zoom 1)]
(cond
(or (not (mth/finite? (:width srect)))
(not (mth/finite? (:height srect))))
(or (not (d/num? (:width srect)))
(not (d/num? (:height srect))))
(assoc local :vbox (assoc size :x 0 :y 0))
(or (> (:width srect) width)

View file

@ -32,9 +32,7 @@
(defonce default-image {:x 0 :y 0 :width 1 :height 1 :rx 0 :ry 0})
(defn- assert-valid-num [attr num]
(when (or (nil? num)
(mth/nan? num)
(not (mth/finite? num))
(when (or (not (d/num? num))
(>= num max-safe-int )
(<= num min-safe-int))
(ex/raise (str (d/name attr) " attribute invalid: " num)))
@ -229,14 +227,9 @@
(let [points (-> (gsh/rect->points rect-data)
(gsh/transform-points transform))
center (gsh/center-points points)
rect-shape (-> (gsh/make-centered-rect center (:width rect-data) (:height rect-data))
(update :width max 1)
(update :height max 1))
selrect (gsh/rect->selrect rect-shape)
center (gsh/center-points points)
rect-shape (gsh/center->rect center (:width rect-data) (:height rect-data))
selrect (gsh/rect->selrect rect-shape)
rect-points (gsh/rect->points rect-shape)
[shape-transform shape-transform-inv rotation]

View file

@ -181,9 +181,12 @@
:ignore-tree ignore-tree
;; Attributes that can change in the transform. This way we don't have to check
;; all the attributes
:attrs [:selrect :points
:x :y
:width :height
:attrs [:selrect
:points
:x
:y
:width
:height
:content
:transform
:transform-inverse

View file

@ -59,15 +59,14 @@
(defn- calculate-dimensions
[{:keys [objects] :as data} vport]
(let [shapes (cph/get-immediate-children objects)
to-finite (fn [val fallback] (if (not (mth/finite? val)) fallback val))
rect (cond->> (gsh/selection-rect shapes)
(some? vport)
(gal/adjust-to-viewport vport))]
(-> rect
(update :x to-finite 0)
(update :y to-finite 0)
(update :width to-finite 100000)
(update :height to-finite 100000))))
(update :x mth/finite 0)
(update :y mth/finite 0)
(update :width mth/finite 100000)
(update :height mth/finite 100000))))
(declare shape-wrapper-factory)

View file

@ -195,7 +195,7 @@
snap-list (d/concat-vec lt-snap gt-snap between-snap)
min-snap (reduce best-snap ##Inf snap-list)]
(if (mth/finite? min-snap) [0 min-snap] nil)))
(if (d/num? min-snap) [0 min-snap] nil)))
(defn search-snap-distance [selrect coord shapes-lt shapes-gt zoom]
(->> (rx/combine-latest shapes-lt shapes-gt)

View file

@ -28,10 +28,6 @@
min-val (get params :min)
max-val (get params :max)
num? (fn [val] (and (number? val)
(not (mth/nan? val))
(mth/finite? val)))
emit-blur? (mf/use-ref nil)
font-size-wrapper-ref (mf/use-ref)
@ -103,8 +99,8 @@
new-value (+ value increment)
new-value (cond
(and (num? min-val) (< new-value min-val)) min-val
(and (num? max-val) (> new-value max-val)) max-val
(and (d/num? min-val) (< new-value min-val)) min-val
(and (d/num? max-val) (> new-value max-val)) max-val
:else new-value)]
(set-value new-value)))))))

View file

@ -6,9 +6,9 @@
(ns app.main.ui.components.numeric-input
(:require
[app.main.ui.formats :as fmt]
[app.common.data :as d]
[app.common.spec :as us]
[app.main.ui.formats :as fmt]
[app.util.dom :as dom]
[app.util.globals :as globals]
[app.util.keyboard :as kbd]
@ -18,11 +18,6 @@
[rumext.alpha :as mf])
(:import goog.events.EventType))
(defn num? [val]
(and (number? val)
(not (mth/nan? val))
(mth/finite? val)))
(mf/defc numeric-input
{::mf/wrap-props false
::mf/forward-ref true}
@ -81,15 +76,15 @@
(let [input-node (mf/ref-val ref)
new-value (-> (dom/get-value input-node)
(sm/expr-eval value))]
(when (num? new-value)
(when (d/num? new-value)
(-> new-value
(cljs.core/max us/min-safe-int)
(cljs.core/min us/max-safe-int)
(cond->
(num? min-val)
(d/num? min-val)
(cljs.core/max min-val)
(num? max-val)
(d/num? max-val)
(cljs.core/min max-val)))))))
update-input
@ -120,18 +115,18 @@
new-value (+ current-value increment)
new-value (cond
(and wrap-value? (num? max-val) (num? min-val)
(and wrap-value? (d/num? max-val min-val)
(> new-value max-val) up?)
(-> new-value (- max-val) (+ min-val) (- step-val))
(and wrap-value? (num? min-val) (num? max-val)
(and wrap-value? (d/num? max-val min-val)
(< new-value min-val) down?)
(-> new-value (- min-val) (+ max-val) (+ step-val))
(and (num? min-val) (< new-value min-val))
(and (d/num? min-val) (< new-value min-val))
min-val
(and (num? max-val) (> new-value max-val))
(and (d/num? max-val) (> new-value max-val))
max-val
:else new-value)]

View file

@ -7,6 +7,7 @@
(ns app.main.ui.workspace.viewport.gradients
"Gradients handlers and renders"
(:require
[app.common.data :as d]
[app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
@ -300,7 +301,7 @@
(let [scale-factor-y (/ gradient-length (/ height 2))
norm-dist (/ (gpt/distance point from-p)
(* (/ width 2) scale-factor-y))]
(when (and norm-dist (mth/finite? norm-dist))
(when (and norm-dist (d/num? norm-dist))
(change! {:width norm-dist})))))]
(when (and gradient

View file

@ -7,7 +7,6 @@
(ns app.main.ui.workspace.viewport.scroll-bars
(:require
[app.common.geom.shapes :as gsh]
[app.common.geom.shapes.rect :as gpr]
[app.common.pages.helpers :as cph]
[app.main.data.workspace :as dw]
[app.main.store :as st]
@ -169,7 +168,7 @@
:y2 (+ vbox-y (:height vbox))
:width (:width vbox)
:height (:height vbox)}
containing-rect (gpr/join-selrects [base-objects-rect vbox-rect])
containing-rect (gsh/join-selrects [base-objects-rect vbox-rect])
height-factor (/ (:height containing-rect) vbox-height)
width-factor (/ (:width containing-rect) vbox-width)]
(mf/set-ref-val! start-ref start-pt)

View file

@ -6,6 +6,7 @@
(ns app.util.geom.grid
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.math :as mth]))
@ -39,7 +40,7 @@
gutter (if (= :stretch type)
(let [gutter (/ (- width (* width' size) (* margin 2)) (dec size))]
(if (mth/finite? gutter) gutter 0))
(if (d/num? gutter) gutter 0))
gutter)
next-v (fn [cur-val]