diff --git a/frontend/src/app/main/ui/workspace/shapes.cljs b/frontend/src/app/main/ui/workspace/shapes.cljs index 0b561e58aa..ec3fb5d5ca 100644 --- a/frontend/src/app/main/ui/workspace/shapes.cljs +++ b/frontend/src/app/main/ui/workspace/shapes.cljs @@ -31,6 +31,7 @@ [app.main.ui.workspace.shapes.path :as path] [app.main.ui.workspace.shapes.text :as text] [app.util.object :as obj] + [app.util.debug :refer [debug?]] [beicon.core :as rx] [okulary.core :as l] [rumext.alpha :as mf])) @@ -44,15 +45,17 @@ (defn- shape-wrapper-memo-equals? [np op] - (let [n-shape (obj/get np "shape") - o-shape (obj/get op "shape") - n-frame (obj/get np "frame") - o-frame (obj/get op "frame")] - ;; (prn "shape-wrapper-memo-equals?" (identical? n-frame o-frame)) + (let [n-shape (obj/get np "shape")] (if (= (:type n-shape) :group) false - (and (identical? n-shape o-shape) - (identical? n-frame o-frame))))) + (let [o-shape (obj/get op "shape") + n-frame (obj/get np "frame") + o-frame (obj/get op "frame") + n-ghost (obj/get np "ghost?") + o-ghost (obj/get op "ghost?")] + (and (identical? n-shape o-shape) + (identical? n-frame o-frame) + (identical? n-ghost o-ghost)))))) (defn make-is-moving-ref [id] @@ -94,7 +97,9 @@ ;; Only used when drawing a new frame. :frame [:> frame-wrapper {:shape shape}] nil) - [:& bounding-box {:shape shape :frame frame}]]))) + + (when (debug? :bounding-boxes) + [:& bounding-box {:shape shape :frame frame}])]))) (def group-wrapper (group/group-wrapper-factory shape-wrapper)) (def frame-wrapper (frame/frame-wrapper-factory shape-wrapper)) diff --git a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs index 10edd1b2bd..dc3597a949 100644 --- a/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/bounding_box.cljs @@ -44,7 +44,7 @@ :fill "transparent" :stroke-width "1px" :stroke-opacity 0.5 - :stroke-dasharray 4 + :stroke-dasharray 4 :pointer-events "none"}}]) (mf/defc render-rect-points [{:keys [points color]}] @@ -59,37 +59,36 @@ (mf/defc bounding-box {::mf/wrap-props false} [props] - (when (debug? :bounding-boxes) - (let [shape (-> (unchecked-get props "shape")) - frame (unchecked-get props "frame") - selrect (gsh/points->selrect (-> shape :points)) - shape-center (gsh/center-shape shape) - line-color (rdcolor #js {:seed (str (:id shape))}) - zoom (mf/deref refs/selected-zoom) - childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) - childs (->> (mf/deref childs-ref) - (map gsh/transform-shape))] + (let [shape (-> (unchecked-get props "shape")) + frame (unchecked-get props "frame") + selrect (gsh/points->selrect (-> shape :points)) + shape-center (gsh/center-shape shape) + line-color (rdcolor #js {:seed (str (:id shape))}) + zoom (mf/deref refs/selected-zoom) + childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) + childs (->> (mf/deref childs-ref) + (map gsh/transform-shape))] - [:g.bounding-box - [:text {:x (:x selrect) - :y (- (:y selrect) 5) - :font-size 10 - :fill line-color - :stroke "white" - :stroke-width 0.1} - (str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x shape)) (fixed (:y shape)))] + [:g.bounding-box + [:text {:x (:x selrect) + :y (- (:y selrect) 5) + :font-size 10 + :fill line-color + :stroke "white" + :stroke-width 0.1} + (str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x shape)) (fixed (:y shape)))] - [:& cross-point {:point shape-center + [:& cross-point {:point shape-center + :zoom zoom + :color line-color}] + + (for [point (:points shape)] + [:& cross-point {:point point :zoom zoom - :color line-color}] + :color line-color}]) - (for [point (:points shape)] - [:& cross-point {:point point - :zoom zoom - :color line-color}]) + [:& render-rect-points {:rect selrect + :color line-color}] - [:& render-rect-points {:rect selrect - :color line-color}] - - [:& render-rect {:rect selrect - :color line-color}]]))) + [:& render-rect {:rect selrect + :color line-color}]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index a2a0965e4c..5cb09f50bf 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -68,10 +68,10 @@ (mf/defc frame-title [{:keys [frame]}] - (let [zoom (mf/deref refs/selected-zoom) - {:keys [width x y]} frame - label-pos (gpt/point x (- y (/ 10 zoom))) - handle-click (use-select-shape frame) + (let [{:keys [width x y]} frame + zoom (mf/deref refs/selected-zoom) + label-pos (gpt/point x (- y (/ 10 zoom))) + handle-click (use-select-shape frame) handle-pointer-enter (we/use-pointer-enter frame) handle-pointer-leave (we/use-pointer-leave frame)] [:text {:x 0 @@ -92,33 +92,47 @@ (contains? (:selected local) id)))] (l/derived check-moving refs/workspace-local))) +;; This custom deffered don't deffer rendering when ghost rendering is +;; used. +(defn custom-deferred + [component] + (mf/fnc deferred + {::mf/wrap-props false} + [props] + (let [tmp (mf/useState false) + ^boolean render? (aget tmp 0) + ^js set-render (aget tmp 1)] + (mf/use-layout-effect (fn [] (ts/schedule-on-idle #(set-render true)))) + (if (unchecked-get props "ghost?") + (mf/create-element component props) + (when render? (mf/create-element component props)))))) + (defn frame-wrapper-factory [shape-wrapper] (let [frame-shape (frame/frame-shape shape-wrapper)] (mf/fnc frame-wrapper - {::mf/wrap [#(mf/memo' % frame-wrapper-factory-equals?) - #(mf/deferred % ts/schedule-on-idle)] + {::mf/wrap [#(mf/memo' % frame-wrapper-factory-equals?) custom-deferred] ::mf/wrap-props false} [props] (let [shape (unchecked-get props "shape") objects (unchecked-get props "objects") - ghost? (unchecked-get props "ghost?") + ghost? (unchecked-get props "ghost?") - moving-iref (mf/use-memo (mf/deps (:id shape)) - #(make-is-moving-ref (:id shape))) - moving? (mf/deref moving-iref) + moving-iref (mf/use-memo (mf/deps (:id shape)) + #(make-is-moving-ref (:id shape))) + moving? (mf/deref moving-iref) selected-iref (mf/use-memo (mf/deps (:id shape)) #(refs/make-selected-ref (:id shape))) - selected? (mf/deref selected-iref) + selected? (mf/deref selected-iref) - shape (gsh/transform-shape shape) - children (mapv #(get objects %) (:shapes shape)) - ds-modifier (get-in shape [:modifiers :displacement]) + shape (gsh/transform-shape shape) + children (mapv #(get objects %) (:shapes shape)) + ds-modifier (get-in shape [:modifiers :displacement]) handle-context-menu (we/use-context-menu shape) handle-double-click (use-select-shape shape) - handle-mouse-down (we/use-mouse-down shape)] + handle-mouse-down (we/use-mouse-down shape)] (when (and shape (or ghost? (not moving?)) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 1e09132cd2..8747752a3e 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -167,6 +167,7 @@ shapes (if ids (->> ids (map #(get objects %))) shapes)] + [:* [:g.shapes (for [item shapes] diff --git a/frontend/src/app/util/debug.cljs b/frontend/src/app/util/debug.cljs index b1787add2e..bb50852937 100644 --- a/frontend/src/app/util/debug.cljs +++ b/frontend/src/app/util/debug.cljs @@ -16,7 +16,11 @@ (defn debug! [option] (swap! *debug* conj option)) (defn -debug! [option] (swap! *debug* disj option)) -(defn ^:export debug? [option] (@*debug* option)) +(defn ^:export ^boolean debug? + [option] + (if *assert* + (boolean (@*debug* option)) + false)) (defn ^:export toggle-debug [name] (let [option (keyword name)] (if (debug? option) @@ -28,7 +32,7 @@ (defn ^:export tap "Transducer function that can execute a side-effect `effect-fn` per input" [effect-fn] - + (fn [rf] (fn ([] (rf)) diff --git a/frontend/src/app/util/perf.cljs b/frontend/src/app/util/perf.cljs index 1a7c431607..419aa57d54 100644 --- a/frontend/src/app/util/perf.cljs +++ b/frontend/src/app/util/perf.cljs @@ -27,16 +27,6 @@ ;; percentiles of render time measures. The log function is ;; automatically debouced for avod excesive spam to the console. -;; #?(:clj -;; (defmacro with-measure -;; [name & body] -;; `(let [start# (js/performance.now) -;; res# (do ~@body) -;; end# (js/performance.now) -;; time# (.toFixed (- end# start#) 2)] -;; (println (str "[perf|" ~name "] => " time#)) -;; res#))) - (defn tdigest [] (specify! (td/TDigest.) @@ -111,7 +101,7 @@ (mf/deps label) #(on-render-factory label))] (if enabled? - [:> react/Profiler {:id label - :on-render on-render} + [:> react/Profiler #js {:id label + :onRender on-render} children] children)))