diff --git a/frontend/src/app/main/data/workspace/drawing.cljs b/frontend/src/app/main/data/workspace/drawing.cljs index 8aa948a42..aeff2af30 100644 --- a/frontend/src/app/main/data/workspace/drawing.cljs +++ b/frontend/src/app/main/data/workspace/drawing.cljs @@ -57,13 +57,13 @@ (watch [_ state stream] (rx/of (case type :path - path/handle-drawing-path + (path/handle-drawing-path) :curve - curve/handle-drawing-curve + (curve/handle-drawing-curve) ;; default - box/handle-drawing-box))))) + (box/handle-drawing-box)))))) ;; Export (def close-drawing-path path/close-drawing-path) diff --git a/frontend/src/app/main/data/workspace/drawing/box.cljs b/frontend/src/app/main/data/workspace/drawing/box.cljs index 74810d9b7..35e84e278 100644 --- a/frontend/src/app/main/data/workspace/drawing/box.cljs +++ b/frontend/src/app/main/data/workspace/drawing/box.cljs @@ -20,72 +20,72 @@ [app.main.streams :as ms] [app.main.data.workspace.drawing.common :as common])) -(def handle-drawing-box - (letfn [(resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] - (let [;; The new shape behaves like a resize on the bottom-right corner - initial (gpt/point (+ x width) (+ y height)) - shapev (gpt/point width height) - deltav (gpt/to-vec initial point-snap) - scalev (gpt/divide (gpt/add shapev deltav) shapev) - scalev (if lock? - (let [v (max (:x scalev) (:y scalev))] - (gpt/point v v)) - 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)))) +(defn resize-shape [{:keys [x y width height] :as shape} point lock? point-snap] + (let [;; The new shape behaves like a resize on the bottom-right corner + initial (gpt/point (+ x width) (+ y height)) + shapev (gpt/point width height) + deltav (gpt/to-vec initial point-snap) + scalev (gpt/divide (gpt/add shapev deltav) shapev) + scalev (if lock? + (let [v (max (:x scalev) (:y scalev))] + (gpt/point v v)) + 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)))) - (update-drawing [state point lock? point-snap] - (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap))] +(defn update-drawing [state point lock? point-snap] + (update-in state [:workspace-drawing :object] resize-shape point lock? point-snap)) - (ptk/reify ::handle-drawing-box - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) +(defn handle-drawing-box [] + (ptk/reify ::handle-drawing-box + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) - stoper? #(or (ms/mouse-up? %) (= % :interrupt)) - stoper (rx/filter stoper? stream) - initial @ms/mouse-position + stoper? #(or (ms/mouse-up? %) (= % :interrupt)) + stoper (rx/filter stoper? stream) + initial @ms/mouse-position - page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - layout (get state :workspace-layout) + page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + layout (get state :workspace-layout) - frames (cph/select-frames objects) - fid (or (->> frames - (filter #(gsh/has-point? % initial)) - first - :id) - uuid/zero) + frames (cph/select-frames objects) + fid (or (->> frames + (filter #(gsh/has-point? % initial)) + first + :id) + uuid/zero) - shape (-> state - (get-in [:workspace-drawing :object]) - (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) - (assoc :frame-id fid) - (assoc :initialized? true) - (assoc :click-draw? true))] - (rx/concat - ;; Add shape to drawing state - (rx/of #(assoc-in state [:workspace-drawing :object] shape)) + shape (-> state + (get-in [:workspace-drawing :object]) + (gsh/setup {:x (:x initial) :y (:y initial) :width 1 :height 1}) + (assoc :frame-id fid) + (assoc :initialized? true) + (assoc :click-draw? true))] + (rx/concat + ;; Add shape to drawing state + (rx/of #(assoc-in state [:workspace-drawing :object] shape)) - ;; Initial SNAP - (->> (snap/closest-snap-point page-id [shape] layout initial) - (rx/map (fn [{:keys [x y]}] - #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) + ;; Initial SNAP + (->> (snap/closest-snap-point page-id [shape] layout initial) + (rx/map (fn [{:keys [x y]}] + #(update-in % [:workspace-drawing :object] assoc :x x :y y)))) - (->> ms/mouse-position - (rx/filter #(> (gpt/distance % initial) 2)) - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/switch-map - (fn [[point :as current]] - (->> (snap/closest-snap-point page-id [shape] layout point) - (rx/map #(conj current %))))) - (rx/map - (fn [[pt ctrl? point-snap]] - #(update-drawing % pt ctrl? point-snap))) + (->> ms/mouse-position + (rx/filter #(> (gpt/distance % initial) 2)) + (rx/with-latest vector ms/mouse-position-ctrl) + (rx/switch-map + (fn [[point :as current]] + (->> (snap/closest-snap-point page-id [shape] layout point) + (rx/map #(conj current %))))) + (rx/map + (fn [[pt ctrl? point-snap]] + #(update-drawing % pt ctrl? point-snap))) - (rx/take-until stoper)) - (rx/of common/handle-finish-drawing))))))) + (rx/take-until stoper)) + (rx/of common/handle-finish-drawing)))))) diff --git a/frontend/src/app/main/data/workspace/drawing/curve.cljs b/frontend/src/app/main/data/workspace/drawing/curve.cljs index c0685383b..5053d79fd 100644 --- a/frontend/src/app/main/data/workspace/drawing/curve.cljs +++ b/frontend/src/app/main/data/workspace/drawing/curve.cljs @@ -18,34 +18,34 @@ (def simplify-tolerance 0.3) -(def handle-drawing-curve - (letfn [(stoper-event? [{:keys [type shift] :as event}] - (ms/mouse-event? event) (= type :up)) +(defn stoper-event? [{:keys [type shift] :as event}] + (ms/mouse-event? event) (= type :up)) - (initialize-drawing [state] - (assoc-in state [:workspace-drawing :object :initialized?] true)) +(defn initialize-drawing [state] + (assoc-in state [:workspace-drawing :object :initialized?] true)) - (insert-point-segment [state point] - (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) +(defn insert-point-segment [state point] + (update-in state [:workspace-drawing :object :segments] (fnil conj []) point)) - (finish-drawing-curve [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] - (-> shape - (update :segments #(path/simplify % simplify-tolerance)) - (gsh/update-path-selrect)))))] +(defn finish-drawing-curve [state] + (update-in + state [:workspace-drawing :object] + (fn [shape] + (-> shape + (update :segments #(path/simplify % simplify-tolerance)) + (gsh/update-path-selrect))))) - (ptk/reify ::handle-drawing-curve - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - stoper (rx/filter stoper-event? stream) - mouse (rx/sample 10 ms/mouse-position)] - (rx/concat - (rx/of initialize-drawing) - (->> mouse - (rx/map (fn [pt] #(insert-point-segment % pt))) - (rx/take-until stoper)) - (rx/of finish-drawing-curve - common/handle-finish-drawing))))))) +(defn handle-drawing-curve [] + (ptk/reify ::handle-drawing-curve + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) + stoper (rx/filter stoper-event? stream) + mouse (rx/sample 10 ms/mouse-position)] + (rx/concat + (rx/of initialize-drawing) + (->> mouse + (rx/map (fn [pt] #(insert-point-segment % pt))) + (rx/take-until stoper)) + (rx/of finish-drawing-curve + common/handle-finish-drawing)))))) diff --git a/frontend/src/app/main/data/workspace/drawing/path.cljs b/frontend/src/app/main/data/workspace/drawing/path.cljs index e1430b83f..3d92288fc 100644 --- a/frontend/src/app/main/data/workspace/drawing/path.cljs +++ b/frontend/src/app/main/data/workspace/drawing/path.cljs @@ -17,97 +17,115 @@ [app.util.geom.path :as path] [app.main.data.workspace.drawing.common :as common])) -(def handle-drawing-path - (letfn [(stoper-event? [{:keys [type shift] :as event}] - (or (= event ::end-path-drawing) - (= event :interrupt) - (and (ms/mouse-event? event) - (or (= type :double-click) - (= type :context-menu))) - (and (ms/keyboard-event? event) - (= type :down) - (= 13 (:key event))))) +(defn stoper-event? [{:keys [type shift] :as event}] + (or (= event ::end-path-drawing) + (= event :interrupt) + (and (ms/mouse-event? event) + (or (= type :double-click) + (= type :context-menu))) + (and (ms/keyboard-event? event) + (= type :down) + (= 13 (:key event))))) - (initialize-drawing [state point] - (-> state - (assoc-in [:workspace-drawing :object :segments] [point point]) - (assoc-in [:workspace-drawing :object :initialized?] true))) +(defn init-path [] + (fn [state] + (update-in state [:workspace-drawing :object] + assoc :content [] + :initialized? true))) - (insert-point-segment [state point] - (-> state - (update-in [:workspace-drawing :object :segments] (fnil conj []) point))) +(defn add-path-command [command] + (fn [state] + (update-in state [:workspace-drawing :object :content] conj command))) - (update-point-segment [state index point] - (let [segments (count (get-in state [:workspace-drawing :object :segments])) - exists? (< -1 index segments)] - (cond-> state - exists? (assoc-in [:workspace-drawing :object :segments index] point)))) +#_(defn update-point-segment [state index point] + (let [segments (count (get-in state [:workspace-drawing :object :segments])) + exists? (< -1 index segments)] + (cond-> state + exists? (assoc-in [:workspace-drawing :object :segments index] point)))) - (finish-drawing-path [state] - (update-in - state [:workspace-drawing :object] - (fn [shape] (-> shape - (update :segments #(vec (butlast %))) - (gsh/update-path-selrect)))))] +(defn finish-drawing-path [] + (fn [state] + (update-in + state [:workspace-drawing :object] + (fn [shape] (-> shape + (update :segments #(vec (butlast %))) + (gsh/update-path-selrect)))))) - (ptk/reify ::handle-drawing-path - ptk/WatchEvent - (watch [_ state stream] - (let [{:keys [flags]} (:workspace-local state) - last-point (volatile! @ms/mouse-position) +(defn handle-drawing-path [] - stoper (->> (rx/filter stoper-event? stream) - (rx/share)) + (ptk/reify ::handle-drawing-path + ptk/WatchEvent + (watch [_ state stream] - mouse (rx/sample 10 ms/mouse-position) + ;; clicks stream<[MouseEvent, Position]> + clicks (->> stream + (rx/filter ms/mouse-click?) + (rx/with-latest vector ms/mouse-position)) - points (->> stream - (rx/filter ms/mouse-click?) - (rx/filter #(false? (:shift %))) - (rx/with-latest vector mouse) - (rx/map second)) + - counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) + ))) - stream' (->> mouse - (rx/with-latest vector ms/mouse-position-ctrl) - (rx/with-latest vector counter) - (rx/map flatten)) +#_(def handle-drawing-path + (ptk/reify ::handle-drawing-path + ptk/WatchEvent + (watch [_ state stream] + (let [{:keys [flags]} (:workspace-local state) - imm-transform #(vector (- % 7) (+ % 7) %) - immanted-zones (vec (concat - (map imm-transform (range 0 181 15)) - (map (comp imm-transform -) (range 0 181 15)))) + last-point (volatile! @ms/mouse-position) - align-position (fn [angle pos] - (reduce (fn [pos [a1 a2 v]] - (if (< a1 angle a2) - (reduced (gpt/update-angle pos v)) - pos)) - pos - immanted-zones))] + stoper (->> (rx/filter stoper-event? stream) + (rx/share)) - (rx/merge - (rx/of #(initialize-drawing % @last-point)) + mouse (rx/sample 10 ms/mouse-position) - (->> points - (rx/take-until stoper) - (rx/map (fn [pt] #(insert-point-segment % pt)))) + points (->> stream + (rx/filter ms/mouse-click?) + (rx/filter #(false? (:shift %))) + (rx/with-latest vector mouse) + (rx/map second)) - (rx/concat - (->> stream' - (rx/take-until stoper) - (rx/map (fn [[point ctrl? index :as xxx]] - (let [point (if ctrl? - (as-> point $ - (gpt/subtract $ @last-point) - (align-position (gpt/angle $) $) - (gpt/add $ @last-point)) - point)] - #(update-point-segment % index point))))) - (rx/of finish-drawing-path - common/handle-finish-drawing)))))))) + counter (rx/merge (rx/scan #(inc %) 1 points) (rx/of 1)) + + stream' (->> mouse + (rx/with-latest vector ms/mouse-position-ctrl) + (rx/with-latest vector counter) + (rx/map flatten)) + + imm-transform #(vector (- % 7) (+ % 7) %) + immanted-zones (vec (concat + (map imm-transform (range 0 181 15)) + (map (comp imm-transform -) (range 0 181 15)))) + + align-position (fn [angle pos] + (reduce (fn [pos [a1 a2 v]] + (if (< a1 angle a2) + (reduced (gpt/update-angle pos v)) + pos)) + pos + immanted-zones))] + + (rx/merge + (rx/of #(initialize-drawing % @last-point)) + + (->> points + (rx/take-until stoper) + (rx/map (fn [pt] #(insert-point-segment % pt)))) + + (rx/concat + (->> stream' + (rx/take-until stoper) + (rx/map (fn [[point ctrl? index :as xxx]] + (let [point (if ctrl? + (as-> point $ + (gpt/subtract $ @last-point) + (align-position (gpt/angle $) $) + (gpt/add $ @last-point)) + point)] + #(update-point-segment % index point))))) + (rx/of finish-drawing-path + common/handle-finish-drawing))))))) (defn close-drawing-path [] (ptk/reify ::close-drawing-path diff --git a/frontend/src/app/main/streams.cljs b/frontend/src/app/main/streams.cljs index cc5c720c9..af90f2b93 100644 --- a/frontend/src/app/main/streams.cljs +++ b/frontend/src/app/main/streams.cljs @@ -26,6 +26,11 @@ [v] (instance? MouseEvent v)) +(defn mouse-down? + [v] + (and (mouse-event? v) + (= :down (:type v)))) + (defn mouse-up? [v] (and (mouse-event? v)