diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index c909f1924..3dd63183f 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -26,6 +26,7 @@ [app.common.types.pages-list :as ctpl] [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctst] + [app.common.types.shape.impl :as shape.impl] [app.common.types.token :as cto] [app.common.types.token-theme :as ctot] [app.common.types.tokens-lib :as ctob] @@ -540,7 +541,7 @@ (when verify? (check-changes! items)) - (binding [*touched-changes* (volatile! #{})] + (binding [*touched-changes* (volatile! #{}) shape.impl/*wasm-sync* true] (let [result (reduce #(or (process-change %1 %2) %1) data items) result (reduce process-touched-change result @*touched-changes*)] ;; Validate result shapes (only on the backend) diff --git a/common/src/app/common/types/shape/impl.cljc b/common/src/app/common/types/shape/impl.cljc index dc6f92231..45a0f9e13 100644 --- a/common/src/app/common/types/shape/impl.cljc +++ b/common/src/app/common/types/shape/impl.cljc @@ -19,6 +19,7 @@ (defonce wasm-set-shape-selrect (constantly nil)) (defonce wasm-set-shape-transform (constantly nil)) (defonce wasm-set-shape-rotation (constantly nil)) +(defonce wasm-set-shapes (constantly nil)) (cr/defrecord Shape [id name type x y width height rotation selrect points transform transform-inverse parent-id frame-id flip-x flip-y]) @@ -113,9 +114,10 @@ (when *wasm-sync* (wasm-use-shape (:id coll)) (case k - :selrect (wasm-set-shape-selrect v) - :rotation (wasm-set-shape-rotation v) + :selrect (wasm-set-shape-selrect v) + :rotation (wasm-set-shape-rotation v) :transform (wasm-set-shape-transform v) + :shapes (wasm-set-shapes v) nil)) (let [delegate (.-delegate ^ShapeProxy coll) delegate' (assoc delegate k v)] diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index c13cd657f..0143cba50 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -283,10 +283,13 @@ (fn [] (render.wasm/clear-canvas)))) - (mf/with-effect [base-objects modifiers canvas-init?] + (mf/with-effect [base-objects canvas-init?] (when @canvas-init? - ;; FIXME: review this to not call it but still do the first draw - ;; (render.wasm/set-objects base-objects modifiers) + (render.wasm/set-objects base-objects) + (render.wasm/draw-objects zoom vbox))) + + (mf/with-effect [modifiers canvas-init?] + (when (and @canvas-init? modifiers) (render.wasm/draw-objects zoom vbox))) (mf/with-effect [vbox canvas-init?] diff --git a/frontend/src/app/render_wasm.cljs b/frontend/src/app/render_wasm.cljs index 424d3db8d..f954140ff 100644 --- a/frontend/src/app/render_wasm.cljs +++ b/frontend/src/app/render_wasm.cljs @@ -8,7 +8,6 @@ "A WASM based render API" (:require [app.common.data.macros :as dm] - [app.common.files.helpers :as cfh] [app.common.types.shape.impl :as ctsi] [app.common.uuid :as uuid] [app.config :as cf] @@ -25,7 +24,6 @@ ;; TODO: remove the `take` once we have the dynamic data structure in Rust (def xform (comp - (remove cfh/root?) (take 2048))) (defn create-shape @@ -60,13 +58,12 @@ [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-shapes + [shape_ids] + (._clear_child_shapes ^js internal-module) + (doseq [id shape_ids] + (let [buffer (uuid/uuid->u32 id)] + (._add_child_shape ^js internal-module (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))))) (defn set-objects [objects] @@ -78,11 +75,13 @@ id (dm/get-prop shape :id) selrect (dm/get-prop shape :selrect) rotation (dm/get-prop shape :rotation) - transform (dm/get-prop shape :transform)] + transform (dm/get-prop shape :transform) + children (dm/get-prop shape :shapes)] (use-shape id) (set-shape-selrect selrect) (set-shape-rotation rotation) (set-shape-transform transform) + (set-shapes children) (recur (inc index))))))) (defn draw-objects @@ -144,3 +143,4 @@ (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) +(set! app.common.types.shape.impl/wasm-set-shapes set-shapes) diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 423b6f8fb..5a427f05f 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -49,7 +49,7 @@ pub unsafe extern "C" fn draw_all_shapes(zoom: f32, pan_x: f32, pan_y: f32) { scale(zoom, zoom); translate(pan_x, pan_y); - render::render_all(state); + render::render_shape(state, Uuid::nil()); flush(); } @@ -125,26 +125,6 @@ pub unsafe extern "C" fn set_shape_rotation(rotation: f32) { } } -#[no_mangle] -pub unsafe extern "C" fn set_shape_x(x: f32) { - let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); - if let Some(shape) = state.current_shape.as_deref_mut() { - let width = shape.selrect.x2 - shape.selrect.x1; - shape.selrect.x1 = x; - shape.selrect.x2 = x + width; - } -} - -#[no_mangle] -pub unsafe extern "C" fn set_shape_y(y: f32) { - let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); - if let Some(shape) = state.current_shape.as_deref_mut() { - let height = shape.selrect.y2 - shape.selrect.y1; - shape.selrect.y1 = y; - shape.selrect.y2 = y + height; - } -} - #[no_mangle] pub unsafe extern "C" fn set_shape_transform(a: f32, b: f32, c: f32, d: f32, e: f32, f: f32) { let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); @@ -158,6 +138,23 @@ pub unsafe extern "C" fn set_shape_transform(a: f32, b: f32, c: f32, d: f32, e: } } +#[no_mangle] +pub extern "C" fn add_child_shape(a: u32, b: u32, c: u32, d: u32) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + let id = uuid_from_u32_quartet(a, b, c, d); + if let Some(shape) = state.current_shape.as_deref_mut() { + shape.shapes.push(id); + } +} + +#[no_mangle] +pub extern "C" fn clear_child_shapes() { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape.as_deref_mut() { + shape.shapes.clear(); + } +} + fn main() { render::init_gl(); } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 02a93ccf7..833b05c42 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1,5 +1,6 @@ use skia_safe as skia; use skia_safe::gpu::{self, gl::FramebufferInfo, DirectContext}; +use uuid::Uuid; use crate::state::State; @@ -81,34 +82,44 @@ pub(crate) fn render_rect(surface: &mut skia::Surface, rect: skia::Rect, color: surface.canvas().draw_rect(rect, &paint); } -pub(crate) fn render_all(state: &mut State) { - for shape in state.shapes.values() { - let r = skia::Rect::new( - shape.selrect.x1, - shape.selrect.y1, - shape.selrect.x2, - shape.selrect.y2, - ); +pub(crate) fn render_shape(state: &mut State, id: Uuid) { + let shape = state.shapes.get(&id).unwrap(); + let r = skia::Rect::new( + shape.selrect.x1, + shape.selrect.y1, + shape.selrect.x2, + shape.selrect.y2, + ); - state.render_state.surface.canvas().save(); + // TODO: check if this save and restore are really neaded or not + // state.render_state.surface.canvas().save(); - // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc - let mut matrix = skia::Matrix::new_identity(); - let (translate_x, translate_y) = shape.translation(); - let (scale_x, scale_y) = shape.scale(); - let (skew_x, skew_y) = shape.skew(); + // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc + let mut matrix = skia::Matrix::new_identity(); + let (translate_x, translate_y) = shape.translation(); + let (scale_x, scale_y) = shape.scale(); + let (skew_x, skew_y) = shape.skew(); - matrix.set_all(scale_x, skew_x, translate_x, skew_y, scale_y, translate_y, 0., 0., 1.); + matrix.set_all(scale_x, skew_x, translate_x, skew_y, scale_y, translate_y, 0., 0., 1.); - let mut center = r.center(); - matrix.post_translate(center); - center.negate(); - matrix.pre_translate(center); + let mut center = r.center(); + matrix.post_translate(center); + center.negate(); + matrix.pre_translate(center); - state.render_state.surface.canvas().concat(&matrix); + state.render_state.surface.canvas().concat(&matrix); - render_rect(&mut state.render_state.surface, r, skia::Color::RED); + let mut color = skia::Color::RED;; + if skew_x != 0. { + color = skia::Color::BLACK; + } + render_rect(&mut state.render_state.surface, r, color); - state.render_state.surface.canvas().restore(); + // state.render_state.surface.canvas().restore(); + + let shape_ids = shape.shapes.clone(); + + for shape_id in shape_ids { + render_shape(state, shape_id); } } diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index 8015aaf1b..38746d491 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -50,9 +50,10 @@ impl Matrix { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct Shape { pub id: Uuid, + pub shapes: Vec::, pub kind: Kind, pub selrect: Rect, pub transform: Matrix, @@ -63,6 +64,7 @@ impl Shape { pub fn new(id: Uuid) -> Self { Self { id, + shapes: Vec::::new(), kind: Kind::Rect, selrect: Rect::default(), transform: Matrix::identity(),