mirror of
https://github.com/penpot/penpot.git
synced 2025-08-02 14:28:23 +02:00
🎉 Save shape data in rust memory
This commit is contained in:
parent
48909dc3c4
commit
65ee2f9081
13 changed files with 479 additions and 297 deletions
|
@ -10,6 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.logic.shapes :as cls]
|
||||
[app.common.types.shape.impl :as shape.impl]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.shape.radius :as ctsr]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
|
@ -248,19 +249,20 @@
|
|||
(fn [value attr]
|
||||
(let [token-value (wtc/maybe-resolve-token-value value)
|
||||
undo-id (js/Symbol)]
|
||||
(if-not design-tokens?
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(udw/update-dimensions ids attr (or token-value value)))
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(dwsh/update-shapes ids
|
||||
(if token-value
|
||||
#(assoc-in % [:applied-tokens attr] (:id value))
|
||||
#(d/dissoc-in % [:applied-tokens attr]))
|
||||
{:reg-objects? true
|
||||
:attrs [:applied-tokens]})
|
||||
(udw/update-dimensions ids attr (or token-value value))
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
(binding [shape.impl/*wasm-sync* true]
|
||||
(if-not design-tokens?
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(udw/update-dimensions ids attr (or token-value value)))
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(dwsh/update-shapes ids
|
||||
(if token-value
|
||||
#(assoc-in % [:applied-tokens attr] (:id value))
|
||||
#(d/dissoc-in % [:applied-tokens attr]))
|
||||
{:reg-objects? true
|
||||
:attrs [:applied-tokens]})
|
||||
(udw/update-dimensions ids attr (or token-value value))
|
||||
(dwu/commit-undo-transaction undo-id)))))))
|
||||
|
||||
on-proportion-lock-change
|
||||
(mf/use-fn
|
||||
|
@ -283,7 +285,8 @@
|
|||
(mf/deps ids)
|
||||
(fn [value attr]
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
||||
(doall (map #(do-position-change %1 %2 value attr) shapes frames))))
|
||||
(binding [shape.impl/*wasm-sync* true]
|
||||
(doall (map #(do-position-change %1 %2 value attr) shapes frames)))))
|
||||
|
||||
;; ROTATION
|
||||
|
||||
|
@ -291,8 +294,9 @@
|
|||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [value]
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(udw/increase-rotation ids value))))
|
||||
(binding [shape.impl/*wasm-sync* true]
|
||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||
(udw/increase-rotation ids value)))))
|
||||
|
||||
;; RADIUS
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.impl :as shape.impl]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.features :as features]
|
||||
|
@ -111,10 +112,9 @@
|
|||
modifiers (mf/deref refs/workspace-modifiers)
|
||||
text-modifiers (mf/deref refs/workspace-text-modifier)
|
||||
|
||||
render-context-lost? (mf/deref refs/render-context-lost?)
|
||||
|
||||
objects-modified (mf/with-memo [base-objects text-modifiers modifiers]
|
||||
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
|
||||
(binding [shape.impl/*wasm-sync* true]
|
||||
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers)))
|
||||
|
||||
selected-shapes (keep (d/getf objects-modified) selected)
|
||||
|
||||
|
@ -177,8 +177,6 @@
|
|||
|
||||
mode-inspect? (= options-mode :inspect)
|
||||
|
||||
on-render-restore-context #(.reload js/location)
|
||||
|
||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect z?)
|
||||
on-context-menu (actions/on-context-menu hover hover-ids read-only?)
|
||||
on-double-click (actions/on-double-click hover hover-ids hover-top-frame-id drawing-path? base-objects edition drawing-tool z? read-only?)
|
||||
|
@ -281,18 +279,18 @@
|
|||
(p/fmap (fn [ready?]
|
||||
(when ready?
|
||||
(reset! canvas-init? true)
|
||||
(render.wasm/setup-canvas canvas)))))
|
||||
(render.wasm/assign-canvas canvas)))))
|
||||
(fn []
|
||||
(render.wasm/dispose-canvas canvas))))
|
||||
(render.wasm/clear-canvas))))
|
||||
|
||||
(mf/with-effect [objects-modified canvas-init?]
|
||||
(mf/with-effect [base-objects modifiers canvas-init?]
|
||||
(when @canvas-init?
|
||||
(render.wasm/set-objects objects-modified)
|
||||
;; FIXME: review this to not call it but still do the first draw
|
||||
;; (render.wasm/set-objects base-objects modifiers)
|
||||
(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)))]
|
||||
(let [frame-id (when @canvas-init? (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?)
|
||||
|
@ -639,11 +637,4 @@
|
|||
{:objects base-objects
|
||||
:zoom zoom
|
||||
:vbox vbox
|
||||
:bottom-padding (when palete-size (+ palete-size 8))}]]]]
|
||||
|
||||
(when render-context-lost?
|
||||
[:div {:id "context-lost" :class (stl/css :context-lost)}
|
||||
[:h1 "GL Error Screen"]
|
||||
[:button
|
||||
{:on-click on-render-restore-context}
|
||||
"Restore context"]])]))
|
||||
:bottom-padding (when palete-size (+ palete-size 8))}]]]]]))
|
||||
|
|
|
@ -9,12 +9,10 @@
|
|||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.types.shape.impl]
|
||||
[app.common.types.shape.impl :as ctsi]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.main.data.render-wasm :as drw]
|
||||
[app.main.store :as st]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.object :as obj]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(def enabled?
|
||||
|
@ -23,7 +21,6 @@
|
|||
(set! app.common.types.shape.impl/enabled-wasm-ready-shape enabled?)
|
||||
|
||||
(defonce internal-module #js {})
|
||||
(defonce internal-gpu-state #js {})
|
||||
|
||||
;; TODO: remove the `take` once we have the dynamic data structure in Rust
|
||||
(def xform
|
||||
|
@ -31,49 +28,70 @@
|
|||
(remove cfh/root?)
|
||||
(take 2048)))
|
||||
|
||||
;; Size in number of f32 values that represents the shape selrect (
|
||||
(def rect-size 4)
|
||||
(defn create-shape
|
||||
[id]
|
||||
(let [buffer (uuid/uuid->u32 id)]
|
||||
(._create_shape ^js internal-module (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))))
|
||||
|
||||
(defn use-shape
|
||||
[id]
|
||||
(let [buffer (uuid/uuid->u32 id)]
|
||||
(._use_shape ^js internal-module (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))))
|
||||
|
||||
(defn set-shape-selrect
|
||||
[selrect]
|
||||
(let [x1 (:x1 selrect)
|
||||
y1 (:y1 selrect)
|
||||
x2 (:x2 selrect)
|
||||
y2 (:y2 selrect)]
|
||||
(._set_shape_selrect ^js internal-module x1 y1 x2 y2)))
|
||||
|
||||
(defn set-shape-transform
|
||||
[transform]
|
||||
(let [a (:a transform)
|
||||
b (:b transform)
|
||||
c (:c transform)
|
||||
d (:d transform)
|
||||
e (:e transform)
|
||||
f (:f transform)]
|
||||
(._set_shape_transform ^js internal-module a b c d e f)))
|
||||
|
||||
(defn set-shape-rotation
|
||||
[rotation]
|
||||
(._set_shape_rotation ^js internal-module rotation))
|
||||
|
||||
(defn set-shape-x
|
||||
[x]
|
||||
(._set_shape_x ^js internal-module x))
|
||||
|
||||
(defn set-shape-y
|
||||
[y]
|
||||
(._set_shape_y ^js internal-module y))
|
||||
|
||||
(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)]
|
||||
|
||||
(let [shapes (into [] xform (vals objects))
|
||||
total-shapes (count shapes)]
|
||||
(loop [index 0]
|
||||
(when (< index total-shapes)
|
||||
(let [shape (nth shapes index)]
|
||||
(.set ^js mem (.-buffer shape) (* index rect-size))
|
||||
(let [shape (nth shapes index)
|
||||
id (dm/get-prop shape :id)
|
||||
selrect (dm/get-prop shape :selrect)
|
||||
rotation (dm/get-prop shape :rotation)
|
||||
transform (dm/get-prop shape :transform)]
|
||||
(use-shape id)
|
||||
(set-shape-selrect selrect)
|
||||
(set-shape-rotation rotation)
|
||||
(set-shape-transform transform)
|
||||
(recur (inc index)))))))
|
||||
|
||||
(defn draw-objects
|
||||
[zoom vbox]
|
||||
(let [draw-all-shapes (unchecked-get internal-module "_draw_all_shapes")]
|
||||
(js/requestAnimationFrame
|
||||
(fn []
|
||||
(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))))))
|
||||
(js/requestAnimationFrame
|
||||
(fn []
|
||||
(let [pan-x (- (dm/get-prop vbox :x))
|
||||
pan-y (- (dm/get-prop vbox :y))]
|
||||
(._draw_all_shapes ^js internal-module zoom pan-x pan-y)))))
|
||||
|
||||
(defn cancel-draw
|
||||
[frame-id]
|
||||
|
@ -86,67 +104,28 @@
|
|||
:stencil true
|
||||
:alpha true})
|
||||
|
||||
(defn init-skia
|
||||
[canvas]
|
||||
(let [init-fn (unchecked-get internal-module "_init")
|
||||
state (init-fn (.-width ^js canvas)
|
||||
(.-height ^js canvas))]
|
||||
(set! internal-gpu-state state)))
|
||||
|
||||
;; NOTE: This function can be called externally
|
||||
;; by the button in the context lost component (shown
|
||||
;; in viewport-wasm) or called internally by
|
||||
;; on-webgl-context
|
||||
(defn restore-canvas
|
||||
[canvas]
|
||||
(st/emit! (drw/context-restored))
|
||||
;; We need to reinitialize skia when the
|
||||
;; context is restored.
|
||||
(init-skia canvas))
|
||||
|
||||
;; Handles both events: webglcontextlost and
|
||||
;; webglcontextrestored
|
||||
(defn on-webgl-context
|
||||
[event]
|
||||
(dom/prevent-default event)
|
||||
(if (= (.-type event) "webglcontextlost")
|
||||
(st/emit! (drw/context-lost))
|
||||
(restore-canvas (dom/get-target event))))
|
||||
|
||||
(defn dispose-canvas
|
||||
[canvas]
|
||||
(defn clear-canvas
|
||||
[]
|
||||
;; TODO: perform corresponding cleaning
|
||||
(.removeEventListener canvas "webglcontextlost" on-webgl-context)
|
||||
(.removeEventListener canvas "webglcontextrestored" on-webgl-context))
|
||||
)
|
||||
|
||||
(defn init-debug-webgl-context-state
|
||||
[context]
|
||||
(let [context-extension (.getExtension ^js context "WEBGL_lose_context")
|
||||
info-extension (.getExtension ^js context "WEBGL_debug_renderer_info")]
|
||||
(set! (.-penpotGL js/window) #js {:context context-extension
|
||||
:renderer info-extension})
|
||||
(js/console.log "WEBGL_lose_context" context-extension)
|
||||
(js/console.log "WEBGL_debug_renderer_info" info-extension)))
|
||||
|
||||
(defn setup-canvas
|
||||
(defn assign-canvas
|
||||
[canvas]
|
||||
(let [gl (unchecked-get internal-module "GL")
|
||||
init-fn (unchecked-get internal-module "_init")
|
||||
|
||||
context (.getContext ^js canvas "webgl2" canvas-options)
|
||||
|
||||
;; Register the context with emscripten
|
||||
handle (.registerContext ^js gl context #js {"majorVersion" 2})
|
||||
_ (.makeContextCurrent ^js gl handle)]
|
||||
|
||||
(when (dbg/enabled? :gl-context)
|
||||
(init-debug-webgl-context-state context))
|
||||
|
||||
(.addEventListener canvas "webglcontextlost" on-webgl-context)
|
||||
(.addEventListener canvas "webglcontextrestored" on-webgl-context)
|
||||
|
||||
handle (.registerContext ^js gl context #js {"majorVersion" 2})]
|
||||
(.makeContextCurrent ^js gl handle)
|
||||
;; Initialize Skia
|
||||
(init-fn (.-width ^js canvas)
|
||||
(.-height ^js canvas))
|
||||
(set! (.-width canvas) (.-clientWidth ^js canvas))
|
||||
(set! (.-height canvas) (.-clientHeight ^js canvas))
|
||||
|
||||
(init-skia canvas)))
|
||||
(obj/set! js/window "shape_list" (fn [] ((unchecked-get internal-module "_shape_list"))))))
|
||||
|
||||
(defonce module
|
||||
(->> (js/dynamicImport "/js/render_wasm.js")
|
||||
|
@ -159,3 +138,9 @@
|
|||
(p/merr (fn [cause]
|
||||
(js/console.error cause)
|
||||
(p/resolved false)))))
|
||||
|
||||
(set! app.common.types.shape.impl/wasm-create-shape create-shape)
|
||||
(set! app.common.types.shape.impl/wasm-use-shape use-shape)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-selrect set-shape-selrect)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-transform set-shape-transform)
|
||||
(set! app.common.types.shape.impl/wasm-set-shape-rotation set-shape-rotation)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue