diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index 084fbbd0f..556b2fde6 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -1730,8 +1730,8 @@ (def start-move-selected transforms/start-move-selected) (def move-selected transforms/move-selected) -(def apply-displacement-in-bulk transforms/apply-displacement-in-bulk) -(def materialize-displacement-in-bulk transforms/materialize-displacement-in-bulk) +(def set-modifiers transforms/set-modifiers) +(def apply-modifiers transforms/apply-modifiers) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Shortcuts diff --git a/frontend/src/uxbox/main/data/workspace/transforms.cljs b/frontend/src/uxbox/main/data/workspace/transforms.cljs index 16a76e83d..ee48b3e21 100644 --- a/frontend/src/uxbox/main/data/workspace/transforms.cljs +++ b/frontend/src/uxbox/main/data/workspace/transforms.cljs @@ -14,20 +14,14 @@ [uxbox.util.geom.matrix :as gmt] [uxbox.main.data.helpers :as helpers] [uxbox.main.data.workspace.common :refer [IBatchedChange IUpdateGroup] :as common])) -;; -- Specs - -(s/def ::set-of-uuid - (s/every uuid? :kind set?)) ;; -- Declarations -(declare assoc-resize-modifier-in-bulk) -(declare apply-displacement-in-bulk) -(declare apply-rotation) +(declare set-modifiers) +(declare set-rotation) +(declare apply-modifiers) -(declare materialize-resize-modifier-in-bulk) -(declare materialize-displacement-in-bulk) -(declare materialize-rotation) +;; -- Helpers (defn- apply-zoom [point] @@ -71,7 +65,7 @@ ;; -- RESIZE (defn start-resize - [vid ids shape objects] + [handler ids shape objects] (letfn [(resize [shape initial [point lock?]] (let [frame (get objects (:frame-id shape)) {:keys [width height rotation]} shape @@ -80,7 +74,7 @@ shapev (-> (gpt/point width height)) ;; Vector modifiers depending on the handler - handler-modif (let [[x y] (handler-modifiers vid)] (gpt/point x y)) + handler-modif (let [[x y] (handler-modifiers handler)] (gpt/point x y)) ;; Difference between the origin point in the coordinate system of the rotation deltav (-> (gpt/subtract point initial) @@ -94,13 +88,13 @@ shape-transform-inverse (:transform-inverse shape (gmt/matrix)) ;; Resize origin point given the selected handler - origin (-> (handler-resize-origin shape vid) + origin (-> (handler-resize-origin shape handler) (geom/transform-shape-point shape shape-transform))] - (rx/of (assoc-resize-modifier-in-bulk ids {:resize-modifier-vector scalev - :resize-modifier-origin origin - :resize-modifier-transform shape-transform - :resize-modifier-transform-inverse shape-transform-inverse})))) + (rx/of (set-modifiers ids {:resize-vector scalev + :resize-origin origin + :resize-transform shape-transform + :resize-transform-inverse shape-transform-inverse})))) ;; Unifies the instantaneous proportion lock modifier ;; activated by Ctrl key and the shapes own proportion @@ -130,64 +124,7 @@ (rx/map normalize-proportion-lock) (rx/mapcat (partial resize shape initial)) (rx/take-until stoper)) - (rx/of (materialize-resize-modifier-in-bulk ids)))))))) - -(defn assoc-resize-modifier-in-bulk - [ids modifiers] - (us/verify ::set-of-uuid ids) - ;; (us/verify gmt/matrix? resize-matrix) - ;; (us/verify gmt/matrix? displacement-matrix) - (ptk/reify ::assoc-resize-modifier-in-bulk - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) - rfn #(-> %1 - (update-in [:workspace-data page-id :objects %2] (fn [item] (merge item modifiers)))) - - not-frame-id? (fn [shape-id] (not (= :frame (:type (get objects shape-id))))) - - ;; TODO: REMOVE FRAMES FROM IDS TO PROPAGATE - ids-with-children (concat ids (mapcat #(helpers/get-children % objects) (filter not-frame-id? ids)))] - (reduce rfn state ids-with-children))))) - -(defn materialize-resize-modifier-in-bulk - [ids] - (ptk/reify ::materialize-resize-modifier-in-bulk - - IUpdateGroup - (get-ids [_] ids) - - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) - - ;; Updates the resize data for a single shape - materialize-shape - (fn [state id] - (update-in state [:workspace-data page-id :objects id] geom/transform-shape)) - - ;; Applies materialize-shape over shape children - materialize-children - (fn [state id] - (reduce materialize-shape state (helpers/get-children id objects))) - - ;; For each shape makes permanent the displacemnt - update-shapes - (fn [state id] - (let [shape (-> (get objects id) geom/transform-shape)] - (-> state - (materialize-shape id) - (materialize-children id))))] - - (reduce update-shapes state ids))) - - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state)] - (rx/of (common/diff-and-commit-changes page-id) - (common/rehash-shape-frame-relationship ids)))))) + (rx/of (apply-modifiers ids)))))))) ;; -- ROTATE @@ -219,12 +156,9 @@ (rx/with-latest vector ms/mouse-position-ctrl) (rx/map (fn [[pos ctrl?]] (let [delta-angle (calculate-angle pos ctrl?)] - (apply-rotation delta-angle shapes)))) - - + (set-rotation delta-angle shapes)))) (rx/take-until stoper)) - (rx/of (materialize-rotation shapes)) - ))))) + (rx/of (apply-modifiers (map :id shapes)))))))) ;; -- MOVE @@ -235,13 +169,16 @@ (let [selected (get-in state [:workspace-local :selected]) stoper (rx/filter ms/mouse-up? stream) zero-point? #(= % (gpt/point 0 0)) + initial (apply-zoom @ms/mouse-position) position @ms/mouse-position] (rx/concat - (->> (ms/mouse-position-deltas position) + (->> ms/mouse-position + (rx/map apply-zoom) (rx/filter (complement zero-point?)) - (rx/map #(apply-displacement-in-bulk selected %)) + (rx/map #(gpt/subtract % initial)) + (rx/map #(set-modifiers selected {:displacement (gmt/translate-matrix %)})) (rx/take-until stoper)) - (rx/of (materialize-displacement-in-bulk selected))))))) + (rx/of (apply-modifiers selected))))))) (defn- get-displacement-with-grid "Retrieve the correct displacement delta point for the @@ -283,81 +220,40 @@ displacement (if align? (get-displacement-with-grid shape direction options) (get-displacement shape direction))] - (rx/of (apply-displacement-in-bulk selected displacement) - (materialize-displacement-in-bulk selected)))))) + (rx/of (set-modifiers selected displacement) + (apply-modifiers selected)))))) ;; -- Apply modifiers -(defn apply-displacement-in-bulk - "Apply the same displacement delta to all shapes identified by the set - if ids." - [ids delta] - (us/verify ::set-of-uuid ids) - (us/verify gpt/point? delta) - (ptk/reify ::apply-displacement-in-bulk - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) - rfn (fn [state id] - (let [path [:workspace-data page-id :objects id] - shape (get-in state path) - prev (:displacement-modifier shape (gmt/matrix)) - curr (gmt/translate prev delta)] - (update-in state path #(assoc % :displacement-modifier curr)))) - ids-with-children (concat ids (mapcat #(helpers/get-children % objects) ids))] - (reduce rfn state ids-with-children))))) +(defn set-modifiers + ([ids modifiers] (set-modifiers ids modifiers true)) + ([ids modifiers recurse-frames?] + (us/verify (s/coll-of uuid?) ids) + (ptk/reify ::set-modifiers + ptk/UpdateEvent + (update [_ state] + (let [page-id (:current-page-id state) + objects (get-in state [:workspace-data page-id :objects]) + not-frame-id? (fn [shape-id] + (let [shape (get objects shape-id)] + (or recurse-frames? (not (= :frame (:type shape)))))) -(defn materialize-displacement-in-bulk - [ids] - (ptk/reify ::materialize-displacement-in-bulk - IBatchedChange - - IUpdateGroup - (get-ids [_] ids) + ;; ID's + Children but remove frame children if the flag is set to false + ids-with-children (concat ids (mapcat #(helpers/get-children % objects) (filter not-frame-id? ids))) - ptk/UpdateEvent - (update [_ state] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) + ;; For each shape updates the modifiers given as arguments + update-shape (fn [state shape-id] + (update-in + state + [:workspace-data page-id :objects shape-id :modifiers] + #(merge % modifiers)))] + (reduce update-shape state ids-with-children)))))) - ;; Updates the displacement data for a single shape - materialize-shape - (fn [state id mtx] - (update-in - state - [:workspace-data page-id :objects id] - #(-> % - (dissoc :displacement-modifier) - (geom/transform mtx)))) - - ;; Applies materialize-shape over shape children - materialize-children - (fn [state id mtx] - (reduce #(materialize-shape %1 %2 mtx) state (helpers/get-children id objects))) - - ;; For each shape makes permanent the resize - update-shapes - (fn [state id] - (let [shape (get objects id) - mtx (:displacement-modifier shape (gmt/matrix))] - (-> state - (materialize-shape id mtx) - (materialize-children id mtx))))] - - (as-> state $ - (reduce update-shapes $ ids)))) - - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state)] - (rx/of (common/diff-and-commit-changes page-id) - (common/rehash-shape-frame-relationship ids)))))) - -(defn apply-rotation +;; Set-rotation is custom because applies different modifiers to each shape adjusting their position +(defn set-rotation [delta-rotation shapes] - (ptk/reify ::apply-rotation + (ptk/reify ::set-rotation ptk/UpdateEvent (update [_ state] (let [page-id (:current-page-id state)] @@ -369,11 +265,11 @@ (rotate-shape [state angle shape center] (let [objects (get-in state [:workspace-data page-id :objects]) - path [:workspace-data page-id :objects (:id shape)] + path [:workspace-data page-id :objects (:id shape) :modifiers] ds (calculate-displacement shape angle center)] (-> state - (assoc-in (conj path :rotation-modifier) angle) - (assoc-in (conj path :displacement-modifier) ds)))) + (assoc-in (conj path :rotation) angle) + (assoc-in (conj path :displacement) ds)))) (rotate-around-center [state angle center shapes] @@ -386,25 +282,30 @@ shapes (concat shapes (mapcat get-children shapes))] (rotate-around-center state delta-rotation center shapes))))))) -(defn materialize-rotation - [shapes] - (ptk/reify ::materialize-rotation - IBatchedChange +(defn apply-modifiers + [ids] + (us/verify (s/coll-of uuid?) ids) + (ptk/reify ::apply-modifiers IUpdateGroup - (get-ids [_] (map :id shapes)) + (get-ids [_] ids) ptk/UpdateEvent (update [_ state] - (letfn - [(materialize-shape [state shape] - (let [page-id (:current-page-id state) - objects (get-in state [:workspace-data page-id :objects]) - path [:workspace-data page-id :objects (:id shape)]] - (as-> state $ - (update-in $ path geom/transform-shape) - (reduce materialize-shape $ (map #(get objects %) (:shapes shape))))))] + (let [page-id (:current-page-id state) + objects (get-in state [:workspace-data page-id :objects]) - (reduce materialize-shape state shapes))))) + ;; ID's + Children + ids-with-children (concat ids (mapcat #(helpers/get-children % objects) ids)) + ;; For each shape applies the modifiers by transforming the objects + update-shape + (fn [state shape-id] + (update-in state [:workspace-data page-id :objects shape-id] geom/transform-shape))] + (reduce update-shape state ids-with-children))) + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state)] + (rx/of (common/diff-and-commit-changes page-id) + (common/rehash-shape-frame-relationship ids)))))) diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index 448f0b7b0..25bad9db1 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -679,12 +679,13 @@ (defn- transform-apply-modifiers [shape] - (let [ds-modifier (:displacement-modifier shape (gmt/matrix)) - resize (:resize-modifier-vector shape (gpt/point 1 1)) - origin (:resize-modifier-origin shape (gpt/point 0 0)) - resize-transform (:resize-modifier-transform shape (gmt/matrix)) - resize-transform-inverse (:resize-modifier-transform-inverse shape (gmt/matrix)) - rt-modif (:rotation-modifier shape 0) + (let [modifiers (:modifiers shape) + ds-modifier (:displacement modifiers (gmt/matrix)) + resize (:resize-vector modifiers (gpt/point 1 1)) + origin (:resize-origin modifiers (gpt/point 0 0)) + resize-transform (:resize-transform modifiers (gmt/matrix)) + resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix)) + rt-modif (:rotation modifiers 0) shape (-> shape (transform ds-modifier)) @@ -734,15 +735,6 @@ (translate-to-frame frame) (shape->rect-shape))) -(defn dissoc-modifiers [shape] - (-> shape - (dissoc :rotation-modifier) - (dissoc :displacement-modifier) - (dissoc :resize-modifier) - (dissoc :resize-modifier-vector) - (dissoc :resize-modifier-origin) - (dissoc :resize-modifier-rotation))) - (defn transform-rect-shape [shape] (let [;; Apply modifiers to the rect as a path so we have the end shape expected @@ -813,8 +805,8 @@ (transform-rect-shape shape))] (-> new-shape (translate-to-frame frame) - (update :rotation #(mod (+ % (:rotation-modifier shape)) 360)) - (dissoc-modifiers))))) + (update :rotation #(mod (+ % (get-in shape [:modifiers :rotation] 0)) 360)) + (dissoc :modifiers))))) (defn transform-matrix diff --git a/frontend/src/uxbox/main/ui/workspace/drawarea.cljs b/frontend/src/uxbox/main/ui/workspace/drawarea.cljs index 2deab4f54..36e78f0d2 100644 --- a/frontend/src/uxbox/main/ui/workspace/drawarea.cljs +++ b/frontend/src/uxbox/main/ui/workspace/drawarea.cljs @@ -123,9 +123,9 @@ scalev (gpt/divide (gpt/add shapev deltav) shapev)] (-> shape - (assoc :resize-modifier-vector scalev) - (assoc :resize-modifier-origin (gpt/point x y)) - (assoc :resize-modifier-rotation 0)))) + (assoc-in [:modifiers :resize-vector] scalev) + (assoc-in [:modifiers :resize-origin] (gpt/point x y)) + (assoc-in [:modifiers :resize-rotation] 0)))) (update-drawing [state initial point lock?] (update-in state [:workspace-local :drawing] resize-shape initial point lock?))] @@ -273,11 +273,11 @@ (rx/of dw/clear-drawing) (when (::initialized? shape) (let [shape (-> shape - (geom/transform-shape) - (dissoc shape ::initialized?))] - ;; Add & select the created shape to the workspace - (rx/of dw/deselect-all - (dw/add-shape shape))))))))) + (geom/transform-shape) + (dissoc shape ::initialized?))] + ;; Add & select the created shape to the workspace + (rx/of dw/deselect-all + (dw/add-shape shape))))))))) (def close-drawing-path (ptk/reify ::close-drawing-path diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs index f8e4a50e0..59069a8e6 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/frame.cljs @@ -64,8 +64,10 @@ delta (if (= attr :x) (gpt/point (math/neg (- pval cval)) 0) (gpt/point 0 (math/neg (- pval cval))))] - (st/emit! (udw/apply-displacement-in-bulk #{(:id shape)} delta) - (udw/materialize-displacement-in-bulk #{(:id shape)})))) + + ;; TODO: Change so not apply the modifiers until blur + (st/emit! (udw/set-modifiers #{(:id shape)} {:displacement delta}) + (udw/apply-modifiers #{(:id shape)})))) on-width-change #(on-size-change % :width) on-height-change #(on-size-change % :height)