Merge pull request #5201 from penpot/niwinz-shape-with-selrect-as-f32-array

 Shape with buffer
This commit is contained in:
Belén Albeza 2024-10-29 13:47:37 +01:00 committed by GitHub
commit fa4f2aa5cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 518 additions and 228 deletions

View file

@ -15,7 +15,6 @@
[app.common.geom.rect :as grc]
[app.common.geom.shapes :as gsh]
[app.common.logic.libraries :as cll]
[app.common.record :as cr]
[app.common.types.component :as ctk]
[app.common.uuid :as uuid]
[app.main.data.changes :as dch]
@ -68,15 +67,15 @@
calculate-selrect
(fn [selrect [delta space?]]
(let [selrect (-> (cr/clone selrect)
(cr/update! :x2 + (:x delta))
(cr/update! :y2 + (:y delta)))
(let [selrect (-> selrect
(update :x2 + (:x delta))
(update :y2 + (:y delta)))
selrect (if ^boolean space?
(-> selrect
(cr/update! :x1 + (:x delta))
(cr/update! :y1 + (:y delta)))
(update :x1 + (:x delta))
(update :y1 + (:y delta)))
selrect)]
(grc/update-rect! selrect :corners)))
(grc/update-rect selrect :corners)))
selrect-stream
(->> ms/mouse-position

View file

@ -6,32 +6,20 @@
(ns app.main.ui.workspace.shapes.common
(:require
[app.common.record :as cr]
[app.main.ui.shapes.shape :refer [shape-container]]
[app.main.ui.workspace.shapes.debug :as wsd]
[rumext.v2 :as mf]))
(def ^:private excluded-attrs
#{:blocked
:hide-fill-on-export
:collapsed
:remote-synced
:exports})
(defn check-shape
[new-shape old-shape]
(cr/-equiv-with-exceptions old-shape new-shape excluded-attrs))
(defn check-shape-props
[np op]
(check-shape (unchecked-get np "shape")
(unchecked-get op "shape")))
(= (unchecked-get np "shape")
(unchecked-get op "shape")))
(defn generic-wrapper-factory
[component]
(mf/fnc generic-wrapper
{::mf/wrap [#(mf/memo' % check-shape-props)]
::mf/wrap-props false}
::mf/props :obj}
[props]
(let [shape (unchecked-get props "shape")]
[:> shape-container {:shape shape}

View file

@ -134,13 +134,13 @@
hover-top-frame-id (mf/use-state nil)
frame-hover (mf/use-state nil)
active-frames (mf/use-state #{})
canvas-init? (mf/use-state false)
;; REFS
[viewport-ref
on-viewport-ref] (create-viewport-ref)
canvas-ref (mf/use-ref nil)
canvas-init (mf/use-ref false)
;; VARS
disable-paste (mf/use-var false)
@ -261,7 +261,8 @@
(= (:layout selected-frame) :flex)
(zero? (:rotation first-shape)))
selecting-first-level-frame? (and single-select? (cfh/root-frame? first-shape))
selecting-first-level-frame?
(and single-select? (cfh/root-frame? first-shape))
offset-x (if selecting-first-level-frame?
(:x first-shape)
@ -280,14 +281,20 @@
(->> render.wasm/module
(p/fmap (fn [ready?]
(when ready?
(mf/set-ref-val! canvas-init true)
(reset! canvas-init? true)
(render.wasm/assign-canvas canvas)))))
(fn []
(render.wasm/clear-canvas))))
(mf/with-effect [vbox' base-objects]
(when (mf/ref-val canvas-init)
(render.wasm/draw-objects base-objects zoom vbox'))))
(mf/with-effect [objects-modified canvas-init?]
(when @canvas-init?
(render.wasm/set-objects objects-modified)
(render.wasm/draw-objects zoom vbox)))
(mf/with-effect [vbox canvas-init?]
(let [frame-id (when @canvas-init? (do
(render.wasm/draw-objects zoom vbox)))]
(partial render.wasm/cancel-draw frame-id))))
(hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool drawing-path?)
(hooks/setup-viewport-size vport viewport-ref)
@ -295,6 +302,8 @@
(hooks/setup-keyboard alt? mod? space? z? shift?)
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected mod? hover measure-hover
hover-ids hover-top-frame-id @hover-disabled? focus zoom show-measures?)
;; FIXME: this should be removed on canvas viewport
(hooks/setup-viewport-modifiers modifiers base-objects)
(hooks/setup-shortcuts node-editing? drawing-path? text-editing? grid-editing?)
(hooks/setup-active-frames base-objects hover-ids selected active-frames zoom transform vbox)

View file

@ -8,44 +8,75 @@
"A WASM based render API"
(:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.types.shape.impl]
[app.config :as cf]
[promesa.core :as p]))
(def enabled?
(contains? cf/flags :render-wasm))
(defonce ^:dynamic internal-module #js {})
(defonce ^:dynamic internal-gpu-state #js {})
(set! app.common.types.shape.impl/enabled-wasm-ready-shape enabled?)
(defn draw-objects [objects zoom vbox]
(let [draw-rect (unchecked-get internal-module "_draw_rect")
translate (unchecked-get internal-module "_translate")
reset-canvas (unchecked-get internal-module "_reset_canvas")
scale (unchecked-get internal-module "_scale")
flush (unchecked-get internal-module "_flush")
gpu-state internal-gpu-state]
(defonce internal-module #js {})
(defonce internal-gpu-state #js {})
;; TODO: remove the `take` once we have the dynamic data structure in Rust
(def xform
(comp
(remove cfh/root?)
(take 2048)))
;; Size in number of f32 values that represents the shape selrect (
(def rect-size 4)
(defn set-objects
[objects]
;; FIXME: maybe change the name of `_shapes_buffer` (?)
(let [get-shapes-buffer-ptr
(unchecked-get internal-module "_shapes_buffer")
heap
(unchecked-get internal-module "HEAPF32")
shapes
(into [] xform (vals objects))
total-shapes
(count shapes)
heap-offset
(get-shapes-buffer-ptr)
heap-size
(* rect-size total-shapes)
mem
(js/Float32Array. (.-buffer heap)
heap-offset
heap-size)]
(loop [index 0]
(when (< index total-shapes)
(let [shape (nth shapes index)]
(.set ^js mem (.-buffer shape) (* index rect-size))
(recur (inc index)))))))
(defn draw-objects
[zoom vbox]
(let [draw-all-shapes (unchecked-get internal-module "_draw_all_shapes")]
(js/requestAnimationFrame
(fn []
(reset-canvas gpu-state)
(scale gpu-state zoom zoom)
(let [pan-x (- (dm/get-prop vbox :x))
pan-y (- (dm/get-prop vbox :y))]
(draw-all-shapes internal-gpu-state zoom pan-x pan-y))))))
(let [x (dm/get-prop vbox :x)
y (dm/get-prop vbox :y)]
(translate gpu-state (- x) (- y)))
(defn cancel-draw
[frame-id]
(when (some? frame-id)
(js/cancelAnimationFrame frame-id)))
(run! (fn [shape]
(let [selrect (dm/get-prop shape :selrect)
x1 (dm/get-prop selrect :x1)
y1 (dm/get-prop selrect :y1)
x2 (dm/get-prop selrect :x2)
y2 (dm/get-prop selrect :y2)]
(draw-rect gpu-state x1 y1 x2 y2)))
(vals objects))
(flush gpu-state)))))
(def canvas-options
(def ^:private canvas-options
#js {:antialias true
:depth true
:stencil true

View file

@ -181,10 +181,12 @@
[state name]
(let [page-id (get state :current-page-id)
objects (get-in state [:workspace-data :pages-index page-id :objects])
result (or (d/seek (fn [[_ shape]] (= name (:name shape))) objects)
result (or (d/seek (fn [shape] (= name (:name shape))) (vals objects))
(get objects (uuid/uuid name)))]
(logjs name result)
nil))
#_(logjs name result)
result
#_nil))
(defn ^:export dump-object
[name]