diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 30964d869..be4cc88fa 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -292,19 +292,23 @@ (when @canvas-init? (wasm.api/resize-viewbox (:width vport) (:height vport)))) - (mf/with-effect [base-objects @canvas-init?] + (mf/with-effect [@canvas-init? base-objects] (when @canvas-init? (wasm.api/set-objects base-objects))) - (mf/with-effect [preview-blend @canvas-init?] + (mf/with-effect [@canvas-init? preview-blend] (when (and @canvas-init? preview-blend) - (wasm.api/request-render))) + (wasm.api/request-render "with-effect"))) - (mf/with-effect [vbox @canvas-init?] + (mf/with-effect [@canvas-init? vbox] (when @canvas-init? - (wasm.api/set-view zoom vbox))) + (wasm.api/set-view-zoom zoom vbox))) - (mf/with-effect [background] + (mf/with-effect [@canvas-init? vbox] + (when @canvas-init? + (wasm.api/set-view-box zoom vbox))) + + (mf/with-effect [@canvas-init? background] (when @canvas-init? (wasm.api/set-canvas-background background))) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 8585e1e34..efbcc3376 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -61,15 +61,16 @@ [r g b a])) (defn cancel-render - [] + [_] (when internal-frame-id (js/cancelAnimationFrame internal-frame-id) (set! internal-frame-id nil))) (defn request-render - [] - (when internal-frame-id (cancel-render)) - (set! internal-frame-id (js/requestAnimationFrame render))) + [requester] + (when internal-frame-id (cancel-render requester)) + (let [frame-id (js/requestAnimationFrame render)] + (set! internal-frame-id frame-id))) (defn use-shape [id] @@ -386,10 +387,15 @@ (def debounce-render-without-cache (fns/debounce render-without-cache 100)) -(defn set-view +(defn set-view-box [zoom vbox] (h/call internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox))) - (h/call internal-module "_navigate") + (h/call internal-module "_pan")) + +(defn set-view-zoom + [zoom vbox] + (h/call internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox))) + (h/call internal-module "_zoom") (debounce-render-without-cache)) (defn set-objects @@ -441,7 +447,7 @@ (let [pending' (concat (set-shape-fills fills) (set-shape-strokes strokes))] (recur (inc index) (into pending pending')))) pending))] - (request-render) + (request-render "set-objects") (when-let [pending (seq pending)] (->> (rx/from pending) (rx/mapcat identity) diff --git a/frontend/src/app/render_wasm/shape.cljs b/frontend/src/app/render_wasm/shape.cljs index 08bba0a95..79d5ffffd 100644 --- a/frontend/src/app/render_wasm/shape.cljs +++ b/frontend/src/app/render_wasm/shape.cljs @@ -130,7 +130,7 @@ ;; when something synced with wasm ;; is modified, we need to request ;; a new render. - (api/request-render))) + (api/request-render "set-wasm-attrs"))) (defn- impl-assoc [self k v] diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 701768ef2..90bbc6852 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -70,9 +70,16 @@ pub unsafe extern "C" fn render_without_cache() { } #[no_mangle] -pub unsafe extern "C" fn navigate() { +pub unsafe extern "C" fn zoom() { + let state: &mut Box> = + unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + state.zoom(); +} + +#[no_mangle] +pub unsafe extern "C" fn pan() { let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); - state.navigate(); + state.pan(); } #[no_mangle] diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 0f9b1e90c..75716d0b0 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -36,9 +36,13 @@ pub(crate) struct CachedSurfaceImage { } impl CachedSurfaceImage { - fn is_dirty(&self, viewbox: &Viewbox) -> bool { + fn is_dirty_for_zooming(&mut self, viewbox: &Viewbox) -> bool { !self.has_all_shapes && !self.viewbox.area.contains(viewbox.area) } + + fn is_dirty_for_panning(&mut self, _viewbox: &Viewbox) -> bool { + !self.has_all_shapes + } } pub(crate) struct RenderState { @@ -168,9 +172,23 @@ impl RenderState { .clear(skia::Color::TRANSPARENT); } - pub fn navigate(&mut self, tree: &HashMap) -> Result<(), String> { - if let Some(cached_surface_image) = self.cached_surface_image.as_ref() { - if cached_surface_image.is_dirty(&self.viewbox) { + pub fn zoom(&mut self, tree: &HashMap) -> Result<(), String> { + if let Some(cached_surface_image) = self.cached_surface_image.as_mut() { + let is_dirty = cached_surface_image.is_dirty_for_zooming(&self.viewbox); + if is_dirty { + self.render_all(tree, true); + } else { + self.render_all_from_cache()?; + } + } + + Ok(()) + } + + pub fn pan(&mut self, tree: &HashMap) -> Result<(), String> { + if let Some(cached_surface_image) = self.cached_surface_image.as_mut() { + let is_dirty = cached_surface_image.is_dirty_for_panning(&self.viewbox); + if is_dirty { self.render_all(tree, true); } else { self.render_all_from_cache()?; @@ -192,6 +210,7 @@ impl RenderState { ); self.translate(self.viewbox.pan_x, self.viewbox.pan_y); + // Reset shape tree let is_complete = self.render_shape_tree(&Uuid::nil(), tree); if generate_cached_surface_image || self.cached_surface_image.is_none() { self.cached_surface_image = Some(CachedSurfaceImage { @@ -299,7 +318,7 @@ impl RenderState { if !root_id.is_nil() { if !element.bounds().intersects(self.viewbox.area) || element.hidden() { self.render_debug_element(element, false); - // TODO: This means that not all the shapes are renderer so we + // TODO: This means that not all the shapes are rendered so we // need to call a render_all on the zoom out. return is_complete; // TODO return is_complete or return false?? } else { diff --git a/render-wasm/src/shapes/rects.rs b/render-wasm/src/shapes/rects.rs new file mode 100644 index 000000000..e9a6b3fd8 --- /dev/null +++ b/render-wasm/src/shapes/rects.rs @@ -0,0 +1,6 @@ +use crate::math::Point; + +#[derive(Debug, Clone, PartialEq)] +pub struct Rect { + +} diff --git a/render-wasm/src/state.rs b/render-wasm/src/state.rs index dde967a0d..73e4df6cf 100644 --- a/render-wasm/src/state.rs +++ b/render-wasm/src/state.rs @@ -36,9 +36,14 @@ impl<'a> State<'a> { &mut self.render_state } - pub fn navigate(&mut self) { + pub fn pan(&mut self) { // TODO: propagate error to main fn - let _ = self.render_state.navigate(&self.shapes).unwrap(); + let _ = self.render_state.pan(&self.shapes).unwrap(); + } + + pub fn zoom(&mut self) { + // TODO: propagate error to main fn + let _ = self.render_state.zoom(&self.shapes).unwrap(); } pub fn render_all(&mut self, generate_cached_surface_image: bool) {