diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 7fefbd89b4..54dde7688d 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -159,6 +159,8 @@ (get base-objects parent-id))))) zoom (d/check-num zoom 1) + prev-zoom (mf/use-ref zoom) + drawing-tool (:tool drawing) drawing-obj (:object drawing) @@ -334,7 +336,8 @@ (mf/with-effect [vbox zoom] (when (and @canvas-init? initialized?) - (wasm.api/set-view-box zoom vbox))) + (wasm.api/set-view-box (mf/ref-val prev-zoom) zoom vbox)) + (mf/set-ref-val! prev-zoom zoom)) (mf/with-effect [background] (when (and @canvas-init? initialized?) diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index aacd9b5cba..ed66b69d9a 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -111,12 +111,6 @@ (aget buffer 3)) (set! wasm/internal-frame-id nil)))) -(def set-view-render - (fns/debounce - (fn [ts] - (h/call wasm/internal-module "_set_view_end") - (render ts)) - 200)) (defonce pending-render (atom false)) @@ -866,10 +860,24 @@ (:y position))] (= result 1))) +(def render-finish + (letfn [(do-render [ts] + (h/call wasm/internal-module "_set_view_end") + (render ts))] + (fns/debounce do-render 100))) + +(def render-pan + (fns/throttle render 10)) + (defn set-view-box - [zoom vbox] + [prev-zoom zoom vbox] (h/call wasm/internal-module "_set_view" zoom (- (:x vbox)) (- (:y vbox))) - (set-view-render)) + + (if (mth/close? prev-zoom zoom) + (do (render-pan) + (render-finish)) + (do (h/call wasm/internal-module "_render_from_cache" 0) + (render-finish)))) (defn set-object [objects shape] diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 18d2616988..3e19967a85 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -173,6 +173,7 @@ pub extern "C" fn render_sync_shape(a: u32, b: u32, c: u32, d: u32) { #[no_mangle] pub extern "C" fn render_from_cache(_: i32) { with_state_mut!(state, { + state.render_state.cancel_animation_frame(); state.render_from_cache(); }); } @@ -217,9 +218,7 @@ pub extern "C" fn resize_viewbox(width: i32, height: i32) { pub extern "C" fn set_view(zoom: f32, x: f32, y: f32) { with_state_mut!(state, { let render_state = state.render_state_mut(); - render_state.viewbox.set_all(zoom, x, y); - state.render_state.cancel_animation_frame(); - state.render_from_cache(); + render_state.set_view(zoom, x, y); }); } diff --git a/render-wasm/src/render.rs b/render-wasm/src/render.rs index 870a530222..d7fc7b30af 100644 --- a/render-wasm/src/render.rs +++ b/render-wasm/src/render.rs @@ -1199,8 +1199,8 @@ impl RenderState { let start_tile_y = (self.viewbox.area.top * scale / tiles::TILE_SIZE).floor() * tiles::TILE_SIZE; Rect::from_xywh( - (tile.0 as f32 * tiles::TILE_SIZE) - start_tile_x, - (tile.1 as f32 * tiles::TILE_SIZE) - start_tile_y, + (tile.x() as f32 * tiles::TILE_SIZE) - start_tile_x, + (tile.y() as f32 * tiles::TILE_SIZE) - start_tile_y, tiles::TILE_SIZE, tiles::TILE_SIZE, ) @@ -1781,6 +1781,7 @@ impl RenderState { // Cache target surface in a texture self.cached_viewbox = self.viewbox; + self.cached_target_snapshot = Some(self.surfaces.snapshot(SurfaceId::Cache)); if self.options.is_debug_visible() { @@ -1815,7 +1816,7 @@ impl RenderState { .get_tiles_of(shape.id) .map_or(Vec::new(), |tiles| tiles.iter().copied().collect()); - let new_tiles = (rsx..=rex).flat_map(|x| (rsy..=rey).map(move |y| tiles::Tile(x, y))); + let new_tiles = (rsx..=rex).flat_map(|x| (rsy..=rey).map(move |y| tiles::Tile::from(x, y))); let mut result = HashSet::::new(); @@ -1841,7 +1842,7 @@ impl RenderState { pub fn add_shape_tiles(&mut self, shape: &Shape, tree: ShapesPoolRef) -> Vec { let TileRect(rsx, rsy, rex, rey) = self.get_tiles_for_shape(shape, tree); let tiles: Vec<_> = (rsx..=rex) - .flat_map(|x| (rsy..=rey).map(move |y| tiles::Tile(x, y))) + .flat_map(|x| (rsy..=rey).map(move |y| tiles::Tile::from(x, y))) .collect(); for tile in tiles.iter() { @@ -1999,4 +2000,8 @@ impl RenderState { pub fn get_cached_extrect(&mut self, shape: &Shape, tree: ShapesPoolRef, scale: f32) -> Rect { shape.extrect(tree, scale) } + + pub fn set_view(&mut self, zoom: f32, x: f32, y: f32) { + self.viewbox.set_all(zoom, x, y); + } } diff --git a/render-wasm/src/render/debug.rs b/render-wasm/src/render/debug.rs index ff142337ec..0773fff4fc 100644 --- a/render-wasm/src/render/debug.rs +++ b/render-wasm/src/render/debug.rs @@ -139,7 +139,7 @@ pub fn render_workspace_current_tile( let tile_position_origin = skia::Point::new(rect.x() + 10., rect.y() + 20.); p.set_style(skia::PaintStyle::Fill); - let str = format!("{prefix} {}:{}", tile.0, tile.1); + let str = format!("{prefix} {}:{}", tile.x(), tile.y()); let mut debug_font = render_state.fonts.debug_font().clone(); debug_font.set_size(16.); canvas.draw_str(str, tile_position_origin, &debug_font, &p); diff --git a/render-wasm/src/tiles.rs b/render-wasm/src/tiles.rs index be7b056c26..eec43f8ba5 100644 --- a/render-wasm/src/tiles.rs +++ b/render-wasm/src/tiles.rs @@ -7,31 +7,63 @@ use std::collections::{HashMap, HashSet}; #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub struct Tile(pub i32, pub i32); +impl Tile { + pub fn from(x: i32, y: i32) -> Self { + Tile(x, y) + } + pub fn x(&self) -> i32 { + self.0 + } + pub fn y(&self) -> i32 { + self.1 + } +} + #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub struct TileRect(pub i32, pub i32, pub i32, pub i32); impl TileRect { + pub fn x1(&self) -> i32 { + self.0 + } + + pub fn y1(&self) -> i32 { + self.1 + } + + pub fn x2(&self) -> i32 { + self.2 + } + + pub fn y2(&self) -> i32 { + self.3 + } + pub fn width(&self) -> i32 { - self.2 - self.0 + self.x2() - self.x1() } pub fn height(&self) -> i32 { - self.3 - self.1 + self.y2() - self.y1() } pub fn center_x(&self) -> i32 { - self.0 + self.width() / 2 + self.x1() + self.width() / 2 } pub fn center_y(&self) -> i32 { - self.1 + self.height() / 2 + self.y1() + self.height() / 2 } pub fn contains(&self, tile: &Tile) -> bool { - tile.0 >= self.0 && tile.1 >= self.1 && tile.0 <= self.2 && tile.1 <= self.3 + tile.x() >= self.x1() + && tile.y() >= self.y1() + && tile.x() <= self.x2() + && tile.y() <= self.y2() } } +#[derive(Debug)] pub struct TileViewbox { pub visible_rect: TileRect, pub interest_rect: TileRect,